Contents

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.

/en/test-udp-connection-powershell/images/Test-NetworkConnection.png

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.

/en/test-udp-connection-powershell/images/Test-NetworkConnectionUDP.gif

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)
}