Logs say everything is fine. Routing table looks correct. Firewall rules seem right. But traffic still doesn’t flow. What’s actually happening?
Packet capture shows you the truth. The actual packets. Not what the logs say happened, not what should happen according to config — what actually happens on the wire.
Packets never lie.
Basic Packet Capture
VyOS Monitor Traffic Command
# VyOS provides a wrapper around tcpdumpmonitor traffic interface eth0
# Stop with Ctrl+CDirect tcpdump
# More control with tcpdump directlysudo tcpdump -i eth0
# Common optionssudo tcpdump -i eth0 -n # Don't resolve names (faster)sudo tcpdump -i eth0 -v # Verbosesudo tcpdump -i eth0 -vv # More verbosesudo tcpdump -i eth0 -c 100 # Capture 100 packets then stopCapture Filters
By IP Address
# Traffic from specific sourcesudo tcpdump -i eth0 -n src 192.168.1.100
# Traffic to specific destinationsudo tcpdump -i eth0 -n dst 8.8.8.8
# Traffic to or from hostsudo tcpdump -i eth0 -n host 192.168.1.100
# Traffic between two hostssudo tcpdump -i eth0 -n host 192.168.1.100 and host 8.8.8.8By Network
# Traffic to/from subnetsudo tcpdump -i eth0 -n net 192.168.1.0/24
# Traffic NOT from subnetsudo tcpdump -i eth0 -n not net 192.168.1.0/24By Protocol
# ICMP onlysudo tcpdump -i eth0 -n icmp
# TCP onlysudo tcpdump -i eth0 -n tcp
# UDP onlysudo tcpdump -i eth0 -n udp
# ARPsudo tcpdump -i eth0 -n arp
# OSPFsudo tcpdump -i eth0 -n proto ospf
# BGP (TCP 179)sudo tcpdump -i eth0 -n tcp port 179By Port
# Specific portsudo tcpdump -i eth0 -n port 80sudo tcpdump -i eth0 -n port 443
# Source portsudo tcpdump -i eth0 -n src port 22
# Destination portsudo tcpdump -i eth0 -n dst port 80
# Port rangesudo tcpdump -i eth0 -n portrange 1-1024Combined Filters
# HTTP traffic from specific hostsudo tcpdump -i eth0 -n host 192.168.1.100 and port 80
# SSH excluding specific hostsudo tcpdump -i eth0 -n port 22 and not host 192.168.1.1
# All traffic except SSH (while connected via SSH)sudo tcpdump -i eth0 -n not port 22
# TCP SYN packets (new connections)sudo tcpdump -i eth0 -n 'tcp[tcpflags] & (tcp-syn) != 0'
# TCP RST packets (connection resets)sudo tcpdump -i eth0 -n 'tcp[tcpflags] & (tcp-rst) != 0'Saving Captures
Write to File
# Save to pcap filesudo tcpdump -i eth0 -n -w /tmp/capture.pcap
# Save with rotation (10 files of 100MB each)sudo tcpdump -i eth0 -n -w /tmp/capture.pcap -C 100 -W 10
# Save with timestamp in filenamesudo tcpdump -i eth0 -n -w /tmp/capture-$(date +%Y%m%d-%H%M%S).pcapRead from File
# Read saved capturesudo tcpdump -r /tmp/capture.pcap
# Read with filtersudo tcpdump -r /tmp/capture.pcap tcp port 80
# Transfer to workstation for Wireshark analysisscp admin@router:/tmp/capture.pcap .Capture Strategies
Strategy 1: Two-Point Capture
Capture at both ends to see what’s happening:
# On router ingresssudo tcpdump -i eth0 -n host 192.168.1.100 -w /tmp/ingress.pcap
# On router egresssudo tcpdump -i eth1 -n host 192.168.1.100 -w /tmp/egress.pcap
# Compare: Did packet arrive? Did it leave?Strategy 2: All-Interface Capture
# Capture on all interfacessudo tcpdump -i any -n host 192.168.1.100
# Shows which interface packets traverse# Note: May see packet twice (in and out)Strategy 3: Before/After NAT
# Inside interface (pre-NAT source IP)sudo tcpdump -i eth1 -n src 192.168.1.100
# Outside interface (post-NAT source IP)sudo tcpdump -i eth0 -n src <public-ip>
# Verify NAT translation is happeningStrategy 4: Firewall Debug
# Capture traffic that should be allowedsudo tcpdump -i eth0 -n dst port 443 and dst 192.168.1.100
# If packets arrive but connection fails:# - Firewall blocking# - No return route# - Server not listeningReading tcpdump Output
TCP Three-Way Handshake
# Normal connection:10:15:01 IP 192.168.1.100.54321 > 8.8.8.8.80: Flags [S], seq 100010:15:01 IP 8.8.8.8.80 > 192.168.1.100.54321: Flags [S.], seq 2000, ack 100110:15:01 IP 192.168.1.100.54321 > 8.8.8.8.80: Flags [.], ack 2001
# [S] = SYN# [S.] = SYN-ACK# [.] = ACK# [P.] = PUSH-ACK (data)# [F.] = FIN-ACK# [R.] = RST-ACKConnection Refused
# RST immediately after SYN10:15:01 IP 192.168.1.100.54321 > 8.8.8.8.80: Flags [S], seq 100010:15:01 IP 8.8.8.8.80 > 192.168.1.100.54321: Flags [R.], ack 1001
# Means: Port closed or filteredConnection Timeout
# SYN retransmits, no response10:15:01 IP 192.168.1.100.54321 > 8.8.8.8.80: Flags [S], seq 100010:15:02 IP 192.168.1.100.54321 > 8.8.8.8.80: Flags [S], seq 100010:15:04 IP 192.168.1.100.54321 > 8.8.8.8.80: Flags [S], seq 1000
# Means: Packets not reaching destination or response not returningProtocol-Specific Captures
DNS Debugging
# Capture DNS queries and responsessudo tcpdump -i eth0 -n port 53
# Verbose to see query detailssudo tcpdump -i eth0 -n -v port 53
# Example output:# 192.168.1.100.12345 > 8.8.8.8.53: 12345+ A? example.com.# 8.8.8.8.53 > 192.168.1.100.12345: 12345 1/0/0 A 93.184.216.34HTTP Debugging
# Capture HTTP trafficsudo tcpdump -i eth0 -n -A port 80
# -A shows ASCII content (HTTP headers)# WARNING: May capture sensitive dataBGP Session
# Capture BGP trafficsudo tcpdump -i eth0 -n tcp port 179
# See BGP OPEN, UPDATE, KEEPALIVE messagessudo tcpdump -i eth0 -n -v tcp port 179OSPF
# Capture OSPF trafficsudo tcpdump -i eth0 -n proto ospf
# See Hello, LSA, DBD packetsIPsec
# Capture IKE negotiation (UDP 500/4500)sudo tcpdump -i eth0 -n udp port 500 or udp port 4500
# Capture ESP packetssudo tcpdump -i eth0 -n proto espCommon Troubleshooting Scenarios
Scenario 1: Traffic Not Reaching Destination
# Step 1: Capture at sourcesudo tcpdump -i eth1 -n src 192.168.1.100 and dst 8.8.8.8
# Step 2: Capture at exit interfacesudo tcpdump -i eth0 -n src 192.168.1.100 and dst 8.8.8.8# (use NAT source if applicable)
# If packets on eth1 but not eth0:# - Firewall blocking# - Routing issueScenario 2: Asymmetric Routing
# Capture on both interfacessudo tcpdump -i eth0 -n host 192.168.1.100sudo tcpdump -i eth1 -n host 192.168.1.100
# If request on eth0, response on eth1:# - Asymmetric routing# - Might be dropped by stateful firewallScenario 3: Connection Resets
# Find who sends RSTsudo tcpdump -i eth0 -n 'tcp[tcpflags] & (tcp-rst) != 0'
# If RST from destination: Port closed or application error# If RST from middle: Firewall, IPS, or timeoutScenario 4: MTU Problems
# Look for fragmentationsudo tcpdump -i eth0 -n 'ip[6:2] & 0x1fff != 0'
# Look for ICMP fragmentation neededsudo tcpdump -i eth0 -n 'icmp[0] = 3 and icmp[1] = 4'
# If you see these, MTU/MSS issueAdvanced Techniques
Capture Only Headers
# Capture only first 96 bytes (headers)sudo tcpdump -i eth0 -n -s 96 -w /tmp/headers-only.pcap
# Reduces file size, still useful for analysisRing Buffer for Continuous Capture
# Keep last 100MB of trafficsudo tcpdump -i eth0 -n -w /tmp/capture.pcap -C 10 -W 10
# 10 files × 10MB = 100MB rotating buffer# Useful for catching intermittent issuesTrigger-Based Capture
#!/bin/bash# Start capture when problem detectedwhile true; do # Check for symptom (e.g., high conntrack) if [ $(cat /proc/sys/net/netfilter/nf_conntrack_count) -gt 50000 ]; then timeout 60 tcpdump -i eth0 -n -w /tmp/triggered-$(date +%s).pcap fi sleep 10doneBest Practices
1. Filter Early
# Bad: Capture everything, filter latersudo tcpdump -i eth0 -w /tmp/huge.pcap
# Good: Filter during capturesudo tcpdump -i eth0 -n host 192.168.1.100 and port 80 -w /tmp/small.pcap2. Exclude SSH (When Connected via SSH)
# Avoid capturing your own sessionsudo tcpdump -i eth0 -n not port 223. Use Names for Saved Files
# Include date, interface, purposesudo tcpdump -i eth0 -n host 192.168.1.100 \ -w /tmp/eth0-192.168.1.100-$(date +%Y%m%d-%H%M%S).pcap4. Know When to Stop
# Set packet count limitsudo tcpdump -i eth0 -n -c 1000 -w /tmp/capture.pcap
# Set time limittimeout 60 sudo tcpdump -i eth0 -n -w /tmp/capture.pcapThe Lesson
Packets never lie.
When troubleshooting fails with logs and commands, packet capture shows exactly what’s happening:
- Is the traffic arriving?
- Is it leaving?
- Is the firewall changing it?
- Is NAT translating it?
- Is the destination responding?
The capture tells you what logs cannot: the actual bytes on the wire.
Every network engineer should be comfortable with tcpdump. Not Wireshark on a desktop — tcpdump on the router where the problem is.
Start simple: tcpdump -i eth0 -n host problem-ip. Build filters from there. Save captures for complex analysis. But start by looking at the packets.
They never lie.