Skutecznie przetestować, czy port jest otwarty w systemie Linux?

197

Jak ze skryptu bash mogę szybko dowiedzieć się, czy port 445jest otwarty / nasłuchuje na serwerze.

Wypróbowałem kilka opcji, ale chcę czegoś szybkiego:
1. lsof -i :445 (Zajmuje sekundy)
2. netstat -an |grep 445 |grep LISTEN(Zajmuje sekundy)
3. telnet(Nie zwraca)
4. nmap, netcatNie są dostępne na serwerze

Miło będzie wiedzieć o sposobie, który nie wylicza najpierw, a potem greps.

Aman Jain
źródło
1
Czy dostępny jest Netcat? Ma szybką ścieżkę awarii IIRC. netcat.sourceforge.net
JimR
5
netstat -lnt(zi -tbez -a) ograniczy wyjście tylko do nasłuchiwania połączeń TCP. Może trochę przyspieszyć. Możesz dodać -4dla IPv4 tylko wtedy, gdy nie potrzebujesz IPv6.
Bartosz Moczulski
lsof -i jest osobistym ulubieńcem.
Matt Joyce,
14
netstat -an | grep PORTNUMBER | grep -i listenJeśli dane wyjściowe są puste, port nie jest używany.
automatix
Nie wiem, dlaczego lsofjest dla ciebie powolny, ale zwykle jest to najlepsze z wymienionych rozwiązań. Twoje netstatrozwiązanie nie jest zbyt niezawodne (możesz zgadywać za każdym razem, gdy go używasz grep; w każdym razie zwraca wartość prawda, jeśli ktoś słucha np. 4450). telneti netcatfaktycznie próbujemy utworzyć połączenie, które nie zawsze jest tym, czego chcesz.
petersohn,

Odpowiedzi:

155

Niespodzianką, którą ostatnio odkryłem, jest to, że Bash natywnie obsługuje połączenia TCP jako deskryptory plików . Używać:

exec 6<>/dev/tcp/ip.addr.of.server/445
echo -e "GET / HTTP/1.0\n" >&6
cat <&6

Używam 6 jako deskryptora pliku, ponieważ 0,1,2 to stdin, stdout i stderr. 5 jest czasem używane przez Bash do procesów potomnych , więc 3,4,6,7,8 i 9 powinny być bezpieczne.

Zgodnie z komentarzem poniżej, aby przetestować nasłuchiwanie na serwerze lokalnym w skrypcie:

exec 6<>/dev/tcp/127.0.0.1/445 || echo "No one is listening!"
exec 6>&- # close output connection
exec 6<&- # close input connection

Aby ustalić, czy ktoś nasłuchuje, spróbuj połączyć się przez sprzężenie zwrotne. Jeśli to się nie powiedzie, port jest zamknięty lub nie mamy dostępu. Następnie zamknij połączenie.

Zmodyfikuj to dla swojego przypadku użycia, na przykład wysyłając wiadomość e-mail, wychodząc ze skryptu w przypadku awarii lub uruchamiając wymaganą usługę.

Spencer Rathbun
źródło
2
To właśnie dla mnie powieszono.
Aman Jain,
@AmanJain cat czeka na zakończenie EOF lub Ctrl-C. Musisz dostosować to do swojego protokołu. BTW, czy uruchamiasz to na zdalnym serwerze?
Spencer Rathbun,
Chcę osadzić kod sprawdzający port w skrypcie na serwerze pod /etc/init.d/
Aman Jain
@AmanJain Zaktualizowałem go dla systemu lokalnego. Chcesz tylko sprawdzić, czy słucha poprawnie? Nie ma żadnego sprawdzania protokołu, takiego jak żądanie strony przez http?
Spencer Rathbun
1
To nie jest niezawodna metoda, ponieważ nie wszystkie systemy operacyjne (np. Ubuntu 16, jak dzisiaj odkryłem) są dostarczane z bash skompilowanym do budowy /dev/tcp/IP/PORTdrzewa
dyasny 18.04.19
107

„Krótka odpowiedź” jest tutaj bardzo krótka: Jak sprawdzić, czy zdalny port TCP jest otwarty ze skryptu Shell?

nc -z <host> <port>; echo $?

Używam go z 127.0.0.1 jako „zdalny” adres.

zwraca to „0”, jeśli port jest otwarty, i „1”, jeśli port jest zamknięty

na przykład

nc -z 127.0.0.1 80; echo $?

-z Określa, że ​​nc powinien po prostu skanować w poszukiwaniu demonów nasłuchujących, bez wysyłania do nich żadnych danych. Błędem jest użycie tej opcji w połączeniu z opcją -l.

czarny
źródło
2
To chyba najłatwiejszy sposób, dzięki. Przykładowy link do skryptu już nie działa, ale i tak sam się wyjaśnia.
derFunk
Miły! Jest to o wiele szybsze niż w przypadku innych odpowiedzi na serwerze z otwartymi wieloma portami. Zwraca za <0,01 sekundy dla mnie, podczas gdy netstat / lsof zajmuje 1s +
Tim
2
Flaga -z nie jest dostępna w ncat opartym na nmap, który ostatnio dystrybuuje z: Fedorą, Centos itp. (Nmap-ncat-6.01-9.fc18.x86_64)
Zack
9
Wbrew intuicji zwraca to „0”, jeśli port jest otwarty, i „1”, jeśli port jest zamknięty.
Sean
3
@Sean uniksowe polecenia zwykle zwracają „0”, aby wskazać powodzenie, a niezerowe w przypadku niepowodzenia. Zatem „0” oznacza, że ​​połączenie się powiodło i niezerowe, że z jakiegoś powodu nie udało się połączyć. Zauważ jednak, że niektóre wersje „nc” nie obsługują argumentu „-z”, więc stackoverflow.com/a/25793128/6773916 jest prawdopodobnie lepszym rozwiązaniem.
Rich Sedman
89

Możesz użyć netstat w ten sposób, aby uzyskać znacznie szybsze wyniki:

W systemie Linux:

netstat -lnt | awk '$6 == "LISTEN" && $4 ~ /\.445$/'

Na komputerze Mac:

netstat -anp tcp | awk '$6 == "LISTEN" && $4 ~ /\.445$/'

Spowoduje to wyświetlenie listy procesów nasłuchujących na porcie (445 w tym przykładzie) lub nie wyprowadzi niczego, jeśli port będzie wolny.

anubhava
źródło
1
twoja składnia netstat jest niepoprawna. netstat -ln --tcp działa, ale nadal działa wolno
Aman Jain
6
Właściwie jest to poprawna składnia, ale prawdopodobnie używasz Linuksa, a ja jestem na Macu. W systemie Linux użyj tego:netstat -lnt | awk '$6 == "LISTEN" && $4 ~ ".445"'
anubhava
21
to nic nie dało.
Jürgen Paul
1
Pytanie dotyczyło jednak Linuksa, więc być może komentarz powinien znaleźć się w odpowiedzi.
UpTheCreek,
1
Aby sprawdzić port 80, musiałem użyć awk '$6 == "LISTEN" && $4 ~ "80$"'. Zamiast sprawdzać kropkę przed numerem portu \.80, użyłem 80$. W przeciwnym razie, to również pasowało do adresów IP zawierających .80i portów zaczynających się od 80takich jak 8000.
Patrick Oscity,
37

Możesz do tego użyć netcat.

nc ip port < /dev/null

łączy się z serwerem i ponownie bezpośrednio zamyka połączenie. Jeśli netcat nie może się połączyć, zwraca niezerowy kod wyjścia. Kod wyjścia jest przechowywany w zmiennej $ ?. Jako przykład,

nc ip port < /dev/null; echo $?

zwróci 0 wtedy i tylko wtedy, gdy netcat może pomyślnie połączyć się z portem.

Tony
źródło
1
Ta odpowiedź wymaga więcej głosów pozytywnych. nc działa idealnie w tym przypadku. trik / dev / tcp jest sprytny, ale wydaje się trudny do wdrożenia skryptu z przerwaniami sygnału.
Avindra Goolcharan
5
ncma w -ztym celu flagę, która nie wymaga pobierania danych wejściowych /dev/null. Odpowiedź już jest za pomocą -zpowyższej flagi.
Abe Voelker,
2
@AbeVoelker Nie wszystkie wersje nc obsługują flagę -z. Korzystam z CentOS 7 i znalazłem rozwiązanie Tony'ego, którego potrzebowałem.
Shadoninja,
@Shadoninja Dobrze wiedzieć! Gdybym mógł edytować błąd w swoim komentarzu z 2014 roku, zrobiłbym to.
Abe Voelker,
„nc” nie obsługuje już „-z”, więc ta odpowiedź wydaje się najlepszym rozwiązaniem.
Rich Sedman
18

Na podstawie odpowiedzi Spencera Rathbuna, używając bash:

true &>/dev/null </dev/tcp/127.0.0.1/$PORT && echo open || echo closed
użytkownik1338062
źródło
Dobrze, pominie komunikat „Odmowa połączenia”. Automatyczne wyjście, jeśli usługa zaakceptuje połączenie bez czekania na zawsze.
Seff
Najlepsze rozwiązanie dla usług, które nie wysyłają danych po nowym połączeniu. Około 20 razy szybciej niż wywołanie netcat. Może być skrócony do: &>/dev/null </dev/tcp/127.0.0.1/$PORT
ens
16

są wymienione w / proc / net / tcp.

jest to druga kolumna, po „:”, szesnastkowo:

> cat /proc/net/tcp
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode                                                     
   0: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 10863 1 ffff88020c785400 99 0 0 10 -1                     
   1: 0100007F:0277 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 7983 1 ffff88020eb7b3c0 99 0 0 10 -1                      
   2: 0500010A:948F 0900010A:2328 01 00000000:00000000 02:00000576 00000000  1000        0 10562454 2 ffff88010040f7c0 22 3 30 5 3                   
   3: 0500010A:E077 5F2F7D4A:0050 01 00000000:00000000 02:00000176 00000000  1000        0 10701021 2 ffff880100474080 41 3 22 10 -1                 
   4: 0500010A:8773 16EC97D1:0050 01 00000000:00000000 02:00000BDC 00000000  1000        0 10700849 2 ffff880104335440 57 3 18 10 -1                 
   5: 0500010A:8772 16EC97D1:0050 01 00000000:00000000 02:00000BF5 00000000  1000        0 10698952 2 ffff88010040e440 46 3 0 10 -1                  
   6: 0500010A:DD2C 0900010A:0016 01 00000000:00000000 02:0006E764 00000000  1000        0 9562907 2 ffff880104334740 22 3 30 5 4                    
   7: 0500010A:AAA4 6A717D4A:0050 08 00000000:00000001 02:00000929 00000000  1000        0 10696677 2 ffff880106cc77c0 45 3 0 10 -1  

więc chyba jedna z tych :50w trzeciej kolumnie musi być nakładaniem stosu: o)

poszukaj man 5 procwięcej szczegółów. i wybieranie tego osobno za pomocą sed itp. jest ćwiczeniem dla delikatnego czytelnika ...

Andrzej Cooke
źródło
10
ss -tl4 '( sport = :22 )'

2ms jest wystarczająco szybki?

Dodaj dwukropek, a to działa w systemie Linux

leucos
źródło
2
Świetny, ssjest nawet odrobinę szybszy niż nc. ljest do słuchania , 4jest dla IPv4; sportoznacza (oczywiście) port źródłowy . Powyższe polecenie zakłada nasłuchiwanie portu TCP ( topcja): użyj uopcji dla UDP lub żadnego z nich dla obu protokołów. Więcej informacji na sstemat Nixcraft jak zawsze . UWAGA: ssfiltry tutaj nie działają, nie wiem dlaczego (bash 4.3.11, narzędzie ss, iproute2-ss131122), muszą iść z grep .
Campa,
Szkoda, że ​​to sspolecenie nie zwraca kodu wyjścia odzwierciedlającego jego znalezienie; zawsze zwraca 0 kod wyjścia.
John Greene,
| grep LISTEN?
leucos
Rozumiem State Recv-Q Send-Q Local Address:Port Peer Address:Porti teraz? Co to znaczy?
Czarny
6

Oto jeden, który działa zarówno na Macu, jak i Linuksie:

netstat -aln | awk '$6 == "LISTEN" && $4 ~ "[\\.\:]445$"'
Artur Bodera
źródło
Myślę, że możesz bezpiecznie usunąć [\\.\:].
Patrick Oscity,
6
nc -l 8000

Gdzie 8000 to numer portu. Jeśli port jest wolny, uruchomi serwer, który można łatwo zamknąć. Jeśli nie, zgłosi błąd:

nc: Address already in use
Jose Enrique
źródło
5

Chciałem sprawdzić, czy port jest otwarty na jednym z naszych testowych serwerów linuxowych. Byłem w stanie to zrobić, próbując połączyć się z telnetem z mojej maszyny deweloperskiej do serwera testowego. Na komputerze dewelopera spróbuj uruchomić:

$ telnet test2.host.com 8080
Trying 05.066.137.184...
Connected to test2.host.com

W tym przykładzie chcę sprawdzić, czy port 8080 jest otwarty na hoście test2.host.com

razvang
źródło
1

tcping to świetne narzędzie z bardzo niskim narzutem, a także posiada argument limitu czasu, aby przyspieszyć:

[root@centos_f831dfb3 ~]# tcping 10.86.151.175 22 -t 1
10.86.151.175 port 22 open.
[root@centos_f831dfb3 ~]# tcping 10.86.150.194 22 -t 1
10.86.150.194 port 22 user timeout.
[root@centos_f831dfb3 ~]# tcping 1.1.1.1 22 -t 1
1.1.1.1 port 22 closed.
Payam
źródło
1
Nie jestem pewien, czy tcping jest wart instalacji, gdy rozwiązanie Spencera nie wymaga dodatkowych instalacji, ale jest to zdecydowanie najczystsze i najbardziej czytelne dla człowieka rozwiązanie.
bdombro
1

Możesz także użyć polecenia netcat

[location of netcat]/netcat -zv [ip] [port]

lub

nc -zv [ip] [port]

-z - ustawia nc, aby po prostu skanował w poszukiwaniu demonów nasłuchujących, bez wysyłania do nich żadnych danych.
-v - włącza pełny tryb.

Saurabh
źródło
-2

nmapjest właściwym narzędziem. Po prostu użyjnmap example.com -p 80

Możesz go użyć z lokalnego lub zdalnego serwera. Pomaga także określić, czy zapora blokuje dostęp.

zainengineer
źródło
-4

Jeśli używasz iptables, spróbuj:

iptables -nL

lub

iptables -nL | grep 445
Noz
źródło
to tylko lista reguł iptables ... które mogą nie mieć korelacji z otwartymi portami.
David Goodwin