Networking

The TCP 3-Way handshake

Hey there fellow learners πŸ™‚

The purpose of today’s post is to shed light on the TCP 3-Way handshake. Everyone knows what TCP is and what are the benefits and/or features that it offers.

But very few understand the mechanics of how TCP can achieve all its awesomeness.

Today I’m going to jump into the depths TCP 3-Way Handshake. This might take a while, but I guarantee that I will be worth your while.

The 3-Way handshake is how TCP establishes a connection with a peer. The process is so simple that it often causes an administrator to overlook some of the essential parameters.

Below I will try to detail as much as I can and deconstruct the what’s and why’s of the entire process.

Why does TCP do this?

TCP is a connection-oriented protocol, this means that it has a way of tracking and ensuring data that was sent is received. It does this through a numbering system called Sequence Numbers. This coupled with other parameters and subsystems ensure reliability.

The 3-Way handshake is used by each TCP peer to make their counterpart aware of its supported capabilities to ensure that a common ground it met.

  • 1st Segment: The initiator sends out a list of set parameters and supported options.
  • 2nd Segment: The receiver Acknowledges the initiator’s packet and piggybacks its list of parameters and supported options.
  • 3rd Segment: The initiator Acknowledges the received packet.


TCP 3-Way Handshake Illustration

How this looks on the wire.

1 10:17:52 PM 12/3/2018 10.171.80.226 172.23.176.89 TCP TCP:Flags=......S., SrcPort=57585, DstPort=Microsoft-DS(445), PayloadLen=0, Seq=1960785164, Ack=0, Win=8192 ( Negotiating scale factor 0x8 ) = 8192
# Expanding:
Frame: Number = 1, Captured Frame Length = 90, MediaType = ETHERNET
+ Ethernet: Etype = Internet IP (IPv4),DestinationAddress:[00-12-DA-7E-7A-C0],SourceAddress:[78-2B-CB-AD-41-49]
+ Ipv4: Src = 10.171.80.226, Dest = 172.23.176.89, Next Protocol = ESP, Packet ID = 10447, Total IP Length = 76
+ Esp: Next Protocol = TCP, SPI = 0xabb45be1, Seq = 0x1
- Tcp: Flags=......S., SrcPort=57585, DstPort=Microsoft-DS(445), PayloadLen=0, Seq=1960785164, Ack=0, Win=8192 ( Negotiating scale factor 0x8 ) = 8192
SrcPort: 57585
DstPort: Microsoft-DS(445)
SequenceNumber: 1960785164 (0x74DF350C)
AcknowledgementNumber: 0 (0x0)
+ DataOffset: 128 (0x80)
+ Flags: ......S.
Window: 8192 ( Negotiating scale factor 0x8 ) = 8192
Checksum: 0xA78, Good
UrgentPointer: 0 (0x0)
- TCPOptions: # These are the TCP Options, we will describe them more later.
- MaxSegmentSize: 1
type: Maximum Segment Size. 2(0x2)
OptionLength: 4 (0x4)
MaxSegmentSize: 1460 (0x5B4) # MSS = MTU – (TCP + IP Header). I.E: Default MTU for Ethernet [CAT5/6 Cable] is 1500bytes, the TCP Header and the IP Header are both 20bytes each. Hence 1460 = 1500 – (20 + 20)
+ NoOption:
- WindowsScaleFactor: ShiftCount: 8
type: Window scale factor. 3(0x3)
Length: 3 (0x3)
ShiftCount: 8 (0x8)
+ NoOption:
+ NoOption:
- SACKPermitted:
type: SACK permitted. 4(0x4)
OptionLength: 2 (0x2)
2 10:17:52 PM 12/3/2018 172.23.176.89 10.171.80.226 TCP TCP:Flags=...A..S., SrcPort=Microsoft-DS(445), DstPort=57585, PayloadLen=0, Seq=2549695584, Ack=1960785165, Win=16384 ( Negotiated scale factor 0x0 ) = 16384
# Expanding:
Frame: Number = 2, Captured Frame Length = 94, MediaType = ETHERNET
+ Ethernet: Etype = Internet IP (IPv4),DestinationAddress:[78-2B-CB-AD-41-49],SourceAddress:[00-12-DA-7E-7A-C0]
+ Ipv4: Src = 172.23.176.89, Dest = 10.171.80.226, Next Protocol = ESP, Packet ID = 18259, Total IP Length = 80
+ Esp: Next Protocol = TCP, SPI = 0x5ed887bb, Seq = 0x1
- Tcp: Flags=...A..S., SrcPort=Microsoft-DS(445), DstPort=57585, PayloadLen=0, Seq=2549695584, Ack=1960785165, Win=16384 ( Negotiated scale factor 0x0 ) = 16384
SrcPort: Microsoft-DS(445)
DstPort: 57585
SequenceNumber: 2549695584 (0x97F94460)
AcknowledgementNumber: 1960785165 (0x74DF350D) # That is the ACK for the SEQ in Frame 1. Notice that the number increments only by 1 since there is no payload as of yet.
+ DataOffset: 128 (0x80)
+ Flags: ...A..S.
Window: 16384 ( Negotiated scale factor 0x0 ) = 16384
Checksum: 0xE15, Good
UrgentPointer: 0 (0x0)
- TCPOptions: # These are the TCP Options, we will describe them more later.
- MaxSegmentSize: 1
type: Maximum Segment Size. 2(0x2)
OptionLength: 4 (0x4)
MaxSegmentSize: 1460 (0x5B4) # MSS = MTU ß (TCP + IP Header). I.E: Default MTU for Ethernet [CAT5/6 Cable] is 1500bytes, the TCP Header and the IP Header are both 20bytes each. Hence 1460 = 1500 – (20 + 20)
+ NoOption:
- WindowsScaleFactor: ShiftCount: 0
type: Window scale factor. 3(0x3)
Length: 3 (0x3)
ShiftCount: 0 (0x0)
+ NoOption:
+ NoOption:
- SACKPermitted:
type: SACK permitted. 4(0x4)
OptionLength: 2 (0x2)
3 10:17:52 PM 12/3/2018 10.171.80.226 172.23.176.89 TCP TCP:Flags=...A...., SrcPort=57585, DstPort=Microsoft-DS(445), PayloadLen=0, Seq=1960785165, Ack=2549695585, Win=261 (scale factor 0x8) = 66816
# Expanding:
Frame: Number = 3, Captured Frame Length = 78, MediaType = ETHERNET
+ Ethernet: Etype = Internet IP (IPv4),DestinationAddress:[00-12-DA-7E-7A-C0],SourceAddress:[78-2B-CB-AD-41-49]
+ Ipv4: Src = 10.171.80.226, Dest = 172.23.176.89, Next Protocol = ESP, Packet ID = 10448, Total IP Length = 64
+ Esp: Next Protocol = TCP, SPI = 0xabb45be1, Seq = 0x2
- Tcp: Flags=...A...., SrcPort=57585, DstPort=Microsoft-DS(445), PayloadLen=0, Seq=1960785165, Ack=2549695585, Win=261 (scale factor 0x8) = 66816
SrcPort: 57585
DstPort: Microsoft-DS(445)
SequenceNumber: 1960785165 (0x74DF350D)
AcknowledgementNumber: 2549695585 (0x97F94461) # That is the ACK for the SEQ in Frame 1. Notice that the number increments only by 1 since there is no payload as of yet.
+ DataOffset: 80 (0x50)
+ Flags: ...A....
Window: 261 (scale factor 0x8) = 66816
Checksum: 0x8DDB, Good
UrgentPointer: 0 (0x0)

Things to remember:

  • The 3-Way handshake is used to indicate to the peer the Initial Sequence Number (ISN), this is done by setting Synchronize (SYN) flag.
  • Each peer sends out its supported options, only those options that are common to both will be used during the conversation.
  • You should always know the MSS being set and keep a close watch on the Window Size being advertised.

Breaking down the TCP header

To better understand TCP, one must understand the all the bits and pieces of the TCP header.

The TCP header has a lot of parameters and options packed into them.


Details of the header:

  • Source Port
    • A 2-byte field that indicates the source Application’s port that is sending the TCP Segment.
    • The combinations of the Source IP Address in the IP header and the Source Port in the TCP header indicates a source socket.
  • Destination Port
    • A 2-byte field that indicates the destination Application’ port that is to receive the TCP Segment.
    • The combination of the destination IP Address in the IP Header and the destination port in the TCP header indicates a destination socket.
  • Sequence Number
    • A 4-byte fields that indicates the outgoing byte-stream-based sequence number of the segment’s first byte.
    • This field is always set, even when there is no data in the segment.
    • The Sequence Number field is set to the number of the outgoing byte stream’s next byte.
    • When establishing a TCP connection, TCP segments with a SYN flag set the Sequence Number field to the ISN.
    • This indicates that the first byte in the outgoing byte stream on the connection is ISN+1
  • Acknowledgement Number
    • A 4-byte field that indicates the Sequence Number of the next byte that the receiver expects to receiver.
    • The ACK number provides a positive acknowledgement number that all bytes, but now including, the ACK number were received.
    • The ACK number is significant in all TCP segments with the ACK flag set.
  • Data Offset
    • A 4-bit field that indicates where the TCP Segment data begins.
    • This field is also the TCP Header’s size.
    • This field is the number of 32-bit words (4-byte blocks) in the TCP header.
    • The smallest TCP header (no options): The size is set to 0x5 (20-bytes).
    • The largest TCP header: The size is 0x15 (60-bytes).
  • Reserved
    • A 4-bit field that is reserved for future use.
    • The sender sets bits to 0.
  • Flags
    • An 8-bit field that indicates the eight TCP flags defined in RFCs 793 and 9168.
    • These flags are:
      • CWR : Congestion Windows Reduced
      • ECE : Explicit Congestion Notification [ECN]-Echo
      • URG : Urgent
      • ACK : Acknowledgement
      • PSH : Push
      • RST : Reset
      • SYN : Synchronize
      • FIN : Finish
  • Window Size
    • A 2-byte field that indicates the number of bytes that the receiver allows the other TCP peer to send.
    • By advertising the window size with each segment, a TCP receiver is telling the sender how much data can be sent, successfully received and stored.
    • The sender should not be sending more data than the receiver can receive.
    • If the receiver cannot receive more data, it advertises a window size of 0.
    • A sender cannot send any more data until the window size is a non-zero number.
    • The advertisement of the window size is an implementation of receiver-side flow control.
    • The use of this field is extended to larger window sizes with the TCP Windows Scale option.
  • Checksum
    • A 2-byte field that provides a bit-level integrity check for the TCP segment (Header + Segment).
    • The checksum field’s value is calculated in the same way as the IP Header checksum, over all the 16-bit words in a TCP pseudo header, the TCP header, the segment, and, if needed, a padding byte of 0x00.
    • The padding byte is used only if the segment length is an odd number of bytes.
    • The value of the checksum is set to 0 during the checksum calculation.
  • Urgent Pointer
    • A 2-byte field that indicates the location of urgent data in the segment.
  • Options and Padding
    • One or more TCP options can be added to the TCP header but must be done in 4-byte increments so that the TCP header size can be indicated with the Data Offset field.

How this Sequencing thing works.

When the sender transmits a TCP packet, the SEQ number indicates the first byte of data in the data-stream. Since TCP strives for efficiency, it always try to fill up the packet. For ethernet this means each packet will have a maximum payload of 1460. Whenever data is being sent, the SEQ number field will be a range of numbers, indicating the first and last byte of the data in the packet.

The sequence number will increment every time a data payload is sent in a packet, it will increment by the number of bytes being transmitted. In a TCP conversation, you will be able to determine the size of data being sent by making a note of the first sequence number in a packet with data and subtracting it from last sequence number at the end of the conversation. Knowing how to do this can be particularly useful when analyzing encrypted date streams, especially since you cannot see the data inside.

A receiver will always ACK a received TCP packet, by indicating to the sender the next SEQ it expects. For example: if the sender sent SEQ 5000-5460, the receiver will ACK 5461. This tells the sender that everything from the ISN up to 5460 was received and processed successfully, and that receiver expects data from 5461 onwards.

Sequencing and Retransmissions

When TCP sends out any packet, it starts a timer called the Retransmission Timeout (RTO). This is a dynamically calculated value that indicates how long a packet should take to get from the Sender to the Receiver and its corresponding ACK sent back. If for any reason, a sent packet is lost and not received by the Receiving Peer, or the ACK is not received by the Sender, the packet will be retransmitted after the RTO expires. Generally, the Sender and Receiver will wait for the RTO to expire before either retransmitting or re-requesting the packet. However, If the Receiver needs the packet immediately to reassemble the data before pushing it up the TCP stack, it will ask for the lost packet right away, by ACK’ing the previous packet. This is called a Request-For-Fast-Retransmit. When the Sender sees an ACK for a packet that was already ACK’ed (this is called a duplicate ACK), it will send out the requested packet right away. This is called a Fast-Retransmission.

Now, since the RTO is dynamically calculated, a couple of packets will need to be exchanged for the calculation to be reliable. However, if the first packet, i.e. SYN, its self is lost, TCP will use the Initial RTO.

The Initial RTO is set to 3000ms or 3secs.

So, in essence during the 3-Way Handshake, when the SYN packets are sent an RTO of 3000ms is used. If a response is not received for the SYN, the sender will retransmit the SYN packet after the RTO expires and double the time. A TCP Peer will try 3 attempts to setup a connection, if there is no success the connection is abandoned.

RTO for Connection Establishment:

  • Attempt 1: Wait 3 seconds.
  • Attempt 2: Wait 6 seconds.
  • Attempt 3: Wait 12 seconds.
  • Connection is abandoned after 21secs.

Here is how it looks on the wire!

1 11:59:46 AM 0.00 192.168.1.10 192.168.1.12 TCP TCP: [Bad CheckSum]Flags=CE....S., SrcPort=65076, DstPort=MS WBT Server(3389), PayloadLen=0, Seq=2978535055, Ack=0, Win=8192 ( Negotiating scale factor 0x8 ) = 8192
2 11:59:49 AM 3.00 192.168.1.10 192.168.1.12 TCP TCP:[SynReTransmit #1064] [Bad CheckSum]Flags=CE....S., SrcPort=65076, DstPort=MS WBT Server(3389), PayloadLen=0, Seq=2978535055, Ack=0, Win=8192 ( Negotiating scale factor 0x8 ) = 8192
3 11:59:55 AM 6.01 192.168.1.10 192.168.1.12 TCP TCP:[SynReTransmit #1064] [Bad CheckSum]Flags=......S., SrcPort=65076, DstPort=MS WBT Server(3389), PayloadLen=0, Seq=2978535055, Ack=0, Win=8192 ( Negotiating scale factor 0x8 ) = 8192

I think this is enough for today! Keep a watch out for more posts of the mechanics of TCP.

If you want to read more into this, I’d recommend reading the Windows Server 2008 TCP/IP Protocols and Services from Joseph Davies. This book has been my bible for many years.

Coming soon:

  • TCP Window Scale Factor and Windows Size
  • TCP Flags
  • TCP Options
  • TCP Window Scale Facor and Windows Size
  • TCP Flow Control and Congestion Control

Additional References:

2 Comments

  • Marc-AndrΓ© Beaulieu

    Hi, I know I am 2 years late, but it looks like, in the first picture, for the Segment 2, the SEQ and the ACK numbers have been exchanged… I think it should be “ACK.. SYN, SEQ: ISN2, ACK: ISN1 + 1” instead !

    Correct me if I am wrong, I am really new to this !