You know and love both tcpdump and Wireshark, and are pretty good at finding the information you want. But sometimes, you still end up dumping the output to a text file and using grep to look for strings or regular expressions that tcpdump and Wire-shark can't filter on. If only there were something like tcpdump and grep combined.
There is: ngrep, or "network grep." ngrep is a packet sniffer that is similar to tcpdump, with the added facility of being able to search on any text string or regular expression just like grep. Suppose you're snooping to see what your employees are saying about you on IRC. You want to get straight to the juicy stuff, so try this command:
# ngrep -qpd eth0 host ircserver -i carla
interface: eth0 (192.168.1.0/255.255.255.0)
match: carla
##
T 192.168.1.10:33116 -> 140.222.222.107:6667 [AP]
PRIVMSG #authors :that carla is truly wonderful and everyone loves her
##
T 192.168.1.32:39422 -> 140.222.222.107:6667 [AP]
PRIVMSG #authors :yes, carla is great, the world would be dust and ashes without her
It looks promising, and you want some more context, so you add
the -A 5
switch to include the five
lines that follow your match:
# ngrep -qpd eth0 -A5 host ircserver -i carla
T 192.168.1.10:33116 -> 140.222.222.107:6667 [AP]
PRIVMSG #authors :LOL thanks, I haven't laughed that hard in ages
##
T 192.168.1.32:39422 -> 140.222.222.107:6667 [AP]
PRIVMSG #authors :NP, it's a good thing the bossy little dope can't eavesdrop on us
ngrep uses the same protocol options as tcpdump. This example shows only POP3 traffic:
# ngrep -qpd eth0 '' tcp port 110
ngrep can tell the difference between Windows pings and Linux pings. Windows uses letters to fill out the payload, and Linux uses numbers, so you can tailor your search to see what OS certain pings are coming from:
# ngrep -qpd eth0 'abcd' icmp
interface: eth0 (192.168.1.0/255.255.255.0) filter: (ip or ip6) and ( icmp ) match: abcd # I 192.168.1.77 -> 192.168.1.10 8:0 ....abcdefghijklmnopqrstuvwabcdefghi# ngrep -qpd eth0 '1234' icmp
interface: eth0 (192.168.1.0/255.255.255.0) filter: (ip or ip6) and ( icmp ) match: 1234 # I 192.168.1.76 -> 192.168.1.10 8:0 . .....F!s.... ..................... !"#$%&'()*+,-./01234567
That demonstrates how, if you can find something reasonably
unique in the data pay-load, you can make some very fine-tuned
searches. By default, ngrep displays the entire
packet. The maximum size is 65,536 bytes; use the -S
switch to view a smaller number of bytes.
This example captures HTTP headers and views only the first 156
bytes:
# ngrep -qpd -S 156 '' tcp port 80
interface: eth0 (192.168.1.0/255.255.255.0)
filter: (ip or ip6) and ( tcp port 80 )
T 192.168.1.10:33812 -> 208.201.239.36:80 [AP]
GET / HTTP/1.1..User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.
5.6 (like Gecko) (Kubuntu)..Accept: te
xt/html, image/jpeg, image/png, tex [...]
So, you can take a quick look at what web browsers your site visitors are using, without having to dig through logfiles or HTTP analyzers.
One of ngrep's nicest features is the
classic grep inversion match, -v
, which means "don't match this." This
example excludes any Session Initiation Protocol (SIP) INVITES
requests on an Asterisk
server:
# ngrep -qpd eth0 -vi invites port 5060
interface: eth0 (192.168.1.0/255.255.255.0)
filter: (ip or ip6) and ( port 5060 )
don't match: invites
Protocols and hosts are excluded with not
statements:
# ngrep -qpd eth0 \(not port 22\)
interface: eth0 (192.168.1.0/255.255.255.0) filter: (ip or ip6) and ( (not port 22) )# ngrep -qpd eth0 \(not host irc.ircserver1.org\)
interface: eth0 (192.168.1.0/255.255.255.0) filter: (ip or ip6) and ( (not host irc.ircserver1.org) )
The parentheses must be escaped, or the Bash shell will try to interpret them.
q
This means quiet output. This displays headers and payload, and omits the hash marks that separate each packet.
p
This means turn off promiscuous mode, which you should do routinely because it doesn't really work on packet-switched networks anyway.
d
This means device, or your network interface. On a multihomed system, ngrep will use the lowest-numbered device by default.
i
This means case-insensitive.
S
This means display this number of bytes.
v
This means do not match this.