Been playing with system.net.sockets.tcpclient in Powershell today. My larger goal is to build a set of tools for use in automating the gathering of information in my very dynamic and disparate lab. One of the things I often need to do is to find out where a certain service is running. Web, SMTP, RDP, whatever.
To that end, I’ve come up with a modest filter function which when provided with a list of IP addresses or hostnames, will loop through them peeking and poking at a specified TCP port, and it will let you know what’s open and what’s not.
Won’t Nmap do this, you ask? Well, yeah, but then I wouldn’t learn anything.
Besides–Nmap can’t use a Powershell pipeline and we can’t have that.
Before this little script is done, I need to learn more about error trapping so that I can pretty up the output a bit. Also I think I’ll dig around in the tcpclient to figure out how to shorten the timeout. Since I’m just directing this at my lab a few feet from my desk, a long timeout isn’t necessary or desirable.
Here’s the code:
1: filter Test-TcpPort {
2: ### filter: Test-TcpPort
3: ### description: Tests to see if a port is open or closed.
4: ### version: 0.1
5: ### input:
6: ### paramaters (1) (optional, default = 80): [int] port
7: ### object pipeline: [string] IP addresses and hostnames
8: ### output:
9: ### [string] "$_ ## status" where # is port number
10: ### TODO: create custom object for output instead of strings
11: ### also need to trap the connect errors
12: Param([int]$port = 80)
13:
14: $socket = new-object Net.Sockets.TcpClient
15: $socket.Connect($_, $port)
16: if ($socket.Connected) {
17: $status = "Open"
18: $socket.Close()
19: }
20: else {
21: $status = "Closed / Filtered"
22: }
23: $socket = $null
24: write-output "$_`t$port`t$status"
25: }
And here it is in action:
6# $a = 'halr9000.com','yahoo.com','google.com' 7# $a | Test-TcpPort halr9000.com 80 Open yahoo.com 80 Open google.com 80 Open
8# $a | Test-TcpPort 22 halr9000.com 22 Open Exception calling "Connect" with "2" argument(s): "A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond" At D:\Documents and Settings\Hal\My Documents\WindowsPowerShell\lib-tcp.ps1:15 char:18 + $socket.Connect( <<<< $_, $port) yahoo.com 22 Closed / Filtered

Cool stuff, Cheers!
Shay
http://scriptolog.blogspot.com
Very nice script Hal !
For error testing, you can use the automatic variable $_. But if you do so, you must disable error display by using $ErrorActionPreference = “SilentlyContinue”.
Here’s your modified script :
filter Test-TcpPort {
### filter: Test-TcpPort
### description: Tests to see if a port is open or closed.
### version: 0.1
### input:
### paramaters (1) (optional, default = 80): [int] port
### object pipeline: [string] IP addresses and hostnames
### output:
### [string] “$_ ## status†where # is port number
### TODO: create custom object for output instead of strings
### also need to trap the connect errors
Param([int]$port = 80)
$ErrorActionPreference = “SilentlyContinue”
$socket = new-object Net.Sockets.TcpClient
$socket.Connect($_, $port)
if ($_ -and $socket.Connected) {
$status = “Openâ€
$socket.Close()
}
else {
$status = “Closed / Filteredâ€
}
$socket = $null
write-output “$_`t$port`t$statusâ€
}
Can I put you script in my French Powershell script repository ?
Best regards from France,
Arnaud
Why did you do { $_ -and $socket.connected } ? $_ is pretty much assumed this deep into the function, if I were gonna test for $_ I would do it one level up, otherwise the lack of a pipeline sets the status to closed. Or am I missing something?
Hi Hal,
You are right, testing $_ is a non sense.
Arnaud
How long was your timeout lasting? I am interested in wrapping this into a script that would scan all my DMZ hosts once a day and dump to a file and then email me if there where any differences.
I haven’t touched this .NET object in a while actually. As much as I was teasing NMAP, it is still such a cool tool that you may want to use it in combination with a script to parse the results. There’s at least one example out there of using PowerShell to do this: http://blogs.sans.org/windows-security/2009/06/11/powershell-script-to-parse-nmap-xml-output/