Sprawdź, czy port w systemie zdalnym jest osiągalny (bez telnet)


353

W dawnych czasach telnetsprawdzaliśmy, czy port na zdalnym hoście był otwarty: telnet hostname portpróbował połączyć się z dowolnym portem na dowolnym hoście i dać ci dostęp do surowego strumienia TCP.

Obecnie w systemach, na których pracuję, nie ma zainstalowanego Telnet (ze względów bezpieczeństwa), a wszystkie połączenia wychodzące do wszystkich hostów są domyślnie blokowane. Z czasem łatwo stracić orientację, które porty są otwarte dla których hostów.

Czy istnieje inny sposób sprawdzenia, czy port w systemie zdalnym jest otwarty - przy użyciu systemu Linux z zainstalowaną ograniczoną liczbą pakietów i telnetnie jest dostępny?



Miałem ten sam problem. Odpowiedź @Subhranath Chunder poniżej pomogła. Jednak później dowiedziałem się, że instalacja Telnetu była niewielką sprawą brew install telnet. Spodziewam się, że użytkownicy Linuxa mogą zrobić to samo z yumi apt-get.
Mig82

Odpowiedzi:


277

Bash od dłuższego czasu ma dostęp do portów TCP i UDP . Ze strony podręcznika:

/dev/tcp/host/port
    If host is a valid hostname or Internet address, and port is an integer port number
    or service name, bash attempts to open a TCP connection to the corresponding socket.
/dev/udp/host/port
    If host is a valid hostname or Internet address, and port is an integer port number
    or service name, bash attempts to open a UDP connection to the corresponding socket.

Możesz więc użyć czegoś takiego:

xenon-lornix:~> cat < /dev/tcp/127.0.0.1/22
SSH-2.0-OpenSSH_6.2p2 Debian-6
^C pressed here

Taa Daa!


Wydaje się, że działa to również w MinGW . Na przykład zdalny serwer VNC na 192.168.2.100 odpowiada „RFB 003.008”, używając „cat </dev/tcp/192.168.2.100/5900”.
Peter Mortensen

1
@lornix, ok, ale w tym przypadku muszę uzyskać ten sam wynik z użyciem nc bez opcji -z, ale nadal nie działa: # nc -v -w5 127.0.0.1 18080 Połączenie z portem 127.0.0.1 18080 [tcp / *] się udało! # cat </dev/tcp/127.0.0.1/18080 Po prostu zawiesza się bez żadnego wyniku. Chcę tylko zrozumieć, kiedy mogę użyć opcji „/ dev / tcp / host / port”
Alexandr

5
@Alexandr ... właściwie „zawiesza się bez żadnego rezultatu” to zachowanie, którego się prawie spodziewałem. kot czeka na dane wejściowe. nc ma dodatkowe inteligentne funkcje umożliwiające wykrywanie braku danych w toku i przestaje próbować. kot nie jest tak mądry. Spróbuj cat < /dev/tcp/localhost/22, powinieneś dostać swój nagłówek sshd. Najwyraźniej twój proces na porcie 18080 czeka na coś przed wejściem. Port 22 ( ssh ) wita Cię swoją wersją i tym podobne. Wypróbuj to!
lornix

1
@lornix, dziękuję bardzo za wyjaśnienie! Teraz ograniczenie jest jasne. Myślę, że używanie nc powinno być preferowanym sposobem sprawdzania portów.
Alexandr

2
Było to niezwykle pomocne podczas pracy z kontenerem dokującym, w którym nic nie zainstalowano. Był w stanie szybko sprawdzić, czy kontener miał dostęp do DB bez konteneryzacji przez DNS. Przykład: cat </ dev / tcp / hostname / 5432
Michael Hobbs

404

Miły i pełny! Ze stron podręcznika.
Pojedynczy port:

nc -zv 127.0.0.1 80

Wiele portów:

nc -zv 127.0.0.1 22 80 8080

Zakres portów:

nc -zv 127.0.0.1 20-30

6
Dzięki, to chyba najlepsza odpowiedź. ;-)
lpapp

6
Zostało zawieszone, gdy wypróbowano na Ubuntu 14.04 (Trusty Tahr) dla zdalnego serwera (ta sama sieć LAN) dla zamkniętych portów (upłynął limit czasu po 127 sekundach) - w związku z tym nie jest to bardzo przydatne w skryptach. Działa to jednak w przypadku usługi z otwartym portem. Rozwiązaniem może być opcja „-w2”.
Peter Mortensen

6
Użyj opcji -u dla portów UDP.
Efren

8
W wersji 6.4 programu ncat -z nie jest rozpoznawany. Byłem w stanie obejść się bez z
smishra

5
Możesz sprawdzić wiele zakresów za pomocą: nc -zv 127.0.0.1 22,80,8080,20-30,443-446(wersja nc: 1.107-4).
bobbel

102

Netcat to przydatne narzędzie:

nc 127.0.0.1 123 &> /dev/null; echo $?

Wyjdzie, 0jeśli port 123 jest otwarty i 1jeśli jest zamknięty.


To jest o wiele bardziej elegancka i skryptowalna odpowiedź niż moja własna. Dla mnie niefortunne jest to, że świadomi bezpieczeństwa sysadmini, którzy odmówili, telnetrównież odmówili nc(choć - o dziwo - nie curllub wget).
Steve HHH,

Tak, to jest całkowicie arbitralne i głupie.
wtorek,

3
Niech FORzaczną się oświadczenia!
Chad Harrison

1
Zostało zawieszone, gdy wypróbowano na Ubuntu 14.04 (Trusty Tahr) dla zdalnego serwera (ta sama sieć LAN) dla zamkniętych portów (upłynął limit czasu po około 127 sekundach) - dlatego nie jest bardzo odpowiednie w skryptach. Działa to jednak w przypadku usługi, która ma otwarty port, zwracając wartość 0. Użycie opcji „-w2” może być rozwiązaniem.
Peter Mortensen

1
Myślę, -G 2że bardziej odpowiednie byłoby przekroczenie limitu czasu TCP
AB

58

Najprostsza metoda bez użycia innego narzędzia, takiego jak socat, jest opisana w powyższej odpowiedzi @ lornix. To po prostu dodać faktyczny przykład wykorzystania urządzenia psuedo /dev/tcp/...w Bash, jeśli chcesz, powiedzmy, przetestować, czy inny serwer ma dany port dostępny za pośrednictwem wiersza poleceń.

Przykłady

Powiedz, że mam hosta w mojej sieci o nazwie skinner.

$ (echo > /dev/tcp/skinner/22) >/dev/null 2>&1 \
    && echo "It's up" || echo "It's down"
It's up

$ (echo > /dev/tcp/skinner/222) >/dev/null 2>&1 && \
    echo "It's up" || echo "It's down"
It's down

Powodem, dla którego chcesz zawijać echo > /dev/...nawiasy w ten sposób, (echo > /dev/...)jest to, że jeśli tego nie zrobisz, to przy testach połączeń, które nie działają, pojawią się tego rodzaju wiadomości.

$ (echo > /dev/tcp/skinner/223) && echo hi
bash: connect: Connection refused
bash: /dev/tcp/skinner/223: Connection refused

Nie można ich po prostu przekierować, /dev/nullponieważ pochodzą one z próby zapisania danych na urządzeniu /dev/tcp. Przechwytujemy więc wszystkie dane wyjściowe w ramach podrzędnego polecenia, tj. (...cmds...)I przekierowujemy dane wyjściowe tego polecenia.


To jest wspaniałe. Żałuję, że nie zagłosuje na szczycie. Przeczytałem tylko tę stronę, ponieważ przypadkowo przewinąłem ją przed zamknięciem.
Still.Tony

@ Okuma.Tony - tak, to zawsze jest problem z Q, które mają wiele odpowiedzi 8-). Dziękujemy za opinie, ale to doceniamy.
slm

46

Odkryłem, że curlmoże to zrobić zadanie w podobny sposób telnet, a curlnawet powie ci, jakiego protokołu oczekuje słuchacz.

Skonstruuj identyfikator URI HTTP z nazwy hosta i portu jako pierwszy argument curl. Jeśli curlmożna się połączyć, zgłosi niezgodność protokołu i zakończy działanie (jeśli nasłuchiwanie nie jest usługą internetową). Jeśli curlnie można się połączyć, upłynie limit czasu.

Na przykład port 5672 na hoście 10.0.0.99 jest zamknięty lub zablokowany przez zaporę:

$ curl http://10.0.0.99:5672
curl: (7) couldn't connect to host

Jednak z innego systemu można uzyskać dostęp do portu 5672 na hoście 10.0.0.99 i wydaje się, że działa on jako detektor AMQP.

$ curl http://10.0.0.99:5672
curl: (56) Failure when receiving data from the peer
AMQP

Ważne jest, aby rozróżniać różne komunikaty: pierwsza awaria była spowodowana brakiem curlpołączenia z portem. Druga porażka to test powodzenia, choć curloczekiwany jest odbiornik HTTP zamiast odbiornika AMQP.


5
Jeśli curl nie jest dostępny, może być wget. wget -qS -O- http://ip.add.re.ss:portpowinien skutecznie zrobić to samo.
CVn

4
Działa to nawet z nazwą hosta, np. curl myhost:22.
에이 바

To może być niepoprawne. Mam uruchomioną usługę tomcat, ale pojawia się błąd 404. # curl -k 192.168.194.4:6443 <html><head> <title> Apache Tomcat / 7.0.34 - Raport błędów </title> <style> <! - H1 --- HR {kolor: # 525D76;} -> </style> </head><body> <h1> Status HTTP 404 - / </h1> <HR size = "1" noshade = "noshade"> <p> <b> typ </b> Raport o stanie </p> <p> <b> komunikat </b> <u>/</u></p><p> <b> opis </b> <u> Żądany zasób jest niedostępny. </u> </p> <HR size = "1" noshade = "noshade"> <h3> Apache Tomcat / 7.0.34 </h3> </body> </html>

Zobacz mój post z podobnym podejściem.
kenorb

12
[admin@automation-server 1.2.2]# nc -v -z -w2 192.168.193.173 6443
nc: connect to 192.168.193.173 port 6443 (tcp) failed: Connection refused

[admin@automation-server 1.2.2]# nc -v -z -w2 192.168.194.4 6443
Connection to 192.168.194.4 6443 port [tcp/sun-sr-https] succeeded!

Mam nadzieję, że to rozwiąże twój problem :)


1
Tak, jest to lepsze - prawie natychmiast upływa limit czasu dla zamkniętych portów.
Peter Mortensen

1
Czy to zawsze używa TCP, czy jest sposób, aby sprawdzić UDP?
kmoe


6

Walczyłem cały dzień, ponieważ żadna z tych odpowiedzi nie działała dla mnie. Problem polega na tym, że najnowsza wersja ncnie ma już -zflagi, podczas gdy bezpośredni dostęp przez TCP (zgodnie z @lornix i @slm) nie działa, gdy host jest nieosiągalny. W końcu znalazłem tę stronę , na której w końcu znalazłem nie jeden, ale dwa działające przykłady:

  1. nc -w1 127.0.0.1 22 </dev/null

    ( -wflaga ustala limit czasu i </dev/nullzastępuje -zflagę)

  2. timeout 1 bash -c '(echo > /dev/tcp/127.0.0.1/22) >/dev/null 2>&1'

    ( timeoutpolecenie zajmuje limit czasu, a reszta pochodzi z @slm)

Następnie po prostu użyj &&i / lub ||(lub nawet $?), aby wyodrębnić wynik. Mam nadzieję, że ktoś uzna te informacje za przydatne.


4

Łącząc odpowiedzi z @kenorb i @Azukikuru, możesz przetestować port otwarty / zamknięty / firewalled.

timeout 1 bash -c '</dev/tcp/127.0.0.1/22 && echo Port is open || echo Port is closed' || echo Connection timeout

Inne podejście z zawinięciem do osiągnięcia dowolnego portu

curl telnet://127.0.0.1:22

3

Oto funkcja, która wybierze jedną z metod w zależności od tego, co jest zainstalowane w systemie:

# Check_port <address> <port> 
check_port() {
if [ "$(which nc)" != "" ]; then 
    tool=nc
elif [ "$(which curl)" != "" ]; then
     tool=curl
elif [ "$(which telnet)" != "" ]; then
     tool=telnet
elif [ -e /dev/tcp ]; then
      if [ "$(which gtimeout)" != "" ]; then  
       tool=gtimeout
      elif [ "$(which timeout)" != "" ]; then  
       tool=timeout
      else
       tool=devtcp
      fi
fi
echo "Using $tool to test access to $1:$2"
case $tool in
nc) nc -v -G 5 -z -w2 $1 $2 ;;
curl) curl --connect-timeout 10 http://$1:$2 ;;
telnet) telnet $1 $2 ;;
gtimeout)  gtimeout 1 bash -c "</dev/tcp/${1}/${2} && echo Port is open || echo Port is closed" || echo Connection timeout ;;
timeout)  timeout 1 bash -c "</dev/tcp/${1}/${2} && echo Port is open || echo Port is closed" || echo Connection timeout ;;
devtcp)  </dev/tcp/${1}/${2} && echo Port is open || echo Port is closed ;;
*) echo "no tools available to test $1 port $2";;
esac

}
export check_port

2

Nie powinno być dostępne na twoim pudełku, ale spróbuj nmap.


4
nmapjest dobrym narzędziem, ale niedostępnym w tych systemach. Zamiast pobierać nmap, kompilować, instalować w moim katalogu domowym, a następnie kopiować do wszystkich innych systemów, miałem nadzieję znaleźć sposób, korzystając z istniejących narzędzi dostępnych w większości instalacji Linuksa.
Steve HHH,

1

dla odniesienia, rozwijając odpowiedź @peperunas:

sposobem użycia nmap do testowania jest:

nmap -p 22 127.0.0.1

(powyższy przykład używa localhost do celów demonstracyjnych)


0

Jeśli chcesz przetestować więcej niż na systemie, możesz użyć naszego narzędzia testowego dda-serverspec ( https://github.com/DomainDrivenArchitecture/dda-serverspec-crate ) do takich zadań. Możesz określić swoje oczekiwania

{:netcat [{:host "mywebserver.com" :port "443"}
          {:host "telnet mywebserver.com" :port "80"}
          {:host "telnet mywebserver.com" :port "8443"}]}

i przetestuj te oczekiwania na hoście lokalnym lub na hoście zdalnym (połącz przez ssh). W przypadku testów zdalnych musisz zdefiniować cele:

{:existing [{:node-name "test-vm1"
             :node-ip "35.157.19.218"}
            {:node-name "test-vm2"
             :node-ip "18.194.113.138"}]
 :provisioning-user {:login "ubuntu"}}

Możesz uruchomić test z java -jar dda-serverspec.jar --targets targets.edn serverspec.edn

Pod maską używamy netcata tak jak wyżej ...

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.