Test UDP connection with PowerShell
When analyzing network problems, a simple ICMP ping is never sufficient to verify if the connection between two devices works. Normally a TCP connection to a server is needed and PowerShell comes with an appropriate cmdlet Test-NetConnection
.
However, by default Test-NetConnection
only supports TCP connections and also tests an ICMP ping each time.
So, what’s up with UDP?
There is no built-in tool for analyzing stateless UDP packets, so I wrote the following two functions.
Start-UDPServer
takes over the role of the server and can only be used if the actual service is not running.Test-NetConnectionUDP
sends the current date incl. time to the server.
Start-UDPServer
The function knows only one parameter and that is -Port
. Once started, all incoming UDP packets are accepted and displayed together with the local time, the sent time and the source IP address and port.
function Start-UDPServer {
[CmdletBinding()]
param (
# Parameter help description
[Parameter(Mandatory = $false)]
$Port = 10000
)
# Create a endpoint that represents the remote host from which the data was sent.
$RemoteComputer = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::Any, 0)
Write-Host "Server is waiting for connections - $($UdpObject.Client.LocalEndPoint)"
Write-Host "Stop with CRTL + C"
# Loop de Loop
do {
# Create a UDP listender on Port $Port
$UdpObject = New-Object System.Net.Sockets.UdpClient($Port)
# Return the UDP datagram that was sent by the remote host
$ReceiveBytes = $UdpObject.Receive([ref]$RemoteComputer)
# Close UDP connection
$UdpObject.Close()
# Convert received UDP datagram from Bytes to String
$ASCIIEncoding = New-Object System.Text.ASCIIEncoding
[string]$ReturnString = $ASCIIEncoding.GetString($ReceiveBytes)
# Output information
[PSCustomObject]@{
LocalDateTime = $(Get-Date -UFormat "%Y-%m-%d %T")
SourceIP = $RemoteComputer.address.ToString()
SourcePort = $RemoteComputer.Port.ToString()
Payload = $ReturnString
}
} while (1)
}
Test-NetConnectionUDP
On the client side at least the parameters destination -Port
and server -ComputerName
must be specified. By means of -SourcePort
the sending port can also be influenced, which helps when testing firewall rules.
function Test-NetConnectionUDP {
[CmdletBinding()]
param (
# Desit
[Parameter(Mandatory = $true)]
[int32]$Port,
# Parameter help description
[Parameter(Mandatory = $true)]
[string]$ComputerName,
# Parameter help description
[Parameter(Mandatory = $false)]
[int32]$SourcePort = 50000
)
begin {
# Create a UDP client object
$UdpObject = New-Object system.Net.Sockets.Udpclient($SourcePort)
# Define connect parameters
$UdpObject.Connect($ComputerName, $Port)
}
process {
# Convert current time string to byte array
$ASCIIEncoding = New-Object System.Text.ASCIIEncoding
$Bytes = $ASCIIEncoding.GetBytes("$(Get-Date -UFormat "%Y-%m-%d %T")")
# Send data to server
[void]$UdpObject.Send($Bytes, $Bytes.length)
}
end {
# Cleanup
$UdpObject.Close()
}
}
Known Issues
- The first packet is not displayed immediately, but only when the second packet is received.
- The server must receive one additional packet after it was terminated by CTRL+C to exit the loop.
- The specified ports must not be used by another application.
Update 11.02.2021: Start-TCPServer
In the latest Hamburg PowerShell User Group we build a TCP listener to use with the native Test-NetConnection
cmdlet.
function Start-TCPServer {
[CmdletBinding()]
param (
[Parameter(Mandatory = $false)]
$Port = 10000
)
do {
# Create a TCP listender on Port $Port
$TcpObject = New-Object System.Net.Sockets.TcpListener($port)
# Start TCP listener
$ReceiveBytes = $TcpObject.Start()
# Accept TCP client connection
$ReceiveBytes = $TcpObject.AcceptTcpClient()
# Stop TCP Client listener
$TcpObject.Stop()
# Output information about remote client
$ReceiveBytes.Client.RemoteEndPoint
} while (1)
}