Tags: Netzwerk, PowerShell
Offene Ports auf einem Host abzufragen, kann aus unterschiedlichen Gründen notwendig sein. Dazu zählen etwa Security-Checks, das Troubleshooting bei Verbindungsproblemen oder die Prüfung eines Ports, bevor sich ein Script mit einem Host verbindet. Diese Aufgabe kann PowerShell am besten über die .NET-Klasse TcpClient erledigen.
Für einen großflächigen Port-Scan wird man in der Regel zu Programmen greifen, die auf diesen Zweck spezialisiert sind. Dazu gehören unter anderem einige kostenlose Netzwerk-Scanner.
In PowerShell bieten sich dafür zwei Varianten an:
Test-NetConnection für einzelne Ports
Wenn man jedoch innerhalb eines Scripts herausfinden muss, ob ein Port offen ist, dann wird man eher zu den Bordmitteln von PowerShell greifen. Viele Anleitungen empfehlen dafür den Einsatz von Test-NetConnection.
Damit könnte man zum Beispiel prüfen, ob auf dem Host mit der IP 192.168.0.55 der Port 80 geöffnet ist:
Test-NetConnection 192.168.0.55 -Port 80
Die Eigenschaft TcpTestSucceeded des zurückgegebenen Objekts zeigt dann mit True oder False den Status des Ports.
Innerhalb eines Scripts kann man den Aufruf in ein if-Statement einbetten:
if((Test-NetConnection 192.168.0.55 -Port 80).TcpTestSucceeded){
"Port 80 offen"
}
Der große Nachteil von Test-NetConnection besteht darin, dass man keinen Timeout angeben kann und es somit lange hängt, wenn ein Port auf eine Anfrage nicht reagiert. Das Prüfen eines ganzen Bereichs ist damit praktisch nicht möglich.
ConnectAsync-Methode
Als Alternative bietet sich an, ein Objekt auf Basis der .NET-Klasse Net.Sockets.TcpClient zu erzeugen. Diese umfasst mehrere Methoden zum Aufbau einer Verbindung, darunter Connect() und ConnectAsync(). Erstere hängt wie Test-NetConnection lange fest, wenn ein Port geschlossen ist.
Hingegen kann man ConnectAsync() mit der Wait()-Methode kombinieren, um ein Zeitlimit in Millisekunden für die Task festzulegen. Ein Wert von 5 reicht in der Regel aus, so dass man etwa den Bereich von 1 bis 1024 in einigen Sekunden scannen kann, während Test-NetConnection dafür eine halbe Ewigkeit braucht:
1 .. 1024 |
foreach{ if((New-Object Net.Sockets.TcpClient).ConnectAsync("192.168.0.55", $_).Wait(5))
{ "Port $_ offen" }}
Anstatt einen Bereich auf einem Host zu untersuchen, könnte man etwa in einem Subnetz alle Rechner darauf prüfen, ob der Standard-Port für RDP (3389) offen ist. Auch das lässt sich mit dieser Methode bewerkstelligen:
1 .. 254 |
foreach{ if((New-Object Net.Sockets.TcpClient).ConnectAsync("192.168.0.$_", 3389).Wait(5))
{ "Port 3389 auf 192.168.0.$_ offen" }}
Zusammenfassung
Wenn man auf einem Host nur einen bestimmten Port prüfen möchte, dann kann man dafür Test-NetConnection verwenden. Dieses Cmdlet hat jedoch einen langen Timeout, so dass ein Scan schnell zur Geduldsprobe wird.
Als wesentlich flinker erweist sich die Methode ConnectAsync() der .NET-Klasse TcpClient. Die Task lässt sich dort mit Wait() auf eine bestimmte Dauer begrenzen.
Täglich Know-how für IT-Pros mit unserem Newsletter
Verwandte Beiträge
Weitere Links