Understanding Sockets - DigitalOcean

What is a Datagram Socket?

Datagram sockets are connectionless, which means that packets sent and received from a socket are processed individually by applications. Network-based datagram sockets typically use the User Datagram Protocol (UDP) to encapsulate and transmit data.

UDP does not encode sequence information in packet headers, and there is no error correction built into the protocol. Programs that use datagram-based network sockets must build in their own error handling and data ordering logic to ensure successful data transmission.

UDP sockets are commonly used by Domain Name System (DNS) servers. By default, DNS servers use port 53 to send and receive queries for domain names. An example UDP socket address for a DNS server would be similar to 203.0.113.1:53.

Note: Although the protocol is not included in the human-readable version of the socket address, operating systems differentiate socket addresses by including TCP and UDP protocols as part of the address. So a human-readable socket address like 203.0.113.1:53 could be using either protocol. Tools like ss, and the older netstat utility, are used to determine which kind of socket is being used.

The Network Time Protocol (NTP) uses a UDP socket on port 123 to synchronize clocks between computers. An example UDP socket for the NTP protocol would be 203.0.113.1:123.

Creating Datagram Sockets

As in the previous TCP socket example, in this section you’ll use socat again to emulate an NTP server listening for requests on UDP port 123. Then you’ll examine the sockets that you create using the ss and nc commands.

First, run the following socat commands to create two UDP sockets that are listening for connections on port 123, using IPv4 and IPv6 interfaces:

  1. sudo socat UDP4-LISTEN:123,fork /dev/null&
  2. sudo socat UDP6-LISTEN:123,ipv6only=1,fork /dev/null&

You will receive output like the following, which indicates the two socat process IDs that are running in the background of your shell session. Your process IDs will be different than the ones highlighted here:

Output[1] 465486 [2] 465487
  • Each command is prefixed with sudo, because ports 0 to 1024 are reserved on most systems. sudo runs a command with administrator permissions, which allows socat to bind to any port in the reserved range.
  • The UDP4-LISTEN:123 and UDP6-LISTEN:123 arguments are the protocol type and port to use. They tell socat to create UDP based sockets on port 123 on both IPv4 and IPv6 interfaces, and to listen for incoming data. Again any port in the entire range of 0-65535 is a valid parameter for UDP sockets.
  • The fork, ipv6only=1, and /dev/null arguments are used in the same manner as described in the previous TCP example.

Now that you have two socat processes listening on UDP port 123, you can examine the sockets using the ss and nc utilities.

Examining Datagram Sockets

To examine UDP sockets on a modern Linux system using the ss command, run it with the following -4, -6, and uln` flags to restrict the output:

The u flag limits the output to UDP sockets. The other flags are the same as the ones used in the previous TCP example.

First run the ss -4 -uln command to examine the IPv4 UDP sockets that are listening for connections on your system:

  1. ss -4 -uln

You will receive output like the following:

OutputState Recv-Q Send-Q Local Address:Port Peer Address:Port Process . . . UNCONN 0 0 0.0.0.0:123 0.0.0.0:* . . .

There may be other lines with other ports in your output depending on which services are running on your system. The highlighted 0.0.0.0:123 portion of the output indicates the IPv4 UDP socket is available on all IPv4 interfaces on port 123. A service that is only available on a specific IPv4 address will show only that IP in the highlighted field, for example 203.0.113.1:123.

Now run the same ss command again but with the -6 flag:

  1. ss -6 -uln

You will receive output like the following:

OutputState Recv-Q Send-Q Local Address:Port Peer Address:Port Process . . . UNCONN 0 0 [::]:123 [::]:* . . .

There may be other lines with other ports in your output depending on which services are running on your system. The highlighted [::]:123 portion of the output indicates the IPv6 TCP socket is available on all IPv6 interfaces on port 123 (as indicated by the :: characters). A service that is only available on a specific IPv6 address will show only that IP in the highlighted field, for example [2604:a880:400:d1::3d3:6001]:123.

Testing Datagram Sockets

Now that you are familiar with how to create and enumerate UDP sockets on both IPv4 and IPv6 interfaces, you can experiment with connecting to them. As with TCP sockets, you can experiment with UDP sockets using the netcat utility.

To connect to the example UDP socket on port 123 that you created in the previous section of this tutorial, run the following netcat command:

  1. nc -4 -u -vz 127.0.0.1 123
  • The -4 flag tells netcat to use IPv4.
  • The -u option instructs netcat to use UDP instead of TCP.
  • The -v flag is used to print verbose output to your terminal.
  • The -z option ensures that netcat only connects to a socket, without sending any data.
  • The local loopback 127.0.0.1 IP address is used since your system will have its own unique IP address. If you know the IP for your system you can test using that as well. For example, if your system’s public or private IP address is 203.0.113.1 you could use that in place of the loopback IP.

You will receive output like the following:

OutputConnection to 127.0.0.1 123 port [udp/ntp] succeeded!

The output indicates that netcat did not receive an error from the UDP socket listening on the loopback 127.0.0.1 IPv4 address on port 123. This lack of an error response is used to infer that the socket at 127.0.0.1:123 is available. This behaviour is different from TCP sockets, which need to exchange packets to confirm if a socket is available.

Note: If the socket in this example was unavailable, the remote system would return an ICMP type 3 message (Destination Unreachable) with a Code of 3, indicating that the port is unreachable on the remote host.

Inferring that a socket is available based on a lack of error response assumes that there are no firewalls or connectivity issues that are blocking ICMP traffic. Without sending, receiving, and verifying application data over a UDP socket, there is no guarantee that a remote UDP port is open and accepting packets.

Now you can repeat the same connection test but using IPv6. Run the following netcat command:

  1. nc -6 -u -vz ::1 123

You should receive output like the following:

OutputConnection to ::1 123 port [udp/ntp] succeeded!!

The output indicates that netcat did not receive an error from the UDP socket listening on the loopback ::1 IPv6 address on port 123. Again, this lack of an error response is used to infer that the socket at ::1:123 is available.

To clean up your sockets, you’ll need to run the fg (foreground) command for each socat process that you created. Then you’ll use CTRL+C to close each socat.

Run fg to bring the second IPv6 socat instance to the foreground of your terminal. Then run CTRL+C to close it.

  1. fg

You will receive output like the following:

Outputsudo socat UDP6-LISTEN:123,ipv6only=1,fork /dev/null

Press CTRL+C to stop the process.

Now run fg again to clean up the first IPv4 socket. You will have output like the following:

Outputsudo socat UDP4-LISTEN:123,fork /dev/null

Press CTRL+C to stop the process.

You have now created, examined, and tested IPv4 and IPv6 UDP sockets on your system. Try experimenting with each tool to become more familiar with how they can be used to test and troubleshoot UDP sockets.

Tag » What Is A Socket In Networking