2013-07-19 16:54:10 +0000 2013-07-19 16:54:10 +0000
369
369

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

W dawnych czasach używaliśmy telnet, aby sprawdzić, czy port na zdalnym hoście jest otwarty: telnet hostname port próbowałby połączyć się z dowolnym portem na dowolnym hoście i dać dostęp do surowego strumienia TCP.

Obecnie systemy, nad którymi pracuję nie mają zainstalowanego telnetu (ze względów bezpieczeństwa), a wszystkie połączenia wychodzące do wszystkich hostów są domyślnie blokowane. Z czasem łatwo stracić informację, które porty są otwarte na które hosty.

Czy jest inny sposób na sprawdzenie, czy port w zdalnym systemie jest otwarty - używając systemu Linux z ograniczoną liczbą zainstalowanych pakietów, a telnet nie jest dostępny?

Odpowiedzi (13)

418
418
418
2013-12-03 21:34:41 +0000

Ładnie i gadatliwie! Na stronach man. Port pojedynczy:

nc -zv 127.0.0.1 80

Porty wielokrotne:

nc -zv 127.0.0.1 22 80 8080

Zakres portów:

nc -zv 127.0.0.1 20-30
297
297
297
2013-07-22 10:37:11 +0000

Bash przez pewien czas miał dostęp do portów TCP i UDP . Ze strony man:

/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.

Więc możesz 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!

104
104
104
2013-07-19 18:07:26 +0000

Netcat jest użytecznym narzędziem:

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

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

61
61
61
2014-09-02 17:59:36 +0000

Najprostsza metoda, bez użycia innego narzędzia, takiego jak socat, jest taka jak opisana w odpowiedzi @lornix powyżej. To jest po prostu dodanie aktualnego przykładu jak można by wykorzystać psuedo-urządzenie /dev/tcp/... w obrębie Basha, jeśli chciałoby się, powiedzmy, przetestować czy inny serwer ma dany port dostępny poprzez linię komend.

Przykłady

Powiedzmy, ż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 owinąć echo > /dev/... w nawiasy w ten sposób, (echo > /dev/...) jest to, że jeśli tego nie zrobisz, to przy testach połączeń, które są w dół, pojawią się tego typu komunikaty.

$ (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ć do /dev/null, ponieważ pochodzą z próby wypisania danych do urządzenia /dev/tcp. Przechwytujemy więc wszystkie te dane wyjściowe w ramach pod-polecenia, tj. (...cmds...) i przekierujemy dane wyjściowe pod-polecenia.

48
48
48
2013-07-19 17:05:30 +0000

Stwierdziłem, że curl może wykonać pracę w podobny sposób jak telnet, a curl powie nawet, jakiego protokołu oczekuje słuchacz.

Skonstruuj URI HTTP z nazwy hosta i portu jako pierwszy argument do curl. Jeśli curl może się połączyć, zgłosi niedopasowanie protokołu i zakończy pracę (jeśli listenener nie jest usługą WWW). Jeśli curl nie może się połączyć, to się skończy.

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

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

Jednakże, z innego systemu, port 5672 na hoście 10. 0.0.99 może być osiągnięty, i wydaje się, że jest uruchomiony słuchacz AMQP.

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

Ważne jest, aby rozróżnić różne komunikaty: pierwsza awaria była spowodowana tym, że curl nie mógł się połączyć z portem. Druga porażka to test powodzenia, choć curl spodziewał się, że zamiast słuchacza AMQP zostanie uruchomiony słuchacz HTTP.

13
13
13
2015-06-02 06:27:59 +0000
[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!

Hope it solves your problem :)

11
11
11
2016-03-16 11:21:40 +0000

Tutaj jest jedna linijka:

</dev/tcp/localhost/11211 && echo Port is open || echo Port is closed

przy użyciu składni Basha objaśnionej w @ odpowiedź @lornix .

Aby uzyskać więcej informacji, sprawdź: Advanced Bash-Scripting Guide: Chapter 29. /dev and /proc .

8
8
8
2017-05-31 08:45:09 +0000

Walczyłem przez cały dzień, ponieważ żadna z tych odpowiedzi nie wydawała się dla mnie skuteczna. Problem polega na tym, że najnowsza wersja nc nie ma już flagi -z, podczas gdy bezpośredni dostęp przez TCP (jak w @lornix i @slm) nie działa, gdy host nie jest osiągalny. W końcu znalazłem ta strona , gdzie w końcu znalazłem nie jeden, a two przykłady robocze:

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

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

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

6
6
6
2018-08-10 12:20:04 +0000

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

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

Kolejne podejście z curl do osiągnięcia dowolnego portu

curl telnet://127.0.0.1:22
4
4
4
2019-02-12 20:21:11 +0000

Oto funkcja, która wybierze jedną z metod w zależności od tego, co jest zainstalowane w Twoim 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
2
2
2013-07-19 17:01:16 +0000

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

1
1
1
2019-08-07 23:17:13 +0000

Dla porównania, rozwijając odpowiedź @peperunas:

sposób wykorzystania nmap do testu, to:

nmap -p 22 127.0.0.1

(przykład powyżej wykorzystuje localhost do celów demonstracyjnych)

0
0
0
2018-10-26 13:49:54 +0000

Jeśli musisz 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 zdefiniować swoje oczekiwanie

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

i przetestować je albo na lokalnych hostach albo na zdalnych hostach (połączenie przez ssh). Dla zdalnych testów 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 netcat jako proprosed powyżej …