TCP Three-Way Handshake
SYN: The Synchronize Segment
Read aloud is unavailable in this browser.
The Beginning of Every TCP Conversation
Every reliable connection on the Internet—every web page you load, every file you download, every video stream you watch—begins with a single, carefully crafted packet: the SYN segment. This unassuming 40-byte message initiates a sophisticated dance between two machines, establishing the foundation for reliable, ordered, and error-checked communication.
The SYN (Synchronize) segment represents the client's request to initiate a connection. It carries critical information: a proposed starting sequence number, connection parameters, and optional capabilities. Understanding the SYN segment isn't just academic—it's essential for debugging connection issues, analyzing security attacks, and comprehending why TCP behaves the way it does under various network conditions.
By the end of this page, you will understand the complete purpose and structure of the SYN segment, the critical role of Initial Sequence Numbers (ISN), how SYN packets are constructed and processed, security implications of the synchronization process, and how to analyze SYN segments in real network captures.
The Purpose of Synchronization
Before TCP can begin reliable data transfer, both endpoints must establish a synchronized understanding of key connection parameters. This synchronization serves multiple critical purposes:
Why Can't TCP Just Start Sending Data?
Unlike UDP, which operates in a fire-and-forget mode, TCP guarantees reliable, ordered delivery. To achieve this, TCP must:
- Establish bidirectional communication — Both sides must confirm they can send and receive
- Agree on sequence numbers — Each side must know where the other will begin numbering bytes
- Negotiate connection parameters — Window sizes, maximum segment sizes, and optional features must be agreed upon
- Allocate resources — Both endpoints must reserve memory buffers and data structures for the connection
Without synchronization, TCP would have no way to detect lost packets (no reference point for sequence numbers), no ability to reorder out-of-sequence arrivals, and no agreement on how much data can be in flight.
Imagine calling someone on the telephone. You don't immediately start talking—you wait for them to answer and confirm they can hear you. The SYN is equivalent to dialing the phone: it's a request to establish communication. The subsequent SYN-ACK is the recipient picking up and saying 'Hello,' and your ACK is you confirming 'I can hear you too.' Only then does the actual conversation begin.
The Synchronization Problem:
Consider what happens if a client simply started sending data without synchronization:
- The server has no connection state—it doesn't know this client wants to communicate
- Sequence numbers would be meaningless without an agreed starting point
- Old packets from previous connections might be mistaken for new ones
- The server has no receive buffer allocated for this client's data
- No agreement exists on parameters like maximum segment size
The SYN segment solves all these problems by explicitly establishing a connection context before any data transfer occurs.
The SYN Flag in the TCP Header
The TCP header contains a set of control flags (also called control bits) that indicate the purpose and state of each segment. The SYN flag is one of six primary flags defined in the original TCP specification, each occupying a single bit in the header.
The Six Primary TCP Flags:
| Flag | Bit Position | Purpose | Used In |
|---|---|---|---|
| URG (Urgent) | Bit 5 | Urgent pointer field is valid | Priority data delivery |
| ACK (Acknowledgment) | Bit 4 | Acknowledgment number field is valid | Almost all segments after initial SYN |
| PSH (Push) | Bit 3 | Push buffered data to application | Interactive applications |
| RST (Reset) | Bit 2 | Reset the connection abruptly | Error conditions, rejected connections |
| SYN (Synchronize) | Bit 1 | Synchronize sequence numbers | Connection establishment |
| FIN (Finish) | Bit 0 | Sender has finished sending data | Connection termination |
The SYN Flag's Special Semantics:
When the SYN flag is set (bit value = 1), the segment has special meaning:
- Sequence Number Initialization — The sequence number field contains the Initial Sequence Number (ISN) that this endpoint will use
- No Payload Expected — Pure SYN segments carry no application data (though the specification technically allows it)
- Connection State Transition — Receipt of a SYN causes the receiver to transition to a specific state in the TCP state machine
- Resource Allocation Trigger — The receiver must allocate resources (Transmission Control Block) for the new connection
Flag Combinations:
The SYN flag can appear alone (pure SYN) or in combination with the ACK flag (SYN-ACK). However, certain combinations are invalid or suspicious:
| Combination | Purpose | Validity |
|---|---|---|
| SYN only | Initial connection request from client | Valid — standard first packet |
| SYN + ACK | Server's response to client SYN | Valid — standard second packet |
| SYN + FIN | Request to establish and immediately close | Invalid — never legitimate, often attack signature |
| SYN + RST | Impossible state: establish and reset | Invalid — malformed packet |
| SYN + URG | Sync with urgent data pointer | Highly unusual — suspicious |
| SYN + PSH | Sync with push request | Unusual — may indicate evasion attempt |
Packets with unusual flag combinations (like SYN+FIN or SYN+RST) are often used in network scanning, OS fingerprinting, and IDS evasion attempts. Legitimate TCP implementations never generate such packets. Security tools and firewalls should flag these as suspicious.
Initial Sequence Numbers: The Foundation of Reliability
The Initial Sequence Number (ISN) carried in the SYN segment is perhaps the most critical value in TCP connection establishment. This 32-bit number serves as the starting reference point for all subsequent byte counting in that direction of communication.
Why Not Just Start at Zero?
A naive implementation might set the ISN to 0 for every connection. This approach fails catastrophically for several reasons:
-
Old Duplicate Problem — Consider a client connecting to a server, sending data with sequences 0-1000, then the connection dies. If a new connection also starts at 0, old packets still wandering the network could be misinterpreted as new.
-
Security Vulnerability — Predictable ISNs allow attackers to inject packets into connections they're not part of. If an attacker knows the expected sequence number, they can forge packets that the receiver will accept.
-
Connection Disambiguation — The same client-server pair might establish multiple connections over time. Unique ISNs help distinguish between these connections.
TCP sequence numbers occupy 32 bits, providing a range of 0 to 4,294,967,295 (2³² - 1). When this space is exhausted, it wraps around to 0. For a 1 Gbps connection, wrap-around occurs approximately every 34 seconds, which is why additional mechanisms like PAWS (Protection Against Wrapped Sequences) are needed for high-speed networks.
ISN Generation Strategies:
The evolution of ISN generation reflects advancing understanding of both reliability and security requirements:
| Era | Method | Mechanism | Weakness |
|---|---|---|---|
| Early TCP (RFC 793) | Time-based increment | ISN = clock-based counter incremented every 4μs | Predictable; enables sequence prediction attacks |
| 1990s improvements | Random offset per host pair | Base ISN + hash(src, dst, ports) | Better, but still some predictability |
| Modern (RFC 6528) | Cryptographic randomization | Secret key + hash function (MD5/SHA) | Unpredictable to outsiders; prevents injection |
Modern ISN Generation (RFC 6528):
Contemporary implementations generate ISNs using a formula similar to:
ISN = M + F(src_ip, src_port, dst_ip, dst_port, secret_key)
Where:
- M is a monotonically increasing value (typically from a counter incremented every 4 microseconds)
- F is a cryptographic hash function (commonly MD5 or a keyed HMAC)
- secret_key is a randomly generated key known only to the host, changed periodically
This approach ensures:
- Randomness to outsiders — Without the secret key, ISNs appear completely random
- Consistency for legitimate connections — The same socket pair gets the same ISN offset, preventing old duplicates
- Forward progress — The counter M ensures ISNs always increase over time globally
In 1994, Kevin Mitnick exploited predictable ISNs to conduct one of the most famous attacks in computer security history. By predicting the ISN a server would use, he could inject packets into an existing connection without seeing any responses. Modern random ISN generation makes this attack infeasible—predicting a 32-bit cryptographically random value requires on average 2³¹ guesses.
Complete Structure of the SYN Segment
A SYN segment is a complete TCP segment with specific field values that mark it as a connection initiation request. Let's examine every field in a typical SYN segment:
| Field | Size | SYN Value | Explanation |
|---|---|---|---|
| Source Port | 16 bits | Ephemeral port (e.g., 54321) | Client's randomly assigned high port |
| Destination Port | 16 bits | Service port (e.g., 80, 443) | Well-known or registered port for target service |
| Sequence Number | 32 bits | ISN (e.g., 0x1A2B3C4D) | Client's Initial Sequence Number |
| Acknowledgment Number | 32 bits | 0 (ignored) | Not valid—SYN has no prior segment to acknowledge |
| Data Offset | 4 bits | 5-15 (in 32-bit words) | Header length; typically 10+ with options |
| Reserved | 4 bits | 0 | Reserved for future use |
| Flags | 8 bits | 0x02 (SYN only) | Only SYN flag set |
| Window Size | 16 bits | Receive window (e.g., 65535) | Initial receive buffer size advertisement |
| Checksum | 16 bits | Computed value | Integrity check including pseudo-header |
| Urgent Pointer | 16 bits | 0 (ignored) | Not valid when URG flag not set |
| Options | Variable | MSS, SACK, Window Scale, etc. | Capability negotiation (explained below) |
| Padding | Variable | Zeros | Pad to 32-bit boundary |
Critical Observations:
-
Acknowledgment Number is Meaningless — In a pure SYN (not SYN-ACK), the ACK flag is not set, so the acknowledgment number field has no semantic meaning. Implementations typically set it to 0.
-
Sequence Number Represents a Byte — Although this SYN segment carries no data, the ISN in the sequence field represents a 'virtual byte.' The SYN itself consumes one sequence number, so if ISN = 1000, the first data byte will have sequence number 1001.
-
Window Size is Initial Advertisement — The client declares how much data it's willing to receive in its initial buffer. This may be adjusted by Window Scale option.
-
Options are Critical — Modern TCP heavily relies on options negotiated during the handshake. Without proper options, connections may perform poorly.
Even though the SYN segment carries no application data, it 'consumes' one sequence number. This is crucial for reliability: the SYN-ACK acknowledges receipt of the SYN by setting ACK = client_ISN + 1. Similarly, FIN segments also consume a sequence number. This allows reliable acknowledgment of control messages, not just data.
TCP Options in the SYN Segment
The SYN segment is the only opportunity for a TCP endpoint to advertise optional capabilities to its peer. Options that aren't negotiated during the handshake cannot be used for the duration of the connection. This makes option selection in the SYN critically important.
Common Options in SYN Segments:
| Option | Kind | Length | Purpose | Importance |
|---|---|---|---|---|
| Maximum Segment Size (MSS) | 2 | 4 bytes | Maximum segment size sender can receive | Critical — avoids fragmentation |
| Window Scale | 3 | 3 bytes | Multiplier for window size (enables >64KB windows) | Essential for high bandwidth-delay networks |
| SACK Permitted | 4 | 2 bytes | Enables selective acknowledgments | Critical for loss recovery efficiency |
| Timestamps (TSopt) | 8 | 10 bytes | RTT measurement, PAWS protection | Important for performance, security |
| No-Operation (NOP) | 1 | 1 byte | Padding for option alignment | Structural |
| End of Options | 0 | 1 byte | Marks end of option list | Structural |
Deep Dive: Maximum Segment Size (MSS):
The MSS option is arguably the most important SYN option. It declares the largest segment (TCP header + data) the sender is willing to receive. This prevents the peer from sending segments that would require fragmentation.
MSS Calculation:
MSS = MTU - IP_Header_Size - TCP_Header_Size
= 1500 - 20 - 20
= 1460 bytes (typical for Ethernet + IPv4)
For IPv6:
MSS = MTU - IPv6_Header_Size - TCP_Header_Size
= 1500 - 40 - 20
= 1440 bytes (typical for Ethernet + IPv6)
If MSS option is absent, the default MSS is 536 bytes (576-byte minimum IPv4 MTU minus 40 bytes of headers). This severely limits performance, which is why all modern implementations include MSS.
The base TCP window field is only 16 bits, limiting the advertised receive window to 65,535 bytes. For a connection with 100ms RTT, this caps throughput at ~5 Mbps—unacceptable for modern networks. The Window Scale option adds a multiplier (shift count) of 0-14, allowing windows up to 1 GB. Without Window Scale negotiated in the SYN, the connection is permanently limited to 64KB windows.
Option Negotiation Rules:
-
Both sides must agree — If the server's SYN-ACK doesn't include a capability option that the client's SYN included, that capability is not available for the connection
-
Capabilities are per-connection — Each new connection must renegotiate options; they don't persist
-
Options have size limits — Total TCP header including options cannot exceed 60 bytes (15 × 32-bit words), limiting how many options can be included
-
Order doesn't matter — Options can appear in any order, though NOP padding is commonly used for alignment
The Transmission Control Block (TCB)
When a TCP endpoint sends a SYN (client) or receives a SYN (server), it must allocate a data structure to track the connection state. This structure is called the Transmission Control Block (TCB)—the kernel's representation of a TCP connection.
What the TCB Contains:
The TCB stores all information needed to manage the connection:
- •Local IP address
- •Local port number
- •Remote IP address
- •Remote port number
- •Connection state (SYN_SENT, ESTABLISHED, etc.)
- •SND.UNA — Oldest unacknowledged sequence number
- •SND.NXT — Next sequence number to send
- •SND.WND — Send window (peer's receive window)
- •SND.WL1 — Sequence for last window update
- •SND.WL2 — Acknowledgment for last window update
- •ISS — Initial Send Sequence number
- •RCV.NXT — Next expected sequence number
- •RCV.WND — Receive window (local buffer space)
- •IRS — Initial Receive Sequence number
- •Send buffer (data waiting to be sent)
- •Receive buffer (data waiting for application)
- •Retransmission queue (sent but unacknowledged)
- •Retransmission timer
- •Keepalive timer
- •TIME_WAIT timer
TCB Creation During Handshake:
Client Side (Active Open):
- Application calls
connect() - Kernel creates TCB, sets ISS (Initial Send Sequence)
- Kernel sends SYN with ISS
- TCB state transitions to
SYN_SENT - Kernel stores ISS in TCB, waits for SYN-ACK
Server Side (Passive Open):
- Application calls
listen() - SYN arrives from client
- Kernel creates TCB (or queues SYN in some implementations)
- Kernel extracts client's ISN, stores as IRS
- Kernel generates its own ISS
- Sends SYN-ACK with server's ISS, acknowledges client's ISN
- TCB state transitions to
SYN_RECEIVED
Each SYN received causes TCB allocation on the server. An attacker sending millions of SYN packets from spoofed IP addresses can exhaust server memory with half-open TCBs waiting for ACKs that will never arrive. This is the classic SYN flood attack. Modern defenses include SYN cookies (stateless until handshake completes) and SYN proxy/filtering.
SYN Segment Processing: Step by Step
When a SYN segment arrives at a host, the TCP implementation follows a precise processing sequence. Understanding this sequence is essential for diagnosing connection problems and understanding security mechanisms.
- •Receive and Demultiplex — IP layer delivers segment to TCP; TCP uses destination port to find matching listening socket
- •Validate Destination — Check if any socket is listening on the destination port. If not, send RST (Connection Refused)
- •Check Firewall/Filter Rules — Apply any packet filter rules. If blocked, silently drop or send RST
- •Verify Checksum — Compute TCP checksum including pseudo-header. If invalid, silently discard segment
- •Extract Connection Parameters — Parse source/destination IPs and ports to identify the requesting socket
- •Check for Existing Connection — If a TCB already exists for this 4-tuple, handle as duplicate SYN (see edge cases)
- •Apply SYN Flood Protection — If enabled, may use SYN cookies instead of immediate TCB allocation
- •Allocate TCB — Create Transmission Control Block with CLOSED → SYN_RECEIVED state
- •Record Client ISN — Store the sequence number from SYN as IRS (Initial Receive Sequence)
- •Generate Server ISN — Create ISS (Initial Send Sequence) using secure random generation
- •Parse Options — Extract MSS, Window Scale, SACK Permitted, Timestamps, etc.
- •Prepare SYN-ACK — Construct response segment with SYN+ACK flags, server's ISN, and options
- •Send SYN-ACK — Transmit response; start retransmission timer for the SYN-ACK
Edge Cases in SYN Processing:
Duplicate SYN (Same Connection): If a SYN arrives for an existing connection, behavior depends on the connection state:
- SYN_RECEIVED state — Retransmit the SYN-ACK (client may not have received it)
- ESTABLISHED state — The SYN may indicate the client lost state; respond with ACK of current sequence
- Other states — Complex rules apply; may indicate half-open connection recovery
Simultaneous Open: Rarely, two hosts may each send SYN to each other simultaneously (both acting as clients). TCP handles this by allowing both sides to transition through SYN_RECEIVED to ESTABLISHED without requiring one to be the 'server.'
Modern TCP implementations maintain two queues for incoming connections: the SYN queue (half-open connections awaiting the final ACK) and the Accept queue (fully established connections awaiting application accept()). When these queues are full, new SYNs may be dropped, causing connection failures under load. The 'listen backlog' parameter controls these queue sizes.
KEEP LEARNING
There’s more to understand.
You’re reading the introduction. Create a free account to read the complete lesson, save notes and keep track of your progress.