ONLamp.com    
 Published on ONLamp.com (http://www.onlamp.com/)
 See this if you're having trouble printing code examples


FreeBSD Basics

IP Packets Revealed

03/28/2001

Also in FreeBSD Basics:

Fun with Xorg

Sharing Internet Connections

Building a Desktop Firewall

Using DesktopBSD

Using PC-BSD

In last week's article, we used the tcpdump utility to capture the packets involved in a telnet session and then examined the resulting dump file. This week, I'd like to continue through the output of this file to see what else we can discover regarding a typical TCP connection.

When we looked at the packets involved in the TCP 3-way handshake, we paid particular attention to the flags field in the TCP header. The only time a packet's SYN flag is set is if it is one of the first two packets involved in the 3-way handshake. This means that whenever a packet arrives with its SYN flag set, someone is trying to create a TCP connection. Notice in today's output that every TCP header has an acknowledgment number and the ACK flag is set; the only exception to this rule is found in the very first packet involved in the 3-way handshake. That is, if a packet arrives with the SYN flag set but not the ACK flag, that packet is trying to initiate a connection to one of your network services; the destination port field will tell you which service they are trying to connect to.

Let's take one last look at that first packet from last week's 3-way handshake:

tcpshow < dump
<snip to just show this one packet>

-------------------------------------------------------------
Packet 10
TIME: 10:25:36.854420 (6.232947)
LINK: 00:00:B4:3C:56:40 -> 00:50:BA:DE:36:33 type=IP
  IP: 10.0.0.2 -> 10.0.0.1 hlen=20 TOS=10 dgramlen=44 id=0013
      MF/DF=0/1 frag=0 TTL=64 proto=TCP cksum=26A7
 TCP: port blackjack -> telnet seq=3205630181 ack=0000000000
      hlen=24 (data=0) UAPRSF=000010 wnd=16384 cksum=7814 urg=0
DATA: <No data>
--------------------------------------------------------------

Note that this packet has no acknowledgement (ack=0000000000) and the only TCP flag that has been set (UAPRSF=000010) to 1 is the S or SYN flag. This packet came from 10.0.0.2 and it is trying to establish a connection to (->) the telnet port on 10.0.0.1.

TCP also has an established procedure for gracefully ending a TCP connection. As you may have guessed, it involves the use of the FIN flag. Either end of a TCP connection can ask to close the connection at any time. In our example, I typed the word exit as soon as I had established the telnet connection and had successfully logged in. Let's see what packets were involved in this transaction. Again, I've snipped the output of the tcpshow command to just show these packets:

------------------------------------------------------------
Packet 72
TIME: 10:25:43.153131 (1.174173)
LINK: 00:00:B4:3C:56:40 -> 00:50:BA:DE:36:33 type=IP
  IP: 10.0.0.2 -> 10.0.0.1 hlen=20 TOS=10 dgramlen=41 id=0037
      MF/DF=0/1 frag=0 TTL=64 proto=TCP cksum=2686
 TCP: port blackjack -> telnet seq=3205630360 ack=1746120351
      hlen=20 (data=1) UAPRSF=011000 wnd=17520 cksum=0EE3 urg=0
DATA: e
-------------------------------------------------------------

This is the first packet we've seen that actually contains some data. Even though I typed the word exit from the computer 10.0.0.2, each character I typed was sent in a separate packet. The first packet contained the letter "e".

-------------------------------------------------------------
Packet 73
TIME: 10:25:43.153685 (0.000554)
LINK: 00:50:BA:DE:36:33 -> 00:00:B4:3C:56:40 type=IP
  IP: 10.0.0.1 -> 10.0.0.2 hlen=20 TOS=10 dgramlen=41 id=956E
      MF/DF=0/1 frag=0 TTL=64 proto=TCP cksum=914E
 TCP: port telnet -> blackjack seq=1746120351 ack=3205630361
      hlen=20 (data=1) UAPRSF=011000 wnd=17520 cksum=0EE2 urg=0
DATA: e
-------------------------------------------------------------

This is the response from 10.0.0.1. Note that it acknowledged receipt of my packet as it incremented my sequence number by one. Strangely, it also returned the same data; this told the telnet client to echo the letter "e" onto my terminal.

-------------------------------------------------------------
Packet 74
TIME: 10:25:43.248672 (0.094987)
LINK: 00:00:B4:3C:56:40 -> 00:50:BA:DE:36:33 type=IP
  IP: 10.0.0.2 -> 10.0.0.1 hlen=20 TOS=10 dgramlen=40 id=0038
      MF/DF=0/1 frag=0 TTL=64 proto=TCP cksum=2686
 TCP: port blackjack -> telnet seq=3205630361 ack=1746120352
      hlen=20 (data=0) UAPRSF=010000 wnd=17520 cksum=73EA urg=0
DATA: <No data>
-------------------------------------------------------------
Packet 75
TIME: 10:25:43.456449 (0.207777)
LINK: 00:00:B4:3C:56:40 -> 00:50:BA:DE:36:33 type=IP
  IP: 10.0.0.2 -> 10.0.0.1 hlen=20 TOS=10 dgramlen=41 id=0039
      MF/DF=0/1 frag=0 TTL=64 proto=TCP cksum=2684
 TCP: port blackjack -> telnet seq=3205630361 ack=1746120352
      hlen=20 (data=1) UAPRSF=011000 wnd=17520 cksum=FBE0 urg=0
DATA: x
-------------------------------------------------------------

The next two packets again came from me at 10.0.0.2. First, I acknowledged receipt of the packet from 10.0.0.1, then I sent the letter "x" in its own packet. I won't bore you with the outputs of packets 76 to 84 as they simply repeat this process of individually sending and echoing the letters "x", "i", and "t", and acknowledging that each packet was received.

Packet 85 contains data from the telnet application running on 10.0.0.1. This application is now aware that I typed the word exit. It responds by sending me the word logout to be echoed to my terminal:

-------------------------------------------------------------
Packet 85
TIME: 10:25:44.258982 (0.011001)
LINK: 00:50:BA:DE:36:33 -> 00:00:B4:3C:56:40 type=IP
  IP: 10.0.0.1 -> 10.0.0.2 hlen=20 TOS=10 dgramlen=48 id=9573
      MF/DF=0/1 frag=0 TTL=64 proto=TCP cksum=9142
 TCP: port telnet -> blackjack seq=1746120359 ack=3205630366
      hlen=20 (data=8) UAPRSF=011001 wnd=17520 cksum=1D70 urg=0
DATA: logout.
	
-------------------------------------------------------------

Did you also notice the TCP flags field in this packet? The FIN flag has been set. Not only did the telnet application echo the word logout to my screen, it also indicated that it would "finish up" this TCP connection. At this point, my machine responded with two packets. The first acknowledged receipt of this packet, and the second agreed to the closing of the TCP connection by setting its own FIN flag:

-------------------------------------------------------------
Packet 86
TIME: 10:25:44.259292 (0.000310)
LINK: 00:00:B4:3C:56:40 -> 00:50:BA:DE:36:33 type=IP
  IP: 10.0.0.2 -> 10.0.0.1 hlen=20 TOS=10 dgramlen=40 id=003F
      MF/DF=0/1 frag=0 TTL=64 proto=TCP cksum=267F
 TCP: port blackjack -> telnet seq=3205630366 ack=1746120368
      hlen=20 (data=0) UAPRSF=010000 wnd=17512 cksum=73DD urg=0
DATA: <No data>
-------------------------------------------------------------
Packet 87
TIME: 10:25:44.260137 (0.000845)
LINK: 00:00:B4:3C:56:40 -> 00:50:BA:DE:36:33 type=IP
  IP: 10.0.0.2 -> 10.0.0.1 hlen=20 TOS=10 dgramlen=40 id=0040
      MF/DF=0/1 frag=0 TTL=64 proto=TCP cksum=267E
 TCP: port blackjack -> telnet seq=3205630366 ack=1746120368
      hlen=20 (data=0) UAPRSF=010001 wnd=17520 cksum=73D4 urg=0
DATA: <No data>
-------------------------------------------------------------

The final packet in our dump file was the very last acknowledgment from 10.0.0.1:

-------------------------------------------------------------
Packet 88
TIME: 10:25:44.260231 (0.000094)
LINK: 00:50:BA:DE:36:33 -> 00:00:B4:3C:56:40 type=IP
  IP: 10.0.0.1 -> 10.0.0.2 hlen=20 TOS=10 dgramlen=40 id=9574
      MF/DF=0/1 frag=0 TTL=64 proto=TCP cksum=9149
 TCP: port telnet -> blackjack seq=1746120368 ack=3205630367
      hlen=20 (data=0) UAPRSF=010000 wnd=17519 cksum=73D5 urg=0
DATA: <No data>
-------------------------------------------------------------

We've looked at the very beginning and very end of the TCP connection. Now let's take a look at some of the stuff that happened in between. Once the TCP connection had been established, the rest of the packets either contained data from the telnet application or were acknowledgements that the data had been received. For example, packet 21 shows the terminal type being used for this telnet connection:

-------------------------------------------------------------
Packet 21
TIME: 10:25:36.917010 (0.021554)
LINK: 00:00:B4:3C:56:40 -> 00:50:BA:DE:36:33 type=IP
  IP: 10.0.0.2 -> 10.0.0.1 hlen=20 TOS=10 dgramlen=77 id=0019
      MF/DF=0/1 frag=0 TTL=64 proto=TCP cksum=2680
 TCP: port blackjack -> telnet seq=3205630297 ack=1746119656
      hlen=20 (data=37) UAPRSF=011000 wnd=17520 cksum=5F8D urg=0
DATA: .. .115200,115200....'.......CONS25..
-------------------------------------------------------------

The ethereal utility shows even more detail regarding the data that was passed between the telnet daemon and the telnet client. Let's see how this same packet is viewed by ethereal. I've snipped the output of the packet to just show the telnet data:

Telnet
    Suboption Begin: Terminal Speed
        Here's my Terminal Speed
        Value: 115200,115200
    Command: Suboption End
    Suboption Begin: New Environment Option
        Here's my New Environment Option
        Value: 
    Command: Suboption End
    Suboption Begin: Terminal Type
        Here's my Terminal Type
        Value: CONS25
    Command: Suboption End

Several other packets were sent between the telnet daemon and the telnet application before the "login" prompt appeared. This data was used to negotiate the various telnet options, window size, terminal type, and terminal speed. Even though this data was never displayed on my screen, it is interesting to note that what was happening behind the scenes was still captured by the tcpdump utility. The tcpshow utility didn't bother to interpret this data, but the ethereal utility did. I've snipped the output of the pertinent packets to indicate who sent the packet and the data that was sent in each packet:

Frame 13 (84 on wire, 84 captured)
    Source: biko (10.0.0.2)
    Destination: genisis (10.0.0.1)
Telnet
    Command: Do Encryption Option
    Command: Will Encryption Option
    Command: Do Suppress Go Ahead
    Command: Will Terminal Type
    Command: Will Negotiate About Window Size
    Command: Will Terminal Speed
    Command: Will Remote Flow Control
    Command: Will Linemode
    Command: Will New Environment Option
    Command: Do Status

Frame 14 (57 on wire, 57 captured)
    Source: genisis (10.0.0.1)
    Destination: biko (10.0.0.2)
Telnet
    Command: Do Authentication Option

Frame 15 (60 on wire, 60 captured)
    Source: biko (10.0.0.2)
    Destination: genisis (10.0.0.1)
Telnet
    Command: Won't Authentication Option

Frame 16 (92 on wire, 92 captured)
    Source: genisis (10.0.0.1)
    Destination: biko (10.0.0.2)
Telnet
    Command: Will Encryption Option
    Command: Do Encryption Option
    Suboption Begin: Encryption Option
        Send your Encryption Option
    Command: Suboption End
    Command: Will Suppress Go Ahead
    Command: Do Terminal Type
    Command: Do Negotiate About Window Size
    Command: Do Terminal Speed
    Command: Do Remote Flow Control
    Command: Do Linemode
    Command: Do New Environment Option
    Command: Will Status

Frame 17 (130 on wire, 130 captured)
    Source: biko (10.0.0.2)
    Destination: genisis (10.0.0.1)
Telnet
    Suboption Begin: Encryption Option
        Send your Encryption Option
    Command: Suboption End
    Suboption Begin: Negotiate About Window Size
        Here's my Negotiate About Window Size
        Value: P\000\031
    Command: Suboption End
    Suboption Begin: Linemode
        Send your Linemode
    Data: \022\000
    Command: Suboption End
    Command: Do Suppress Go Ahead

Frame 18 (60 on wire, 60 captured)
    Source: genisis (10.0.0.1)
    Destination: biko (10.0.0.2)
Telnet
    Command: Do X Display Location
    Command: Do Environment Option

Frame 19 (60 on wire, 60 captured)
    Source: biko (10.0.0.2)
    Destination: genisis (10.0.0.1)
Telnet
    Command: Won't X Display Location
    Command: Won't Environment Option

Frame 20 (72 on wire, 72 captured)
    Source: genisis (10.0.0.1)
    Destination: biko (10.0.0.2)
Telnet
    Suboption Begin: Terminal Speed
        Send your Terminal Speed
    Command: Suboption End
    Suboption Begin: New Environment Option
        Send your New Environment Option
    Command: Suboption End
    Suboption Begin: Terminal Type
        Send your Terminal Type
    Command: Suboption End

Frame 22 (57 on wire, 57 captured)
    Source: genisis (10.0.0.1)
    Destination: biko (10.0.0.2)
Telnet
    Command: Do Echo

Frame 23 (60 on wire, 60 captured)
    Source: biko (10.0.0.2)
    Destination: genisis (10.0.0.1)
Telnet
    Command: Won't Echo

Frame 24 (72 on wire, 72 captured)
    Source: genisis (10.0.0.1)
    Destination: biko (10.0.0.2)
Telnet
    Command: Will Echo
    Suboption Begin: Remote Flow Control
        Here's my Remote Flow Control
        Value: 
    Command: Suboption End
    Suboption Begin: Remote Flow Control
        Send your Remote Flow Control
    Command: Suboption End
    Command: Don't Linemode

Frame 25 (60 on wire, 60 captured)
    Source: biko (10.0.0.2)
    Destination: genisis (10.0.0.1)
Telnet
    Command: Do Echo
    Command: Won't Linemode

Frame 26 (110 on wire, 110 captured)
    Source: genisis (10.0.0.1)
    Destination: biko (10.0.0.2)
Telnet
    Suboption Begin: Linemode
        Send your Linemode
    Data: \022\200
    Command: Suboption End

You'll remember from last week that when I demonstrated the telnet session, several bits of information were displayed on my screen. Those bits of information came from the telnet application on 10.0.0.1 and we can use the tcpshow utility to see it being sent in the data fields of the following packets:

-------------------------------------------------------------
Packet 28
TIME: 10:25:37.040099 (0.000144)
LINK: 00:50:BA:DE:36:33 -> 00:00:B4:3C:56:40 type=IP
  IP: 10.0.0.1 -> 10.0.0.2 hlen=20 TOS=10 dgramlen=90 id=955C
      MF/DF=0/1 frag=0 TTL=64 proto=TCP cksum=912F
 TCP: port telnet -> blackjack seq=1746119733 ack=3205630343
      hlen=20 (data=50) UAPRSF=011000 wnd=17520 cksum=2DFE urg=0
DATA: ...
      FreeBSD/i386 (istar.ca) (ttyp0)...
      ...
      login: 
-------------------------------------------------------------
Packet 51
TIME: 10:25:39.140175 (0.012092)
LINK: 00:50:BA:DE:36:33 -> 00:00:B4:3C:56:40 type=IP
  IP: 10.0.0.1 -> 10.0.0.2 hlen=20 TOS=10 dgramlen=51 id=9564
      MF/DF=0/1 frag=0 TTL=64 proto=TCP cksum=914E
 TCP: port telnet -> blackjack seq=1746119790 ack=3205630352
      hlen=20 (data=11) UAPRSF=011000 wnd=17520 cksum=815F urg=0
DATA: .
    Password:
-------------------------------------------------------------
Packet 66
TIME: 10:25:41.680125 (0.020455)
LINK: 00:50:BA:DE:36:33 -> 00:00:B4:3C:56:40 type=IP
  IP: 10.0.0.1 -> 10.0.0.2 hlen=20 TOS=10 dgramlen=150 id=956B
      MF/DF=0/1 frag=0 TTL=64 proto=TCP cksum=90E4
 TCP: port telnet -> blackjack seq=1746119801 ack=3205630360
      hlen=20 (data=110) UAPRSF=011000 wnd=17520 cksum=AE21 urg=0
DATA: .
    Warning: your password expires on Thu Mar  8 17:31:47 2001.
    Last login: Sun Mar  4 10:23:04 from 127.0.0.1.
	
-------------------------------------------------------------
Packet 68
TIME: 10:25:41.779159 (0.000175)
LINK: 00:50:BA:DE:36:33 -> 00:00:B4:3C:56:40 type=IP
  IP: 10.0.0.1 -> 10.0.0.2 hlen=20 TOS=10 dgramlen=283 id=956C
      MF/DF=0/1 frag=0 TTL=64 proto=TCP cksum=905E
 TCP: port telnet -> blackjack seq=1746119911 ack=3205630360
      hlen=20 (data=243) UAPRSF=011000 wnd=17520 cksum=30D1 urg=0
DATA: Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
    .
    The Regents of the University of California.  All rights re
    served..
    .
    FreeBSD 4.2-RELEASE (SOUND) #0: Tue Dec 12 20:01:29 EST 2000
    .
    .
                Welcome to FreeBSD 4.2!!!.
    You have mail..
	
-------------------------------------------------------------
Packet 70
TIME: 10:25:41.879117 (0.000163)
LINK: 00:50:BA:DE:36:33 -> 00:00:B4:3C:56:40 type=IP
  IP: 10.0.0.1 -> 10.0.0.2 hlen=20 TOS=10 dgramlen=237 id=956D
      MF/DF=0/1 frag=0 TTL=64 proto=TCP cksum=908B
 TCP: port telnet -> blackjack seq=1746120154 ack=3205630360
      hlen=20 (data=197) UAPRSF=011000 wnd=17520 cksum=DDC6 urg=0
DATA: .
    Everybody is somebody else's weirdo..
            -- Dykstra.
    .[1mgenisis@~.[m: 
-------------------------------------------------------------

You may have noticed there were many packets that I snipped out between Packet 28, which echoed the login prompt; and Packet 51, wwhich echoed the password prompt. These packets required sending the login name of "genisis" one character at a time. Again, each of these characters needed to be individually acknowledged and echoed to my screen.

The packets between Packet 51 and Packet 66 contained my password -- again sent one character at a time. These packets were acknowledged but the characters were not echoed to my terminal. This is one of the reasons why you don't run a tcpdump on someone else's network. If someone happens to login over the network, you will be able to capture and view the packets which contain the login and password prompts followed by the user's login name and password. At that point, it won't matter how good the password policy is on that network.

Finally, Packets 66, 68, and 70 showed the rest of the data from the telnet application that was echoed to my terminal during the session.

So far, we've only examined the packets that contained TCP headers. However, TCP was not the only protocol involved during this telnet session; the protocols ARP and ICMP also played a role.

Let's start with ARP or the Address Resolution Protocol. We've learned that before we can send an IP packet, it must first be encapsulated into a frame, in our case, an Ethernet frame. To create an Ethernet frame, the MAC (Media Access Control) address of the destination NIC must first be determined. A special packet known as an ARP packet is used to determine this MAC address. Since ARP knows the IP address of the destination, it can send out a broadcast packet, meaning all nodes must read the packet, asking for the MAC address associated with that IP address. Running tcpdump with the r switch summarizes this procedure nicely:

tcpdump -r dump
<snip output to just show packets 2 and 3>

10:25:28.608173 arp who-has 10.0.0.1 tell 10.0.0.2
10:25:28.608285 arp reply 10.0.0.1 is-at 0:50:ba:de:36:33

Because 10.0.0.2 wished to initiate a TCP connection with 10.0.0.1, it sent out an ARP request asking who was using that IP address. You'll notice that it received a reply that included the MAC address associated with 10.0.0.1.

Let's look at a more detailed view of these two packets using tcpshow:

tcpshow < dump
<snip to just show packets 2 and 3>

-------------------------------------------------------------
Packet 2
TIME:	10:25:28.608173 (4.305875)
LINK:	00:00:B4:3C:56:40 -> FF:FF:FF:FF:FF:FF type=ARP
ARP:	htype=Ethernet ptype=IP hlen=6 plen=4 op=request
	sender-MAC-addr=00:00:B4:3C:56:40 sender-IP-address=10.0.0.2
	target-MAC-addr=00:00:00:00:00:00 target-IP-address=10.0.0.1
-------------------------------------------------------------
Packet 3
TIME:	10:25:28.608285 (0.000112)
LINK:	00:50:BA:DE:36:33 -> 00:00:B4:3C:56:40 type=ARP
ARP:	htype=Ethernet ptype=IP hlen=6 plen=4 op=response
	sender-MAC-addr=00:50:BA:DE:36:33 sender-IP-address=10.0.0.1
	target-MAC-addr=00:00:B4:3C:56:40 target-IP-address=10.0.0.2
-------------------------------------------------------------

Notice the MAC addresses used in the LINK section of Packet 2. The source address is the MAC address of 10.0.0.2. This is needed so the response can make it back to the correct NIC. Since 10.0.0.2 does not know the MAC address of 10.0.0.1 (finding that MAC address is the whole point of this ARP packet), it uses a MAC address of FF:FF:FF:FF:FF:FF. A MAC address of all Fs indicates a broadcast packet, meaning all NICs must process the packet, but only the NIC the data pertains to should respond.

Also note that an ARP packet is different than an IP packet. It only contains one header and no data. There is a diagram of an ARP packet here.

The hardware type (htype) indicates this ARP request is looking for an Ethernet hardware address, that is, a MAC address. The protocol type (ptype) indicates the protocol address in use is an IP address. The operation (op) field indicates this is an ARP request. It then contains the known MAC and IP addresses. Because the target MAC address is the unknown value, it has been set to all zeros.

Packet 3 contains the response to Packet 2. Its op field indicates that it is a response, and it contains all of the necessary MAC addresses.

Let's wait until next week to see what role ICMP played in our telnet session as the ICMP protocol deserves an article of its own.

Dru Lavigne is a network and systems administrator, IT instructor, author and international speaker. She has over a decade of experience administering and teaching Netware, Microsoft, Cisco, Checkpoint, SCO, Solaris, Linux, and BSD systems. A prolific author, she pens the popular FreeBSD Basics column for O'Reilly and is author of BSD Hacks and The Best of FreeBSD Basics.


Read more FreeBSD Basics columns.

Return to the BSD DevCenter.

Copyright © 2009 O'Reilly Media, Inc.