Effizient testen, ob ein Port unter Linux offen ist?

197

Wie kann ich anhand eines Bash-Skripts schnell herausfinden, ob ein Port 445auf einem Server geöffnet ist / lauscht.

Ich habe ein paar Optionen ausprobiert, aber ich möchte etwas schnell:
1. lsof -i :445 (Dauert Sekunden)
2. netstat -an |grep 445 |grep LISTEN(Dauert Sekunden)
3. telnet(es gibt nicht)
4. nmap, netcatsind auf dem Server nicht verfügbar

Es wird schön sein, einen Weg zu kennen, der nicht zuerst aufzählt und danach greift.

Aman Jain
quelle
1
Ist Netcat verfügbar? Es hat einen schnellen Fehlerpfad IIRC. netcat.sourceforge.net
JimR
5
netstat -lnt(mit -tund ohne -a) beschränkt die Ausgabe nur auf abhörende TCP-Verbindungen. Es kann sich etwas beschleunigen. Sie können -4IPv4 nur hinzufügen, wenn Sie IPv6 nicht benötigen.
Bartosz Moczulski
lsof -i ist ein persönlicher Favorit.
Matt Joyce
14
netstat -an | grep PORTNUMBER | grep -i listenWenn die Ausgabe leer ist, wird der Port nicht verwendet.
Automatix
Ich weiß nicht, warum lsofes für Sie langsam ist, aber normalerweise ist es die beste der von Ihnen aufgelisteten Lösungen. Ihre netstatLösung ist nicht sehr zuverlässig (Sie können sie bei jeder Verwendung erraten grep; sie gibt ohnehin true zurück, wenn jemand z. B. 4450 zuhört). telnetund netcattatsächlich versuchen, eine Verbindung herzustellen, die möglicherweise nicht immer das ist, was Sie wollen.
Petersohn

Antworten:

154

Eine Überraschung, die ich kürzlich herausgefunden habe, ist, dass Bash TCP-Verbindungen nativ als Dateideskriptoren unterstützt . Benutzen:

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

Ich verwende 6 als Dateideskriptor, weil 0,1,2 stdin, stdout und stderr sind. 5 wird manchmal von Bash für untergeordnete Prozesse verwendet , daher sollten 3,4,6,7,8 und 9 sicher sein.

So testen Sie den Kommentar auf einem lokalen Server in einem Skript:

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

Versuchen Sie, eine Verbindung per Loopback herzustellen, um festzustellen, ob jemand zuhört. Wenn dies fehlschlägt, ist der Port geschlossen oder wir haben keinen Zugriff. Schließen Sie anschließend die Verbindung.

Ändern Sie dies für Ihren Anwendungsfall, z. B. das Senden einer E-Mail, das Beenden des Skripts bei einem Fehler oder das Starten des erforderlichen Dienstes.

Spencer Rathbun
quelle
2
Das hing nur für mich.
Aman Jain
@AmanJain Katze wartet darauf, dass EOF oder Strg-C beendet werden. Sie müssen dies für Ihr Protokoll anpassen. Übrigens, führen Sie dies auf einem Remote-Server aus?
Spencer Rathbun
Ich möchte den Portprüfcode in ein Skript auf dem Server unter /etc/init.d/
Aman Jain
@AmanJain Ich habe es für ein lokales System aktualisiert. Sie möchten nur überprüfen, ob es richtig zuhört? Es gibt keine Protokollprüfung, z. B. das Anfordern einer Seite über http?
Spencer Rathbun
1
Dies ist keine zuverlässige Methode, da nicht alle Betriebssysteme (z. B. Ubuntu 16, wie ich heute entdeckt habe) mit Bash ausgeliefert werden, das für den Bau des /dev/tcp/IP/PORTBaums kompiliert wurde
dyasny
107

Hier gibt es eine sehr kurze Beschreibung mit "schnelle Antwort": Wie kann ich testen, ob der Remote-TCP-Port über das Shell-Skript geöffnet ist?

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

Ich benutze es mit 127.0.0.1 als "entfernte" Adresse.

Dies gibt "0" zurück, wenn der Port geöffnet ist, und "1", wenn der Port geschlossen ist

z.B

nc -z 127.0.0.1 80; echo $?

-z Gibt an, dass nc nur nach abhörenden Dämonen suchen soll, ohne Daten an diese zu senden. Es ist ein Fehler, diese Option in Verbindung mit der Option -l zu verwenden.

Schwarz
quelle
2
Das scheint der einfachste Weg zu sein, danke. Der Beispielskript-Link funktioniert zwar nicht mehr, ist aber trotzdem ziemlich selbsterklärend.
derFunk
Nett! Dies ist viel schneller als die anderen Antworten auf einem Server mit vielen offenen Ports. Kehrt in <0,01 Sekunden für mich zurück, während netstat / lsof 1s +
Tim
2
Das Flag -z ist in der nmap-basierten ncat nicht verfügbar, mit der die neuesten Distributionen ausgeliefert werden: Fedora, Centos usw. (nmap-ncat-6.01-9.fc18.x86_64)
Zack
9
Gegenintuitiv gibt dies "0" zurück, wenn der Port offen ist, und "1", wenn der Port geschlossen ist.
Sean
3
@ Sean Unix-Befehle geben normalerweise '0' zurück, um Erfolg anzuzeigen, und Nicht-Null für Fehler. '0' zeigt also an, dass die Verbindung erfolgreich hergestellt wurde, und nicht Null, dass die Verbindung aus irgendeinem Grund nicht hergestellt wurde. Beachten Sie jedoch, dass einige Versionen von 'nc' das Argument '-z' nicht unterstützen, sodass stackoverflow.com/a/25793128/6773916 wahrscheinlich eine bessere Lösung ist.
Rich Sedman
89

Sie können netstat auf diese Weise verwenden, um viel schnellere Ergebnisse zu erzielen:

Unter Linux:

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

Auf dem Mac:

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

Dadurch wird eine Liste der Prozesse ausgegeben, die den Port überwachen (in diesem Beispiel 445), oder es wird nichts ausgegeben, wenn der Port frei ist.

Anubhava
quelle
1
Ihre Netstat-Syntax ist falsch. netstat -ln --tcp funktioniert, aber immer noch langsam
Aman Jain
6
Eigentlich ist es die richtige Syntax, aber wahrscheinlich verwenden Sie Linux und ich bin auf einem Mac. Für Linux verwenden Sie diese:netstat -lnt | awk '$6 == "LISTEN" && $4 ~ ".445"'
Anubhava
21
dies gab nichts aus.
Jürgen Paul
1
Die Frage betraf jedoch Linux, daher sollte der Kommentar möglicherweise in der Antwort enthalten sein.
UpTheCreek
1
Um nach Port 80 zu suchen, musste ich verwenden awk '$6 == "LISTEN" && $4 ~ "80$"'. Anstatt nach dem Punkt vor der Portnummer mit zu suchen \.80, habe ich verwendet 80$. Ansonsten stimmte dies auch mit IP-Adressen überein, die .80Ports enthalten, die mit 80solchen beginnen, wie z 8000.
Patrick Oscity
37

Sie können dafür netcat verwenden.

nc ip port < /dev/null

stellt eine Verbindung zum Server her und schließt die Verbindung direkt wieder. Wenn netcat keine Verbindung herstellen kann, wird ein Exit-Code ungleich Null zurückgegeben. Der Exit-Code wird in der Variablen $? Gespeichert. Als Beispiel,

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

gibt nur dann 0 zurück, wenn netcat erfolgreich eine Verbindung zum Port herstellen konnte.

Tony
quelle
1
Diese Antwort braucht mehr Upvotes. nc funktioniert perfekt für diesen Fall. Der Trick / dev / tcp ist clever, scheint aber schwierig zu sein, ein Skript mit Signalinterrupts zu implementieren.
Avindra Goolcharan
5
nchat das -zFlag für diesen Zweck, für das keine Eingabe erforderlich ist /dev/null. Es gibt bereits eine Antwort mit der -zFlagge oben.
Abe Voelker
2
@AbeVoelker Nicht alle Versionen von nc unterstützen das Flag -z. Ich bin auf CentOS 7 und habe festgestellt, dass Tonys Lösung genau das ist, was ich brauchte.
Shadoninja
@ Shadoninja Gut zu wissen! Wenn ich die Leichtfertigkeit aus meinem Kommentar von 2014 heraus bearbeiten könnte, würde ich.
Abe Voelker
'nc' unterstützt '-z' nicht mehr und daher scheint diese Antwort die beste Lösung zu sein.
Rich Sedman
17

Basierend auf der Antwort von Spencer Rathbun mit bash:

true &>/dev/null </dev/tcp/127.0.0.1/$PORT && echo open || echo closed
user1338062
quelle
Gut, es wird die Meldung "Verbindung abgelehnt" unterdrückt. Wird automatisch beendet, wenn der Dienst die Verbindung akzeptiert, ohne ewig zu warten.
Seff
Beste Lösung für Dienste, die nach einer neuen Verbindung keine Daten senden. Etwa 20 Mal schneller als Netcat anzurufen. Kann zu verkürzen: &>/dev/null </dev/tcp/127.0.0.1/$PORT
ens
16

Sie sind in / proc / net / tcp aufgeführt.

Es ist die zweite Spalte nach dem ":" in hex:

> 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  

Ich denke also, einer von denen :50in der dritten Spalte muss Stackoverflow sein: o)

Blick in man 5 procfür mehr Details. und das mit sed usw. auseinander zu nehmen, bleibt als Übung für den sanften Leser ...

Andrew Cooke
quelle
10
ss -tl4 '( sport = :22 )'

2ms ist schnell genug?

Fügen Sie den Doppelpunkt hinzu und dies funktioniert unter Linux

Leukos
quelle
2
Großartig, ssist sogar etwas schneller als nc. list zum Hören , 4ist für IPv4; sportsteht für (natürlich) Quellport . Der obige Befehl setzt einen empfangenden TCP-Port voraus ( tOption): Verwenden Sie die uOption für UDPs oder keine für beide Protokolle. Mehr Infos zu sswie immer bei Nixcraft . HINWEIS: ssFilter funktionieren hier nicht, ich weiß nicht warum (bash 4.3.11, SS-Dienstprogramm, iproute2-ss131122), müssen mit grep gehen .
Campa
Schade, dass dieser ssBefehl keinen Exit-Code zurückgibt, der seine Feststellung widerspiegelt. Es wird immer 0 Exit-Code zurückgegeben.
John Greene
| grep LISTEN?
Leukos
Ich bekomme State Recv-Q Send-Q Local Address:Port Peer Address:Portund jetzt? Was bedeutet das?
Schwarzer
6

Hier ist eine, die sowohl für Mac als auch für Linux funktioniert:

netstat -aln | awk '$6 == "LISTEN" && $4 ~ "[\\.\:]445$"'
Artur Bodera
quelle
Ich denke, Sie können das sicher entfernen [\\.\:].
Patrick Oscity
6
nc -l 8000

Wobei 8000 die Portnummer ist. Wenn der Port frei ist, wird ein Server gestartet, den Sie problemlos schließen können. Wenn dies nicht der Fall ist, wird ein Fehler ausgegeben:

nc: Address already in use
Jose Enrique
quelle
5

Ich wollte überprüfen, ob auf einem unserer Linux-Testserver ein Port geöffnet ist. Ich konnte dies tun, indem ich versuchte, eine Verbindung mit Telnet von meinem Entwicklungscomputer zum Testserver herzustellen. Versuchen Sie auf Ihrem Entwicklercomputer Folgendes auszuführen:

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

In diesem Beispiel möchte ich überprüfen, ob Port 8080 auf Host test2.host.com geöffnet ist

Razvang
quelle
1

tcping ist ein großartiges Tool mit einem sehr geringen Overhead. Es hat auch ein Timeout-Argument, um es schneller zu machen:

[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
quelle
1
Ich bin mir nicht sicher, ob es sich lohnt, tcping zu installieren, wenn Spencers Lösung keine zusätzlichen Installationen erfordert, aber dies ist definitiv die sauberste und am besten lesbare Lösung.
Bdombro
1

Sie können auch den Befehl netcat verwenden

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

oder

nc -zv [ip] [port]

-z - setzt nc so, dass es einfach nach lauschenden Dämonen sucht, ohne tatsächlich Daten an sie zu senden.
-v - aktiviert den ausführlichen Modus.

Saurabh
quelle
-2

nmapist das richtige Werkzeug. Einfach benutzennmap example.com -p 80

Sie können es vom lokalen oder Remote-Server verwenden. Außerdem können Sie feststellen, ob eine Firewall den Zugriff blockiert.

Zainengineer
quelle
-4

Wenn Sie iptables verwenden, versuchen Sie:

iptables -nL

oder

iptables -nL | grep 445
Noz
quelle
das listet nur iptables-Regeln auf ... die möglicherweise keine Korrelation zu offenen Ports haben.
David Goodwin