tcpdump
tcpdump is a tool you will often use to troubleshoot networking problems. It's much more convenient than wireshark because you can use it on a server without a GUI. It can process enormous files very quickly and input and output can be processed using standard UNIX utilities.
Basics
The simplest way to log network traffic is to run:
$ doas tcpdump -w YYYYMMDDSS.pcap
This will log all network packets into the file YYYYMMDDSS.pcap
. Replace YYYY with the year, MM with the month, DD with the day, and SS with the serial number.
NOTE: tcpdump requires you to run as root (use doas) when you are logging network traffic because normal users should not have permission to view this sensitive data.
You can choose which network interface to log by including the option -i:
$ doas tcpdump -i vio0 -w YYYYMMDDSS.pcap
This logs only packets from vio0.
To stop collection, type [ctrl]+c, ^C
.
To read a pcap file, you use tcpdump with the -r option. I recommend also using -n to avoid doing hostname lookup (this dramatically speeds up tcpdump):
$ doas tcpdump -n -r YYYYMMDDSS.pcap
To get more verbose output, use -v. This will include the time to live (TTL) and type of service (ToS) of the packet:
$ doas tcpdump -n -v -r YYYYMMDDSS.pcap
To see the first 1500 bytes of data in ASCII format, add -s 1500 -A:
$ doas tcpdump -n -v -s 1500 -A -r YYYYMMDDSS.pcap
Filtering
The power of tcpdump lies in the ability to filter packets easily using english-like syntax:
To show only packets that are coming from or going to IP 10.0.0.1:
$ doas tcpdump 'host 10.0.0.1'
To show only packets that have source IP 192.168.0.1, then to show only packets with destination IP 172.16.0.1:
$ doas tcpdump 'src 192.168.0.1'
$ doas tcpdump 'dst 172.16.0.1'
You can combine these with and &&
, or ||
, and not !
.
To show only packets that have source IP 192.168.0.1 and destination IP 172.16.0.1
$ doas tcpdump 'src 192.168.0.1 && dst 172.16.0.1'
To show only packets from network 192.168.0.0/24 headed for destination network 172.16.0.1/16 but no packets going to or from port 22:
$ doas tcpdump '(src net 192.168.0.0/24 and dst net 172.16.0.1/16) and !port 22'
The keyword net
is used for specifying subnets and parentheses ()
are used for grouping.
To show only traffic from certain protocols, use keywords like icmp or ip6. For example:
$ doas tcpdump '(udp || tcp) && portrange 6667-7000'
This shows UDP and TCP packets that involve ports 6667 to 7000 (port ranges used for IRC).
Here are two different ways for finding RST (reset) packets (see TCP RST flood):
$ doas tcpdump 'tcp[13]&4 != 0'
$ doas tcpdump 'tcp[tcpflags] == tcp-rst'
Here are two different ways for finding SYN packets (see ?SYN flood):
$ doas tcpdump 'tcp[13]&2 != 0'
$ doas tcpdump 'tcp[tcpflags] == tcp-syn'
Here's how to find SYN-ACK packets (see ?SYN-ACK flood):
$ doas tcpdump 'tcp[13] = 18'
Here's how to find ACK packets:
$ doas tcpdump 'tcp[13]&16 != 0'
$ doas tcpdump 'tcp[tcpflags] == tcp-ack'
And FIN packets:
$ doas tcpdump 'tcp[13]&1 != 0'
$ doas tcpdump 'tcp[tcpflags] == tcp-fin'
Find the evil bit, which is always malicious:
$ doas tcpdump 'ip[6]&128 != 0'
External Links
Much of this content was adapted from Daniel Miessler's TCPDump Guide
See Also
tcpdump(8)