Skip to content

network sniffing

(Written by Paul Cobbaut, https://github.com/paulcobbaut/, with contributions by: Alex M. Schapelle, https://github.com/zero-pytagoras/)

A network administrator should be able to use a sniffer like wireshark or tcpdump to troubleshoot network problems.

A student should often use a sniffer to learn about networking. This chapter introduces you to network sniffing.

wireshark

installing wireshark

This example shows how to install wireshark on .deb based distributions (including Debian, Mint, Xubuntu, and others).

root@linux:~# apt-get install wireshark
Reading package lists... Done
Building dependency tree
Reading state information... Done
... (output truncated)

On .rpm based distributions like CentOS, RHEL and Fedora you can use yum to install wireshark.

[root@linux ~]# yum install wireshark
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
... (output truncated)

selecting interface

When you start wireshark for the first time, you will need to select an interface. You will see a dialog box that looks similar to this one.

It is possible that there are no interfaces available because some distributions only allow root to sniff the network. You may need to use sudo wireshark.

Or you can follow the general advice to sniff using tcpdump or any other tool, and save the capture to a file. Any saved capture can be analyzed using wireshark at a later time.

minimize traffic

Sniffing a network can generate many thousands of packets in a very short time. This can be overwhelming. Try to mitigate by isolating your sniffer on the network. Preferably sniff an isolated virtual network interface over which you control all traffic.

If you are at home to learn sniffing, then it could help to close all network programs on your computer, and disconnect other computers and devices like smartphones and tablets to minimize the traffic.

Even more important than this is the use of filters which will be discussed in this chapter.

sniffing ping

I started the sniffer and captured all packets while doing these three ping commands (there is no need for root to do this):

root@linux:~# ping -c2 ns1.paul.local
PING ns1.paul.local (10.104.33.30) 56(84) bytes of data.
64 bytes from 10.104.33.30: icmp_req=1 ttl=64 time=0.010 ms
64 bytes from 10.104.33.30: icmp_req=2 ttl=64 time=0.023 ms

--- ns1.paul.local ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.010/0.016/0.023/0.007 ms
root@linux:~# ping -c3 linux-training.be
PING linux-training.be (188.93.155.87) 56(84) bytes of data.
64 bytes from antares.ginsys.net (188.93.155.87): icmp_req=1 ttl=56 time=15.6 ms
64 bytes from antares.ginsys.net (188.93.155.87): icmp_req=2 ttl=56 time=17.8 ms
64 bytes from antares.ginsys.net (188.93.155.87): icmp_req=3 ttl=56 time=14.7 ms

--- linux-training.be ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 14.756/16.110/17.881/1.309 ms
root@linux:~# ping -c1 centos7.paul.local
PING centos7.paul.local (10.104.33.31) 56(84) bytes of data.
64 bytes from 10.104.33.31: icmp_req=1 ttl=64 time=0.590 ms

--- centos7.paul.local ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.590/0.590/0.590/0.000 ms

In total more than 200 packets were sniffed from the network. Things become clearer when you enter icmp in the filter field and press the apply button.

sniffing ping and dns

Using the same capture as before, but now with a different filter. We want to see both dns and icmp traffic, so we enter both in the filter field.

We put dns or icmp in the filter to achieve this. Putting dns and icmp would render nothing because there is no packet that matches both protocols.

In the screenshot above you can see that packets 25 and 26 both have 10.104.33.30 as source and destination ip address. That is because the dns client is the same computer as the dns server.

The same is true for packets 31 and 32, since the machine is actually pinging itself.

specific ip address

This is a screenshot that filters for dns packets that contain a certain ip address. The filter in use is ip.addr==10.104.33.30 and dns. The and directive forces each displayed packet to match both conditions.

Packet 93 is the dns query for the A record of linux-training.be. Packet 98 is the response from the dns server. What do you think happened in the packets between 93 and 98 ? Try to answer this before reading on (it always helps to try to predict what you will see, and then checking your prediction).

filtering by frame

The correct technical term for a packet as sniffed is a frame (because we sniff on layer two). So to display packets with certain numbers, we use frame.number in the filter.

looking inside packets

The middle pane can be expanded. When selecting a line in this pane, you can see the corresponding bytes in the frame in the bottom panel.

This screenshot shows the middle pane with the source address of my laptop selected.

Note that the above works fine when sniffing one interface. When sniffing with for example tcpdump -i any you will end up with Linux cooked at this level.

other filter examples

You can combine two protocols with a logical or between them. The example below shows how to filter only arp and bootp (or dhcp) packets.

This example shows how to filter for dns traffic containing a certain ip address.

tcpdump

Sniffing on the command line can be done with tcpdump. Here are some examples.

Using the tcpdump host $ip command displays all traffic with one host (192.168.1.38 in this example).

root@linux:~# tcpdump host 192.168.1.38
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes

Capturing only ssh (tcp port 22) traffic can be done with tcpdump tcp port $port. This screenshot is cropped to 76 characters for readability in the pdf.

root@linux:~# tcpdump tcp port 22
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 96 bytes
14:22:20.716313 IP deb106.local.37973 > rhel53.local.ssh: P 666050963:66605
14:22:20.719936 IP rhel53.local.ssh > deb106.local.37973: P 1:49(48) ack 48
14:22:20.720922 IP rhel53.local.ssh > deb106.local.37973: P 49:113(64) ack 
14:22:20.721321 IP rhel53.local.ssh > deb106.local.37973: P 113:161(48) ack
14:22:20.721820 IP deb106.local.37973 > rhel53.local.ssh: . ack 161 win 200
14:22:20.722492 IP rhel53.local.ssh > deb106.local.37973: P 161:225(64) ack
14:22:20.760602 IP deb106.local.37973 > rhel53.local.ssh: . ack 225 win 200
14:22:23.108106 IP deb106.local.54424 > ubuntu910.local.ssh: P 467252637:46
14:22:23.116804 IP ubuntu910.local.ssh > deb106.local.54424: P 1:81(80) ack
14:22:23.116844 IP deb106.local.54424 > ubuntu910.local.ssh: . ack 81 win 2
^C
10 packets captured
10 packets received by filter
0 packets dropped by kernel

Same as above, but write the output to a file with the tcpdump -w $filename command.

root@linux:~# tcpdump -w sshdump.tcpdump tcp port 22
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
^C
17 packets captured
17 packets received by filter
0 packets dropped by kernel

With tcpdump -r $filename the file created above can be displayed.

root@linux:~# tcpdump -r sshdump.tcpdump

Many more examples can be found in the manual page of tcpdump.

practice: network sniffing

1. Install wireshark on your computer (not inside a virtual machine).

2. Start a ping between your computer and another computer.

3. Start sniffing the network.

4. Display only the ping echo\'s in the top pane using a filter.

5. Now ping to a name (like www.linux-training.be) and try to sniff the DNS query and response. Which DNS server was used ? Was it a tcp or udp query and response ?

6. Find an amateur/hobby/club website that features a login prompt. Attempt to login with user \'paul\' and password \'hunter2\' while your sniffer is running. Now find this information in the sniffer.

solution: network sniffing

1. Install wireshark on your computer (not inside a virtual machine).

Debian/Ubuntu: aptitude install wireshark

Red Hat/Mandriva/Fedora: yum install wireshark

2. Start a ping between your computer and another computer.

ping $ip_address

3. Start sniffing the network.

(sudo) wireshark

select an interface (probably eth0)

4. Display only the ping echo\'s in the top pane using a filter.

type 'icmp' (without quotes) in the filter box, and then click 'apply'

5. Now ping to a name (like www.linux-training.be) and try to sniff the DNS query and response. Which DNS server was used ? Was it a tcp or udp query and response ?

First start the sniffer.

Enter 'dns' in the filter box and click apply.

root@linux:~# ping www.linux-training.be
PING www.linux-training.be (88.151.243.8) 56(84) bytes of data.
64 bytes from fosfor.openminds.be (88.151.243.8): icmp_seq=1 ttl=58 time=14.9 ms
64 bytes from fosfor.openminds.be (88.151.243.8): icmp_seq=2 ttl=58 time=16.0 ms
^C
--- www.linux-training.be ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 14.984/15.539/16.095/0.569 ms

The wireshark screen should look something like this.

The details in wireshark will say the DNS query was inside a udp packet.

6. Find an amateur/hobby/club website that features a login prompt. Attempt to login with user \'paul\' and password \'hunter2\' while your sniffer is running. Now find this information in the sniffer.