OPNsenseXXXVI · Packet Capture and Diagnosticstcpdump on the firewall
tcpdump on the firewall — the operator's primary capture tool
What you'll learn
- Construct tcpdump commands for common troubleshooting questions
- Use BPF filters to limit capture to the relevant traffic
- Rotate captures to avoid filling the filesystem
- Read tcpdump output quickly and accurately
Prerequisites
Verified against OPNsense 25.x · FreeBSD 14.x · PF (FreeBSD packet filter) FreeBSD 14.x · Unbound 1.20+ · Kea DHCP OPNsense 25.x plugin · WireGuard in-kernel + OPNsense plugin · strongSwan (IPsec plugin) OPNsense 25.x plugin · OpenVPN 2.6.x · Suricata 7.x · 2026-08-14
The graphical live capture page is convenient for a quick look. The operator who needs to capture into a file, run for hours, or apply precise filters uses tcpdump from the shell. OPNsense’s console menu, SSH session, and diagnostic shell all provide access to tcpdump with the same arguments any other FreeBSD host would use.
This lesson covers the tcpdump flags the operator needs every day, the BPF filter expressions that limit capture to the relevant slice, the rotation pattern that prevents the filesystem from filling, and the discipline of reading the output.
The minimum tcpdump invocation
The most useful tcpdump form is small and consistent:
tcpdump -ni <interface> <bpf-filter>
-n— disable DNS and service-name resolution. The output prints raw IP addresses and port numbers. The operator can decide to add-Nfor partial name resolution later if needed.-i <iface>— the interface to capture on. OPNsense uses driver names:igb0,ix0,vtnet0,em0, plus VLAN interfaces likeigb0_vlan10.- BPF filter — optional but recommended. Without a filter, tcpdump captures every frame on the interface, which on a busy link overwhelms both the buffer and the operator.
$ tcpdump -ni igb0 host 192.0.2.50 and port 443tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on igb0, link-type EN10MB (Ethernet), capture size 262144 bytes
12:34:56.789012 aa:bb:cc:11:22:33 > 66:77:88:99:aa:bb, IPv4, length 74: 192.0.2.50.51820 > 203.0.113.5.443: Flags [S], seq 1234567890, win 65535, options [mss 1460,sackOK,ts val 1234567 ecr 0,nop,wscale 7], length 0Illustrative output
Useful flags
The flags the operator uses most often:
-e— print the link-level header (source and destination MAC).-v,-vv,-vvv— increase verbosity.-vadds the TTL, IP ID, total length, IP options, and decodes more protocols.-vvadds NFS and SMB details.-vvvis rarely needed.-c N— stop after N packets.-w file.pcap— write raw packets to a file in pcap format. The file can be opened in Wireshark later.-r file.pcap— read packets from a pcap file instead of an interface. Useful for post-mortem analysis.-s snaplen— set the snapshot length (per-packet byte cap). Default on FreeBSD is typically 262144 bytes (full packet); the legacy default of 68 or 96 is rarely what the operator wants.-ttt— print delta from previous packet.-tttt— print absolute timestamp with date.
$ tcpdump -ni igb0 -e -c 1 arp12:34:56.789012 aa:bb:cc:11:22:33 > ff:ff:ff:ff:ff:ff, ARP, Request who-has 192.0.2.1 tell 192.0.2.50, length 28Illustrative output
Writing to a file and rotating
Long-running captures must write to a file (the terminal cannot display hours of traffic) and must rotate (a single huge file is hard to analyse and fills the disk). The pattern:
tcpdump -ni igb0 -w /root/capture.pcap -G 3600 -W 24 host 192.0.2.50
-w file.pcap— write to file.-G seconds— rotate the file every N seconds.-W count— keep at most N rotated files. Older files are overwritten.
In this example, files rotate every hour (-G 3600) and the last 24 are kept (-W 24). After 24 hours the oldest file is overwritten. The operator has a 24-hour window of captures at any moment.
A capture workflow
A typical capture session for “is the firewall forwarding traffic from host A to host B”:
- Identify the interfaces. Source: the interface host A is on. Destination: the interface host B is on.
- Write a precise filter.
host A-IP and host B-IPis a starting point; the operator narrows by port, protocol, or direction as the question sharpens. - Capture for a bounded time.
-c Nif the operator knows roughly how many packets to expect;-G 60if the operator needs at least one minute regardless. - Trigger the traffic. Have host A start the flow while the capture is running.
- Stop, then analyse. Ctrl-C the capture; read with
tcpdump -ror open the pcap in Wireshark.
$ tcpdump -ni igb0 -w /tmp/forward-test.pcap -c 100 'host 192.0.2.50 and 203.0.113.5'tcpdump: listening on igb0, link-type EN10MB (Ethernet), capture size 262144 bytes
100 packets captured
102 packets received by filter
0 packets dropped by kernelIllustrative output
Common BPF patterns
The BPF expressions the operator reaches for most often:
| Question | Filter |
|---|---|
| Traffic to/from one host | host 192.0.2.50 |
| Traffic to/from one network | net 192.0.2.0/24 |
| Traffic to a specific port | port 443 |
| Traffic between two hosts | host 192.0.2.50 and host 203.0.113.5 |
| All TCP traffic | tcp |
| All UDP traffic | udp |
| ICMP only | icmp |
| ARP only | arp |
| Exclude a noisy host | not host 192.0.2.100 |
| TCP SYN only (connection starts) | tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0 |
| DNS traffic | port 53 |
The expressions can be combined with and, or, not, and parentheses.
Reading the output
The operator must read tcpdump output quickly. The fields in order:
- Timestamp — when libpcap read the frame.
- Source > destination (link layer) — only with
-e. MAC addresses. - Network layer —
IPv4,IPv6,ARP, etc. - Length — total frame length on the wire.
- Source IP.port > destination IP.port — IP and transport endpoints.
- Protocol-specific details — TCP flags, sequence/ack, ICMP type/code, etc.
- Length — payload length.
For TCP, the operator reads:
- Flags
[S]— SYN, connection start. - Flags
[S.]— SYN-ACK, the server’s response. - Flags
[.]— ACK with no other flag — a data packet. - Flags
[F.]— FIN, clean close. - Flags
[R]— RST, abort. - Flags
[P.]— PSH-ACK, data with push.
The discipline is to recognise the TCP state from the flags: a flow with [S], [S.], [.], [.], [F.], [F.] is a normal connection. A flow with [S], [R] is a refused connection — the server responded with RST.
Summary
- The minimum tcpdump form is
tcpdump -ni <iface> <filter>; the operator should always pass-nto disable name resolution. - Capture to a file with rotation (
-Gand-W) for any capture longer than a minute; never capture to stdout for extended periods. - A capture session is a hypothesis test: write a filter, trigger the traffic, capture, analyse.
- TCP flags identify the connection state:
[S]is SYN,[S.]is SYN-ACK,[.]is data,[F.]is FIN,[R]is RST. - The summary line of a bounded capture is critical: “0 packets dropped by kernel” is the canary for capture completeness.
Knowledge check · 4 questions
Q1. You start a tcpdump capture with `-c 100` and the summary line at the end shows "100 packets captured, 102 packets received by filter, 0 packets dropped by kernel". What does this tell you?
Q2. Capturing for hours to stdout (the terminal) is an acceptable practice if the operator can scroll back far enough.
Q3. Which BPF filter expressions would capture TCP SYN packets (only SYN, no ACK)? Select all that apply.
Q4. You want to capture only ARP traffic on the LAN interface and see the source and destination MAC addresses. Which command?
Passing score: 75%. Answers are checked in this browser.