28

This seems to be quite a trivial problem, but after some searching I can't stil figure out the answer. One can run tcpdump using "any" as the interface description, ie:

 # tcpdump -i any -n host 192.168.0.1

Is there any way to force tcpdump to show on which interface displayed packet was captured?

Update:

As more people confirmed this is probably not possible with vanilla tcpdump, can someone propose a solution to mentioned problem? Perhaps different sniffer?

General issue is as follows: On a system with 50 interfaces determine what is inbound interface for packets coming from specific ip address.

mdrozdziel
  • 734
  • 3
  • 8
  • 17

9 Answers9

25

I hope somebody is still interested in the solution to the problem. ;) We had the same issue in our company and I started writing a script for this.

I wrote a blog post about it with the source code and a screenshot.

I've also shared it below...

enter image description here

And the code: (Be sure to check my site for future updates)

#!/bin/bash
#===================================================================================
#
# FILE: dump.sh
# USAGE: dump.sh [-i interface] [tcpdump-parameters]
# DESCRIPTION: tcpdump on any interface and add the prefix [Interace:xy] in front of the dump data.
# OPTIONS: same as tcpdump
# REQUIREMENTS: tcpdump, sed, ifconfig, kill, awk, grep, posix regex matching
# BUGS:  ---
# FIXED: - In 1.0 The parameter -w would not work without -i parameter as multiple tcpdumps are started.
#        - In 1.1 VLAN's would not be shown if a single interface was dumped.
# NOTES: ---
#        - 1.2 git initial
# AUTHOR: Sebastian Haas
# COMPANY: pharma mall
# VERSION: 1.2
# CREATED: 16.09.2014
# REVISION: 22.09.2014
#
#===================================================================================

# When this exits, exit all background processes:
trap 'kill $(jobs -p) &> /dev/null && sleep 0.2 &&  echo ' EXIT
# Create one tcpdump output per interface and add an identifier to the beginning of each line:
if [[ $@ =~ -i[[:space:]]?[^[:space:]]+ ]]; then
    tcpdump -l $@ | sed 's/^/[Interface:'"${BASH_REMATCH[0]:2}"'] /' &
else
    for interface in $(ifconfig | grep '^[a-z0-9]' | awk '{print $1}')
    do
       tcpdump -l -i $interface -nn $@ | sed 's/^/[Interface:'"$interface"']    /' &
    done
fi
# wait .. until CTRL+C
wait
pevik
  • 286
  • 1
  • 12
Sebastian Haas
  • 351
  • 3
  • 5
11

You can use the -e option to print the ethernet headers, then you can correlate the src/dst MAC addresses with your network interfaces ;).

Cip
  • 111
  • 1
  • 3
  • 2
    Using `-e` only prints one MAC address on each line. For incoming packets it's the source MAC which isn't very useful in identifying which interface it arrived on. – kasperd Mar 02 '18 at 11:39
4

Just a note, tcpdump 4.99 now displays the interface name/direction in the output:

[vagrant@localhost]$sudo tcpdump -i any arp
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
18:38:49.662151 br-ex Out ARP, Request who-has 172.18.1.10 tell localhost.localdomain, length 28
18:38:49.662432 br-ex In  ARP, Reply 172.18.1.10 is-at fa:16:3e:31:b9:10 (oui Unknown), length 28

interface br-ex, above.

3

To add to Sebastian Haas's great bash script. I had to simplify his script since it failed in this line tcpdump -l $@ | sed 's/^/[Interface:'"${BASH_REMATCH[0]:2}"'] /' &.

While it is not as flexible as the original script, it is more likely to run in stripped down linux system.

#!/bin/sh
interfaces="eth0 ip6tnl1" # Interfaces list separated by whitespace
#===================================================================================
#
# FILE: dump-stripped.sh
# USAGE: dump.sh [tcpdump-parameters]
# DESCRIPTION: tcpdump on any interface and add the prefix [Interace:xy] in 
#               front of the dump data. Simplified to work in more limited env.
# OPTIONS: similar to tcpdump
# REQUIREMENTS: tcpdump, sed, ifconfig, kill, awk, grep, posix regex matching
# AUTHOR: Sebastian Haas (Stripped down By Brian Khuu)
#
#===================================================================================

# When this exits, exit all background processes:
trap 'kill $(jobs -p) &> /dev/null && sleep 0.2 &&  echo ' EXIT

# Create one tcpdump output per interface and add an identifier to the beginning of each line:
for interface in $interfaces;
do tcpdump -l -i $interface -nn $@ | sed 's/^/[Interface:'"$interface"'] /' 2>/dev/null & done;

# wait .. until CTRL+C
wait;

You may also be interested in the current github issue ticket regarding this feature omission in https://github.com/the-tcpdump-group/tcpdump/issues/296 .

Brian
  • 131
  • 1
2

If you are running on Mac, there is a -k option to tcpdump if you are using pktap interface, which dumps interface name among other useful metadata.

   -k     Control the display of packet metadata via an optional metadata_arg argument. This is useful when displaying packet saved in the
          pcap-ng file format or with interfaces that support the PKTAP data link type.

          By default, when the metadata_arg optional argument is not specified, any available packet metadata information is printed  out.

          The  metadata_arg  argument controls the display of specific packet metadata information using a flag word, where each character
          corresponds to a type of packet metadata as follows:

                 I     interface name (or interface ID)
                 N     process name
                 P     process ID
                 S     service class
                 D     direction
                 C     comment
                 U     process UUID (not shown by default)
                 A     display all types of metadata

          This is an Apple modification.
Wei Shen
  • 121
  • 2
1

I don't know of any answer to that either. I find no option for it, can't recall ever seeing one, and am rather certain that the tcpdump format doesn't include an interface identifier. I think you'll have to start one tcpdump instance for each interface and log to respective files.

Jeff Ferland
  • 20,239
  • 2
  • 61
  • 85
  • I concur. Typically when I'm sniffing traffic, I already know where the traffic is coming from or where it's going. If I have to figure that out, I have bigger fish to fry first... – Corey S. Jan 20 '11 at 17:47
  • 2
    I really need this functionality very often. I have several interfaces, lots of vlan interfaces, with IGP and BGP on top of this. Finding out how the packets are flowing is essential very often. I can manually check the outbound interface by examining the current routing table. But if I have to find the way packets are coming from the internet, sometimes I have to do blind checking, just by starting tcpdump on most probable interfaces. :( – mdrozdziel Jan 21 '11 at 01:13
1

Assuming this is on Linux, you could add an iptables rule to match the packet you are looking for and log it. Iptables log includes ingress and egress interfaces, among other things.

vadimk
  • 326
  • 2
  • 3
0
for interface in `ifconfig | grep '^[a-z0-9]' | awk '{print $1}'`;do echo $interface;tcpdump -i $interface -nn -c 25;done

Adjust -c as needed.

Nathan
  • 9
  • 1
0

by modifying the interface detection line, you can eliminate the alias-address interfaces in linux. sample below..

for interface in $(ifconfig | grep '^[a-z0-9]' | awk '{print $1}')

changes to

for interface in $(ifconfig | grep flags | sed s/': '/' ~ '/g | grep -v : | awk '{print $1}')
LTK-Tog
  • 1
  • 1