UDP datagrams, despite their "unreliable" nature, are the workhorses of many high-performance applications, from streaming video to DNS lookups. Capturing and inspecting them with tcpdump is essential for debugging network issues, analyzing application behavior, and even identifying security threats. The trick isn’t just capturing packets, but filtering them precisely and understanding what you’re seeing.
Let’s say you’re troubleshooting a DNS server that’s occasionally dropping queries. Your first instinct might be to just run tcpdump -i eth0 udp. This will capture all UDP traffic on the eth0 interface, which is usually a lot. You’ll be wading through background noise from NTP, SNMP, and other UDP services, making it hard to find your specific DNS queries.
Here’s how to cut through the noise and focus on what matters.
Capturing Specific UDP Traffic
The most common scenario is filtering by port. DNS uses UDP port 53. To capture only DNS traffic:
sudo tcpdump -i eth0 udp port 53
This command tells tcpdump to listen on interface eth0 and only record packets where the UDP destination or source port is 53.
Why it works: The udp keyword restricts the capture to UDP packets, and port 53 further filters these to only those involving port 53.
If your DNS server is also acting as a DHCP server (though less common), you might need to capture both DNS (UDP/53) and DHCP (UDP/67 and UDP/68). You can combine filters using logical operators:
sudo tcpdump -i eth0 "udp port 53 or udp port 67 or udp port 68"
Why it works: The or operator allows you to specify multiple conditions. If any of the port conditions are met, the packet is captured.
Sometimes, you need to see traffic between specific hosts. Let’s say your DNS client is at 192.168.1.100 and your DNS server is at 192.168.1.1. To capture UDP traffic only between these two, regardless of the port (though we’ll assume port 53 for DNS):
sudo tcpdump -i eth0 "udp host 192.168.1.100 and udp host 192.168.1.1 and udp port 53"
Why it works: The and operator requires all conditions to be true. This captures UDP packets that are both from 192.168.1.100 and to 192.168.1.1 (or vice-versa, as host matches either source or destination) and are using UDP port 53.
Inspecting UDP Datagrams
Once you’ve captured the traffic, you need to inspect it. tcpdump’s default output can be verbose, but with the right options, you can see the payload.
To see the UDP payload in ASCII, use the -A flag:
sudo tcpdump -i eth0 udp port 53 -A
This will display the packet content, attempting to interpret it as ASCII. For DNS queries, you’ll see human-readable strings representing the domain names being looked up.
Why it works: The -A flag decodes each packet’s data in ASCII. Non-printable characters are displayed as dots (.).
If ASCII isn’t helpful (e.g., for encrypted UDP traffic or binary protocols), you can use -X to see the packet in both hexadecimal and ASCII:
sudo tcpdump -i eth0 udp port 53 -X
This is invaluable for understanding the raw structure of the UDP datagram, including headers and payload.
Why it works: The -X flag provides a hex/ASCII dump, showing the byte-level representation which is crucial for dissecting custom or binary protocols.
Often, you want to capture to a file for later analysis with tools like Wireshark or even just to review it without cluttering your terminal. Use the -w flag:
sudo tcpdump -i eth0 udp port 53 -w dns_capture.pcap
Then, you can read this file later:
tcpdump -r dns_capture.pcap
Why it works: The -w flag writes raw packet data to a file in pcap format, which is a standard for network packet capture. -r reads from such a file.
Common Pitfalls and Advanced Filtering
- Large UDP Payloads: UDP datagrams can be large. If you’re capturing a streaming application, you might see many packets with the same source/destination but varying payload content. Filtering by a specific application’s IP address or a known pattern in the payload might be necessary.
- Fragmented UDP: While UDP itself doesn’t have reassembly built-in like TCP, IP fragmentation can occur.
tcpdumpwill show these fragments. If you’re trying to reconstruct a large UDP message, you’ll need to look at sequences of fragmented packets.tcpdump’s default behavior is to show fragments as they arrive. - Source vs. Destination: Remember that UDP can be used for both client requests (e.g., DNS query to server) and server responses (e.g., DNS response from server). Your filters might need to account for both directions. For example, to see all DNS traffic to or from your server
192.168.1.1:
This is often equivalent to justsudo tcpdump -i eth0 "udp port 53 and (src host 192.168.1.1 or dst host 192.168.1.1)"udp port 53 and host 192.168.1.1.
A less obvious but critical aspect of UDP capture is understanding the Maximum UDP Payload Size. A single UDP datagram can carry up to 65,507 bytes of data (65,535 total UDP packet size minus 8 bytes for the UDP header and 20 bytes for the IP header). If you’re seeing truncated data in your captures, it’s not necessarily tcpdump’s fault; it might be how the application is sending it, or you might be hitting MTU limits and experiencing fragmentation.
If you’ve successfully filtered and inspected your UDP traffic and resolved your immediate issue, the next thing you’ll likely encounter is dealing with the sheer volume of captured data, leading you to explore tcpdump’s rotation and size limits for long-running captures.