Netcat is a super cool tool to perform a great number of different testing and troubleshooting tasks. On Ubuntu Linux, netcat comes built-in so you don’t even have to install it. A common question I get from people trying to troubleshoot a UDP-based application is how to check if a UDP port is “listening” or not. Most folks are familiar with the telnet-based method of checking if a TCP port is listening (e.g., telnet google.com 80), but UDP remains elusive.
Today let’s take a look at why UDP is tricky to check and a method using the netcat tool to see if a server is listening on a particular UDP port.
We’re using a very simple topology here, my PC is at 192.168.122.1 and the server we’re going to check for an open UDP port is at 192.168.122.252. My PC runs an Ubuntu 20.04 Desktop OS, while the server is running the Ubuntu Server version.
TCP and UDP are different protocols
TCP is designed to establish “reliable” connections, meaning packets are either delivered on-time and in order, or the connection fails. To guarantee delivery, it must first establish a “socket”, which is where the TCP handshake comes in. All TCP sockets start like this:
Client –> [SYN] –> Server
Client <– [SYN/ACK] <– Server
Client –> [ACK] –> Server
Once this handshake is done, a socket and connection is established.
A telnet test will succeed if this TCP handshake completes properly, letting you know that the port you’re testing is open.
The problem with UDP is that no such handshake exists, because it was designed specifically to not have connections or reliability. Neither is “better”, they’re just used for different things.
So how do you test for an open UDP connection if there’s not a protocol handshake or guaranteed response? If an application is NOT listening on a particular UDP port, and a UDP packet arrives on that port, the OS will send back an ICMP message of type 3 and code 3, meaning “destination unreachable” and “port unreachable”, respectively. Because UDP lacks a protocol message for this purpose, the ICMP message serves to notify the sender that they’re barking up the wrong tree.
Set up a netcat UDP server
Setting up a server to listen on a UDP port of our choosing is easy using netcat. Just run this command on the Ubuntu server:
netcat -ul 2000 &
-ul switches specify UDP and “listen” mode, respectively. The ampersand at the end puts the process in the background so we can get our shell back. After running this command, we can do a quick netstat to see that there is indeed a UDP server listening on port 2000:
netstat -an | grep 2000 udp 0 0 0.0.0.0:2000 0.0.0.0:*
Use netcat on the client to test the UDP port
From “James’s PC” on the diagram, I’ll run the following command:
nc -vz -u 192.168.122.252 2000
-u options specify verbose and UDP mode, respectively. The
-z option tells netcat not to send any data with the packet. At the end are the IP address of the server and to UDP port 2000. If the port is open, we should see output like this:
Connection to 192.168.122.252 2000 port [udp/*] succeeded!
The message is well and good, but well all know packets don’t lie. If we take a wireshark capture of the interaction, we can see why this success message is produced:
Five UDP packets were sent by netcat on James’s PC to make sure no response came back from the server. If there’s no ICMP response, we can infer that the port is indeed open.
The netcat UDP server will shut down after hitting it once with UDP packets, so it’s no longer listening on port 2000. If we run our command again, we’ll get no output from netcat and wireshark clearly shows the ICMP type 3 code 3 message being sent back from the server:
UDP port testing is not like TCP at all, since we can only infer the port’s open state, not guarantee it like TCP.
I hope this one was helpful!