it-swarm.com.de

Test, ob ein Port auf einem Remote-System erreichbar ist (ohne Telnet)

Früher haben wir telnet verwendet, um festzustellen, ob ein Port auf einem Remote-Host geöffnet war: telnet hostname port hat versucht, eine Verbindung zu einem beliebigen Port auf einem beliebigen Host herzustellen und Ihnen Zugriff auf den unformatierten Stream TCP zu gewähren.

In diesen Tagen ist auf den Systemen, auf denen ich arbeite, aus Sicherheitsgründen kein Telnet installiert, und alle ausgehenden Verbindungen zu allen Hosts werden standardmäßig blockiert. Mit der Zeit ist es leicht, den Überblick zu verlieren, welche Ports für welche Hosts geöffnet sind.

Gibt es eine andere Möglichkeit zu testen, ob ein Port auf einem Remote-System offen ist - unter Verwendung eines Linux-Systems mit einer begrenzten Anzahl installierter Pakete und telnet nicht verfügbar?

322
Steve HHH

Bash kann seit einiger Zeit auf TCP und UDP Ports zugreifen. Von der Manpage:

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

Sie könnten also so etwas verwenden:

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

Taa Daa!

261
lornix

Schön und ausführlich! Aus den Manpages.
Single Port:

nc -zv 127.0.0.1 80

Mehrere Ports:

nc -zv 127.0.0.1 22 80 8080

Reihe von Häfen:

nc -zv 127.0.0.1 20-30
373

Netcat ist ein nützliches Werkzeug:

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

Gibt 0 aus, wenn Port 123 offen ist, und 1, wenn er geschlossen ist.

100
thnee

Die einfachste Methode, ohne ein anderes Tool wie socat zu verwenden, ist die in der obigen Antwort von @ lornix beschriebene. Dies ist nur ein Beispiel dafür, wie man das psuedo-Gerät /dev/tcp/... in Bash verwenden würde, wenn man beispielsweise testen möchte, ob ein anderer Server über die Befehlszeile auf einen bestimmten Port zugreifen kann.

Beispiele

Angenommen, ich habe einen Host in meinem Netzwerk mit dem Namen 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

Der Grund, warum Sie den echo > /dev/... in Klammern wie diesen (echo > /dev/...) einschließen möchten, ist, dass bei Tests von Verbindungen, die nicht funktionieren, diese Nachrichtentypen angezeigt werden, wenn Sie dies nicht tun.

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

Diese können nicht einfach zu /dev/null umgeleitet werden, da sie aus dem Versuch stammen, Daten auf das Gerät /dev/tcp zu schreiben. Wir erfassen also die gesamte Ausgabe in einem Unterbefehl, d. H. (...cmds...), und leiten die Ausgabe des Unterbefehls um.

56
slm

Ich habe festgestellt, dass curl den Job möglicherweise auf ähnliche Weise erledigt wie telnet, und curl sagt Ihnen sogar, welches Protokoll der Listener erwartet.

Erstellen Sie einen HTTP-URI aus dem Hostnamen und dem Port als erstes Argument für curl. Wenn curl eine Verbindung herstellen kann, wird ein Protokollkonflikt gemeldet und beendet (wenn der Listener kein Webdienst ist). Wenn curl keine Verbindung herstellen kann, tritt eine Zeitüberschreitung auf.

Beispielsweise ist Port 5672 auf Host 10.0.0.99 entweder geschlossen oder von einer Firewall blockiert:

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

Von einem anderen System aus kann jedoch Port 5672 auf Host 10.0.0.99 erreicht werden, auf dem anscheinend ein AMQP-Listener ausgeführt wird.

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

Es ist wichtig, zwischen den verschiedenen Nachrichten zu unterscheiden: Der erste Fehler war, dass curl keine Verbindung zum Port herstellen konnte. Der zweite Fehler ist ein Erfolgstest, obwohl curl einen HTTP-Listener anstelle eines AMQP-Listeners erwartet.

41
Steve HHH
[[email protected] 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

[[email protected] 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!

Hoffe es löst dein Problem :)

Hier ist ein Einzeiler:

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

unter Verwendung der Bash-Syntax erklärt in @lornix answer .

Weitere Informationen finden Sie in: Advanced Bash-Scripting Guide: Kapitel 29. /dev und /proc .

9
kenorb

Ich hatte einen ganzen Tag zu kämpfen, weil keine dieser Antworten für mich zu funktionieren schien. Das Problem ist, dass die neueste Version von nc nicht mehr über das Flag -z verfügt, wohingegen der direkte Zugriff über TCP (gemäß @lornix und @slm) fehlschlägt, wenn der Host nicht erreichbar ist. Ich fand schließlich diese Seite , wo ich endlich nicht eine, sondern zwei Arbeitsbeispiele fand:

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

    (Das -w-Flag berücksichtigt die Zeitüberschreitung, und das </dev/null-Flag ersetzt das -z-Flag.)

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

    (Der Befehl timeout kümmert sich um die Zeitüberschreitung, der Rest stammt von @slm.)

Verwenden Sie dann einfach && und/oder || (oder sogar $?), um das Ergebnis zu extrahieren. Hoffentlich findet jemand diese Informationen nützlich.

6
Azukikuru

Es sollte nicht auf Ihrer Box verfügbar sein, aber versuchen Sie es mit nmap.

2
peperunas

Wenn Sie die Antworten von @kenorb und @Azukikuru kombinieren, können Sie den offenen/geschlossenen/Firewall-Port testen.

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

Ein weiterer Ansatz mit Curl zum Erreichen eines beliebigen Ports

curl telnet://127.0.0.1:22
1
Miguel Ferreira

Hier ist eine Funktion, die eine der Methoden auswählt, je nachdem, was auf Ihrem System installiert ist:

# 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
1
Robert Boyd

Wenn Sie mehr als nur ein System testen müssen, können Sie für solche Aufgaben unser Testtool dda-serverspec ( https://github.com/DomainDrivenArchitecture/dda-serverspec-crate ) verwenden. Sie können Ihre Erwartungen definieren

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

und testen Sie diese Erwartung entweder gegen localhost oder gegen Remote-Hosts (Verbindung über ssh). Für Ferntests müssen Sie Ziele definieren:

{: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"}}

Sie können den Test mit Java -jar dda-serverspec.jar --targets targets.edn serverspec.edn ausführen

Unter der Haube benutzen wir Netcat wie oben vorgeschlagen ...

0
jerger