20 Sep

Testing TCP connections with PowerShell

I’ve been in the situation where I have needed to test whether I could make a TCP connection from one Windows host to another Windows host to verify that a network team had indeed opened firewall ports. It seems like a trivial thing to do. Just connect from host A to host B on the specified port. What programs can we use to do this? It’s a bit overkill to install a whole piece of server and client software to test this. Let alone read any necessary documentation to configure the correct port. It gets worse if things don’t work as you still don’t know whether it’s the firewall or your configuration!

Linux users could just install Netcat on both hosts and check this in a few seconds. Window users still have the ability to install some networking utilities similar to Netcat but I find them overly complicated considering 99% of the time I just want to know whether an intermediate firewall is blocking a connection.

PowerShell is so useful and gives you the full power of the .NET framework. This means we can create these utilities ourselves natively without installing any third party libraries.

I’ve created two functions, Listen-Tcp and Connect-Tcp, which have code listsings at the bottom of the post. The following is an example use of the utilities:

Listen-Tcp -port <Int32>
Connect-Tcp -hostname <string> -port <Int32>

Running the corresponding scripts on two hosts, hosta and hostb will give you the following outputs:

hosta > Listen-Tcp -port 3000
Listening on port 3000
Stopped Listening
hostb > Connect-Tcp -hostname "hosta" -port 3000
Data sent to and received from target successfully

For convenience I have added these functions to my PowerShell profile so that they are available on all servers I log into within the domain.

Below is the code listing

function Listen-Tcp()
{
	param(
		[Int32] $port
	)
	
	$server = New-Object -TypeName System.Net.Sockets.TcpListener -ArgumentList @([System.Net.IPAddress]::Any, $port)
	$server.Start()
	
	Write-Host ("Listening on port {0}" -f $port)
	$clientSocket = $server.AcceptSocket()
	
	$buffer = New-Object -TypeName byte[] -ArgumentList 4
	$clientSocket.Receive($buffer) | Out-Null
	
	$clientSocket.Send($buffer) | Out-Null
	$clientSocket.Close()
	
	$server.Stop()
	
	Write-Host "Stopped Listening"
}
function Connect-Tcp()
{
	param(
		[string]$hostname,
		[Int32]$port
	)
	
	try
	{
		$client = New-Object -TypeName System.Net.Sockets.TcpClient -ArgumentList $hostname,$port
		$stream = $client.GetStream()
		
		$buffer = [System.Text.Encoding]::ASCII.GetBytes("EHLO")
		$stream.Write($buffer, 0, $buffer.Length)
		
		$receiveBuffer = New-Object -TypeName byte[] -ArgumentList $buffer.Length
		$stream.Read($receiveBuffer, 0, $receiveBuffer.Length) | Out-Null
		
		$receivedText = [System.Text.Encoding]::ASCII.GetString($receiveBuffer)
		
		$stream.Close()
		$client.Close()
		
		if ($receivedText -eq "EHLO") {
			Write-Host "Data sent to and received from target successfully"
		} else {
			Write-Host "Data receieved was not as expected"
		}
	} Catch [Exception]
	{
		Write-Host "Could not connect to target machine"
	}
}

Leave a Reply

Your email address will not be published. Required fields are marked *