17

I am trying to troubleshoot an issue where I only have tcpdump available on an appliance. I want to use tcpdump to filter web traffic, and only display traffic containing certain strings.

I do the following:

tcpdump -nei eth0 -X | grep "something interesting"

The output is a hexview with 16 bytes pr line. I cannot grep this data, as the data is presented on multiple lines.

Is there a way for tcpdump to present the captured data on a single line? This would make it possible to use grep to find interesting packets.

4
  • 1
    well, I can't test this right now but if you have multiple lines you could do | tr -d '\n' or grep -C 3 to get some lines before and after
    – barlop
    Jun 10, 2014 at 11:50
  • @barlop, grep -C sort of works, but unreliable, as I never know how many lines up the header will be, and I will not see the lines below the match. The tr command trancates all the output to 1 line, so its a bit too much. Jun 10, 2014 at 14:29
  • The following wouldn't be grep, but tcpdump can match strings by hex which is essentially grep without any regex. You can specify an offset. I have this jotted down in a file (done with windump but I that's just a windows version of tcpdump so assume tcpdump) tcpdump -nXr zfile "tcp[32:4] = 0x47455420"
    – barlop
    Jun 10, 2014 at 14:39
  • related: How to process/pipe TCPDUMPs output in realtime
    – bain
    Dec 19, 2019 at 11:56

6 Answers 6

16

For those like you who cannot use ngrep, here's how to use awk to make the tcpdump output of packet contents grepable.

First some sample output as provided by tcpdump -x, in order to present the task ahead:

$ tcpdump -xr dump.pcap 2>/dev/null
12:04:59.590664 IP 10.17.14.93.51009 > 239.194.1.9.51009: UDP, length 370
        0x0000:  4500 018e 0000 4000 fa11 7625 0a11 0e5d
        0x0010:  efc2 0109 c741 c741 017a 6f28 1120 2020
        0x0020:  3337 3030 3039 3031 3835 3635 3430 3130
...

And this is the copy-and-pastable awk script you can pipe the output to

awk '{ if (match($0, /^[0-9]/, _)) { printf (NR == 1 ? "%s " : "\n%s "), $0; fflush() } else { sub(/^\s+0x[0-9a-z]+:\s+/, " "); gsub(" ", ""); printf "%s", $0 } } END { print ""; fflush() }'

in order to get the following, grepable output

12:04:59.590664 IP 10.17.14.93.51009 > 239.194.1.9.51009: UDP, length 370 4500018e00004000fa1176250a...
12:04:59.590798 IP 10.17.14.113.51011 > 239.194.1.11.51011: UDP, length 370 4500018e00004000fa11760f...
...

Below is a commented version of above script:

awk '{
    # if this is a header line
    if (match($0, /^[0-9]/, _)) {
        # print the header, but:

        # except for the first line,
        # we need to insert a newline,
        # as the preceding data lines will
        # have been stripped of theirs

        # we also append a space to
        # separate header info from the
        # data that will get appended
        printf (NR == 1 ? "%s " : "\n%s "), $0
        # enforce line-buffering
        fflush()
    }
    # otherwise it is a data line
    else {
        # remove the data address
        sub(/^\s+0x[0-9a-z]+:\s+/, " ");
        # remove all spaces
        gsub(" ", "");
        # print w/o newline
        printf "%s", $0 
    }
}
END {
    # print final newline, as
    # the preceding data lines will
    # have been stripped of theirs
    print ""
    # enforce line-buffering
    fflush()
}'
7

From the tcpdump manpage:

-A      Print each packet (minus its link level header) in ASCII.  Handy
        for capturing web pages.

Make sure you also use the -s 0 option to make sure the entire packet is displayed.

2
  • 1
    Thanks, but data is still presented at multiply lines - wherever the webpage has newlines in it. I have problem associating the header (and rest of data) with grepped output. Jun 10, 2014 at 11:52
  • I just realized why the tool is called awkward Nov 15, 2015 at 23:32
3

You may want to have a look at ngrep command:

ngrep -W single -d eth0 'regex to match' 'port 80'

Where:

  • -W single specifies single line formatting
  • regex to match means to only dump packets containing certain string.
  • 'port 80' is a pcap filter to only sniff packets from or to port 80
2
  • 1
    Would like to use ngrep, but there is no such tool - it is an appliance... Jun 10, 2014 at 14:30
  • ngrep is awesome. I was searching for hours which host is generating HTTP traffic to my host. With single sudo ngrep "GET .." found answer in minute. Sep 28, 2016 at 13:56
1

tcpdump -nei eth0 -l | grep "something interesting"

man 1 tcpdump: "-l Make stdout line buffered. Useful if you want to see the data while capturing it."

0

The reason your output is hex is the -X flag. Try:

tcpdump -ni eth1 | grep something_interesting

You will get dumped readable output right to the cli.

1
  • 2
    Yes, but it will not contain the content of the packet.
    – RalfFriedl
    May 31, 2019 at 20:36
0

I couldn't get the awk script to do what I wanted and ngrep would not work on an Ethernet over USB, so I wrote a small C program to join the lines output by tcpdump so they are grepable. It's at https://gitlab.com/dargaud/TcpDumpJoin

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.