Optimizing TCPDump Filters: How to Exclude Private IP Traffic Efficiently


2 views

When analyzing network traffic using tcpdump, we often need to exclude internal communications between private IP addresses (RFC 1918 ranges) to focus on external traffic. The standard private IP ranges are:

  • 10.0.0.0/8
  • 172.16.0.0/12 (not /20 as in original filter)
  • 192.168.0.0/16

The initial approach has several inefficiencies:

1. Duplicate conditions (both src and dst checks appear twice)
2. Incorrect subnet mask for 172.16.0.0 (should be /12 not /20)
3. Overly complex logical structure
4. Redundant 'not' operators

Here's a more elegant solution that achieves the same result:

sudo tcpdump -n 'not ( \
    (src net 10.0.0.0/8 or src net 172.16.0.0/12 or src net 192.168.0.0/16) \
    and \
    (dst net 10.0.0.0/8 or dst net 172.16.0.0/12 or dst net 192.168.0.0/16) \
)' -w filtered_capture.pcap

For more complex scenarios, consider these variations:

Basic exclusion:

sudo tcpdump -n 'not (
    src net 10/8 or src net 172.16/12 or src net 192.168/16
) and not (
    dst net 10/8 or dst net 172.16/12 or dst net 192.168/16
)'

Capturing only public traffic:

sudo tcpdump -n '( \
    not src net 10/8 and not src net 172.16/12 and not src net 192.168/16 \
) or ( \
    not dst net 10/8 and not dst net 172.16/12 and not dst net 192.168/16 \
)'

While tcpdump filters are generally efficient, complex filters with many OR conditions can impact performance. For high-traffic networks:

  • Use the most specific filter possible
  • Consider BPF (Berkeley Packet Filter) optimizations
  • Test filter performance with -c option first

Example 1: Capture only traffic involving at least one public IP

sudo tcpdump -n '( \
    not (src net 10/8 or src net 172.16/12 or src net 192.168/16) \
) or ( \
    not (dst net 10/8 or dst net 172.16/12 or dst net 192.168/16) \
)'

Example 2: Exclude internal traffic while capturing specific ports

sudo tcpdump -n 'port 80 and not ( \
    (src net 10/8 or src net 172.16/12 or src net 192.168/16) \
    and \
    (dst net 10/8 or dst net 172.16/12 or dst net 192.168/16) \
)'

When analyzing network traffic with TCPdump, one common need is to exclude internal communications between private IP addresses (RFC 1918 ranges). The standard approach often leads to verbose filter expressions that are difficult to maintain.

The original solution works but can be significantly optimized. Here's a more elegant version:

sudo tcpdump -n 'not (
    (src net 10.0.0.0/8 or src net 172.16.0.0/12 or src net 192.168.0.0/16)
    and
    (dst net 10.0.0.0/8 or dst net 172.16.0.0/12 or dst net 192.168.0.0/16)
)' -w filtered.dump

1. Corrected subnet mask for 172.16.0.0/12 (original used /20 which only covers part of the range)

2. Eliminated redundant conditions

3. Reduced nesting levels

Basic Exclusion:

tcpdump -n 'not (src net 10.0.0.0/8 and dst net 10.0.0.0/8)'

Capture Only External Traffic:

tcpdump -n '(
    not (src net 10.0.0.0/8 or src net 172.16.0.0/12 or src net 192.168.0.0/16)
    and
    not (dst net 10.0.0.0/8 or dst net 172.16.0.0/12 or dst net 192.168.0.0/16)
)'

When dealing with high traffic volumes, consider these optimizations:

tcpdump -n -s 0 -B 4096 'filter-expression'

Combine with other filters for specific analysis:

tcpdump -n '(
    not (src net 10.0.0.0/8 and dst net 10.0.0.0/8)
) and (
    port 80 or port 443
)'

For IPv6 private address filtering (ULA):

tcpdump -n 'not (src net fc00::/7 and dst net fc00::/7)'

Always verify your filters work as intended. First test with -v flag:

tcpdump -n -v 'your-filter'

Remember that complex filters may impact capture performance. Benchmark with:

time tcpdump -n -c 100000 'your-filter' > /dev/null