Loading learning content...
The SYN-ACK segment is a masterpiece of protocol efficiency. In a single packet, the server accomplishes two critical objectives: acknowledging the client's connection request and proposing its own sequence number for the reverse direction. This dual-purpose design reduces Round-Trip Time (RTT) overhead by combining what could have been two separate messages.
When a server receives a valid SYN, it responds with the SYN-ACK—a segment that says, in essence: "I received your request to connect (ACK), and here is my initial sequence number for data I'll send to you (SYN)." This elegant combination makes TCP's connection establishment complete in just three packets rather than four.
By the end of this page, you will understand the dual purpose of the SYN-ACK segment, how the server selects its Initial Sequence Number, how acknowledgment numbers work in TCP, the option negotiation response process, server-side state transitions, and edge cases like SYN-ACK retransmission.
The SYN-ACK segment has two simultaneous meanings, encoded in two flags that are both set:
1. ACK (Acknowledgment) — "I received your SYN"
The ACK flag being set indicates that the Acknowledgment Number field is valid. This value tells the client: "I received your SYN with ISN = X, so I expect your next byte to have sequence number X + 1."
2. SYN (Synchronize) — "Here is my ISN"
The SYN flag being set indicates that the Sequence Number field contains the server's Initial Sequence Number (ISN). This tells the client: "When I start sending you data, it will begin at sequence number Y."
TCP could have used a separate ACK packet followed by a separate SYN packet from the server. But network communication is expensive—every packet incurs processing, latency, and header overhead. Combining SYN+ACK into one segment halves the number of packets needed for the server's response, reducing latency from 2 RTT to 1.5 RTT for connection establishment.
The Two-Way Handshake Fallacy:
A common misconception is that TCP could work with just two packets: SYN from client, SYN-ACK from server. Why isn't this sufficient?
Consider: after the server sends SYN-ACK, it knows the client wants to connect, but the client hasn't confirmed it received the server's response. The server's sequence number hasn't been acknowledged. Without the final ACK:
The three-way handshake ensures both sides have confirmed both directions of communication are functional.
| Aspect | Two-Way (Hypothetical) | Three-Way (Actual TCP) |
|---|---|---|
| Packets required | 2 | 3 |
| Client confirms server's ISN | No | Yes (final ACK) |
| Server confirms client received SYN-ACK | No | Yes |
| Vulnerable to half-open connections | Highly | Protected |
| Reliable bidirectional setup | No | Yes |
The Acknowledgment Number in the SYN-ACK is deceptively simple in concept but critical in practice. When the server sets ACK = client_ISN + 1, it's making a precise statement about what it expects next.
Acknowledgment Number Semantics:
The TCP acknowledgment number indicates the next sequence number the receiver expects. It implicitly acknowledges all bytes up to (but not including) this value.
In the SYN-ACK:
Acknowledgment Number = Client's ISN + 1
This means:
Even though the SYN segment carries no application data, it occupies one sequence number. This is intentional: by consuming a sequence number, the SYN can be reliably acknowledged. The acknowledgment 'ISN + 1' unambiguously means 'I received your SYN.' Without this, there would be no way to confirm SYN receipt distinctly from data receipt.
Example Acknowledgment Calculation:
Suppose the client sends a SYN with:
Sequence Number (ISN): 1000
The server's SYN-ACK will contain:
Acknowledgment Number: 1001
This tells the client: "I've received everything through sequence 1000 (including your SYN). Send byte 1001 whenever you're ready."
When the client later sends its first data segment, it will begin:
Sequence Number: 1001
Data: "GET / HTTP/1.1\r\n..."
Cumulative Acknowledgment:
TCP uses cumulative acknowledgments—the acknowledgment number indicates all contiguous bytes up to that point have been received. This is important for the handshake:
Just as the client proposed its ISN in the SYN, the server must propose its own ISN in the SYN-ACK. This server ISN follows the same security requirements and generation methods as the client's ISN, but the values are completely independent.
Why Independent ISNs?
TCP connections are full-duplex—both sides can send data simultaneously. Each direction has its own sequence number space:
These two sequence spaces are entirely separate. The client's acknowledgments reference the server's sequence space, and vice versa.
Server ISN Generation:
The server generates its ISN using the same cryptographic randomization method as the client (RFC 6528):
Server_ISN = M + F(server_ip, server_port, client_ip, client_port, secret_key)
Note the parameters are the same tuple but with consistent ordering. The function F uses a secret key known only to the host, ensuring:
If an attacker can observe a server's ISNs across multiple connections, they might detect patterns that reveal the secret key or generation algorithm weaknesses. Modern implementations use strong cryptographic functions (like MD5 or SHA-based HMACs) and periodically rotate secret keys to prevent this.
Let's examine every field in a typical SYN-ACK segment, comparing it to the original SYN to understand the response pattern:
| Field | Size | SYN-ACK Value | Explanation |
|---|---|---|---|
| Source Port | 16 bits | Service port (e.g., 443) | Server's well-known or registered port |
| Destination Port | 16 bits | Ephemeral port (e.g., 54321) | Echoes client's source port |
| Sequence Number | 32 bits | Server's ISN (e.g., 0x5A6B7C8D) | Server's Initial Sequence Number |
| Acknowledgment Number | 32 bits | Client_ISN + 1 | Acknowledges client's SYN |
| 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 | 0x12 (SYN + ACK) | Both SYN and ACK flags set |
| Window Size | 16 bits | Server's receive window | Server's available buffer space |
| 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 | Server's supported options | Response to client's capability negotiation |
Critical Observations:
Flags = 0x12 — In the 8-bit flags field, bit 1 (SYN) and bit 4 (ACK) are set: 0001 0010 = 0x12
Port Reversal — Source and destination ports are swapped from the SYN. The server responds from its service port to the client's ephemeral port.
Both Sequence and Acknowledgment Valid — Unlike the pure SYN, both fields carry meaningful values. The sequence number is the server's ISN; the acknowledgment number references the client's sequence space.
Server's Window — The window size advertises how much data the server can receive. This may differ significantly from the client's advertised window.
Just like the client's SYN, the server's SYN-ACK consumes one sequence number. When the client sends its final ACK, it will acknowledge the server's ISN + 1, confirming receipt of the SYN-ACK. If the server's ISN is 5000, the client's ACK will contain ACK = 5001.
The SYN-ACK is the server's opportunity to accept, modify, or reject the optional capabilities the client proposed. The negotiation follows specific rules:
Negotiation Semantics:
| Client Proposes | Server Response | Outcome |
|---|---|---|
| MSS = 1460 | MSS = 1460 | Both agree on 1460 |
| MSS = 1460 | MSS = 1400 | Server restricts to 1400 |
| MSS = 1460 | No MSS option | Default 536 used |
| Window Scale = 7 | Window Scale = 5 | Each side uses its own scale |
| Window Scale = 7 | No Window Scale | Large windows disabled |
| SACK Permitted | SACK Permitted | SACK enabled |
| SACK Permitted | No SACK option | SACK disabled |
| Timestamps | Timestamps | RTT measurement enabled |
| Timestamps | No Timestamps | Timestamps disabled |
Option-by-Option Analysis:
Maximum Segment Size (MSS): Each side independently declares the largest segment it can receive. The effective MSS for each direction is what that direction's receiver advertised. If client says 1460 and server says 1400:
Window Scale: Unlike MSS, Window Scale must be present in both SYN and SYN-ACK to be enabled. If either omits it, neither side can use scaled windows. Each side's scale factor applies to windows they advertise, not receive.
SACK Permitted: This is a binary negotiation. If both include SACK Permitted, selective acknowledgments can be used. If either omits it, SACK is unavailable for the connection.
Timestamps: If both sides include the Timestamps option, subsequent segments will carry timestamps for RTT estimation and PAWS. The server echoes the client's timestamp in the echo-reply field.
Whatever options are agreed upon in the handshake remain fixed for the entire connection. There is no mechanism to add capabilities mid-connection. This is why both SYN and SYN-ACK typically include all supported options—missing the negotiation window means missing the capability entirely.
Server's Option Strategy:
Servers must balance compatibility with performance:
Servers may deliberately omit options in constrained environments:
When the server sends the SYN-ACK, it undergoes a critical state transition in the TCP state machine. Understanding this transition is essential for debugging connection issues and understanding resource management.
State Transition Sequence:
listen())SYN_RECEIVED State Characteristics:
In SYN_RECEIVED, the connection is half-open:
Timeout Behavior:
If the client's ACK never arrives, the server's SYN-ACK retransmission timer expires:
Typical Linux defaults: 5 retries with exponential backoff, totaling ~31 seconds before giving up.
A server in SYN_RECEIVED has committed resources (memory for TCB, entry in connection table) to a connection that isn't complete. An attacker sending SYN from spoofed addresses never intends to complete the handshake, leaving the server with many half-open connections consuming resources. This is the SYN flood attack, which SYN cookies were designed to counter.
Network packets can be lost. When the client's original SYN triggers a SYN-ACK that never reaches the client, or when the client's ACK never reaches the server, retransmission mechanisms ensure the handshake can still complete.
Scenario 1: SYN-ACK Lost (Never Reaches Client)
| Time | Client State | Server State | Action |
|---|---|---|---|
| T=0 | SYN_SENT | LISTEN | Client sends SYN |
| T=50ms | SYN_SENT | SYN_RECEIVED | Server sends SYN-ACK (lost in transit) |
| T=3s | SYN_SENT | SYN_RECEIVED | Server's timer expires, retransmits SYN-ACK |
| T=3.05s | ESTABLISHED* | SYN_RECEIVED | Client receives SYN-ACK, sends ACK |
| T=3.1s | ESTABLISHED | ESTABLISHED | Server receives ACK, handshake complete |
Scenario 2: Client's ACK Lost (Server Never Gets ACK)
| Time | Client State | Server State | Action |
|---|---|---|---|
| T=0 | SYN_SENT | LISTEN | Client sends SYN |
| T=50ms | SYN_SENT | SYN_RECEIVED | Server sends SYN-ACK |
| T=100ms | ESTABLISHED | SYN_RECEIVED | Client receives SYN-ACK, sends ACK (lost) |
| T=3s | ESTABLISHED | SYN_RECEIVED | Server's timer expires, retransmits SYN-ACK |
| T=3.05s | ESTABLISHED | SYN_RECEIVED | Client receives duplicate SYN-ACK, retransmits ACK |
| T=3.1s | ESTABLISHED | ESTABLISHED | Server receives ACK, handshake complete |
Key Observations:
Client may enter ESTABLISHED before server — The client considers the connection established upon receiving SYN-ACK, before its ACK is delivered or processed.
Duplicate SYN-ACKs are handled gracefully — The client responds to duplicate SYN-ACKs by retransmitting its ACK. This is idempotent and safe.
Exponential backoff limits network load — Retransmissions don't flood the network; they're spaced with increasing intervals.
Connection eventually times out — If repeated retransmissions fail, the server abandons the connection attempt.
Interestingly, some TCP implementations allow the client to send data immediately after sending its ACK (piggybacked with the ACK or in a following segment), even before receiving any confirmation from the server. This data will be accepted once the server completes the handshake. TCP Fast Open (TFO) takes this further by allowing data in the SYN itself.
Examining actual SYN-ACK packets reveals implementation details and helps diagnose connection issues. Here's an annotated capture:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
Transmission Control Protocol, Src Port: 443, Dst Port: 54321, Seq: 0, Ack: 1 Source Port: 443 Destination Port: 54321 [Stream index: 0] [TCP Segment Len: 0] Sequence Number: 0 (relative sequence number) Sequence Number (raw): 1517890234 [Next Sequence Number: 1] Acknowledgment Number: 1 (relative ack number) Acknowledgment number (raw): 2812345679 1010 .... = Header Length: 40 bytes (10) Flags: 0x012 (SYN, ACK) 000. .... .... = Reserved: Not set ...0 .... .... = Accurate ECN: Not set .... 0... .... = Congestion Window Reduced: Not set .... .0.. .... = ECN-Echo: Not set .... ..0. .... = Urgent: Not set .... ...1 .... = Acknowledgment: Set .... .... 0... = Push: Not set .... .... .0.. = Reset: Not set .... .... ..1. = Syn: Set .... .... ...0 = Fin: Not set Window: 65535 [Calculated window size: 65535] Checksum: 0x9f8e [unverified] Urgent Pointer: 0 Options: (20 bytes), Maximum segment size, SACK permitted, Timestamps, No-Operation (NOP), Window scale TCP Option - Maximum segment size: 1460 bytes Kind: Maximum Segment Size (2) Length: 4 MSS Value: 1460 TCP Option - SACK permitted Kind: SACK Permitted (4) Length: 2 TCP Option - Timestamps Kind: Time Stamp Option (8) Length: 10 Timestamp value: 987654321 Timestamp echo reply: 123456789 TCP Option - No-Operation (NOP) Kind: No-Operation (1) TCP Option - Window scale: 8 (multiply by 256) Kind: Window Scale (3) Length: 3 Shift count: 8 [Time since first frame in this TCP stream: 0.012345678 seconds] [Time since previous frame in this TCP stream: 0.012345678 seconds]Detailed Analysis:
Flags = 0x012 (SYN + ACK) — Confirms this is the handshake response
Raw Acknowledgment = 2812345679 — This is exactly client's ISN (2812345678) + 1, confirming SYN receipt
Server's ISN — Raw sequence 1517890234, completely independent of client's ISN
Timestamp Echo Reply = 123456789 — Server echoes the client's timestamp from the SYN. This enables the client to measure RTT immediately.
Window Scale = 8 — Server's scale factor differs from client's (which was 7). Each side uses its own factor for windows it advertises.
MSS = 1460 — Server agrees to the same MSS as client (both using standard Ethernet values)
SACK Permitted present — Server agrees to selective acknowledgments
Wireshark shows both relative (0, 1, 2...) and raw sequence numbers. Relative numbers start at 0 for the ISN and count from there, making analysis easier. Raw numbers show the actual values in the packets. For debugging, you may need to work with raw numbers to verify calculations.
Real networks present edge cases that test TCP implementations. Understanding these scenarios helps in debugging and security analysis.
Simultaneous Open Deep Dive:
Simultaneous open is a rare but valid scenario. It occurs when:
Both hosts respond with SYN-ACK:
The result is a normal established connection, just with a symmetric handshake pattern. This is rare in practice because client-server timing makes simultaneous SYN unlikely.
Common reasons SYN-ACK never arrives: (1) Server's firewall blocking outbound SYN-ACKs, (2) Server not listening on the port (should send RST, but firewall may drop), (3) Network path asymmetry (return path blocked), (4) NAT/firewall state table full, (5) Server load so high it can't respond. Tools like tcpdump on both endpoints help isolate where packets are lost.
The SYN-ACK introduces its own security considerations, distinct from those of the initial SYN:
| Concern | Description | Mitigation |
|---|---|---|
| ISN Disclosure | Attacker observing SYN-ACK learns server's ISN | Cryptographic ISN generation limits prediction for future connections |
| Reflection Attack | Trick server into sending SYN-ACK to victim (spoofed source IP) | Ingress filtering, spoofed source can't receive SYN-ACK anyway |
| Server Fingerprinting | SYN-ACK options and timing reveal server OS | Difficult to fully prevent; some OSes have tuning options |
| Resource Commitment | Server in SYN_RECEIVED has committed resources | SYN cookies delay resource allocation |
| Middlebox Interference | Firewalls/NATs may modify or block SYN-ACK | Properly configured firewalls; TCP option stripping awareness |
SYN Cookies and SYN-ACK:
When SYN cookies are enabled, the server's SYN-ACK is constructed specially:
No TCB allocated — Server doesn't store any connection state
ISN encodes connection info — The sequence number in the SYN-ACK is a cryptographic hash of connection parameters including:
Stateless operation — When the client's ACK arrives, the server:
This elegantly prevents SYN flood attacks by deferring resource allocation until the handshake completes.
SYN cookies come with limitations: (1) TCP options from the SYN can't be fully preserved—only MSS with limited entropy, (2) Some features like window scaling and SACK may be unavailable if activated during SYN flood, (3) SACK blocks in subsequent packets can't be validated without state. Modern implementations only activate SYN cookies when the SYN queue approaches overflow.
We've thoroughly examined the SYN-ACK segment—the clever dual-purpose response that makes TCP connection establishment efficient. Let's consolidate the essential knowledge:
What's Next:
With the server's SYN-ACK sent, the handshake is two-thirds complete. The client has proposed its sequence number and received the server's. But the connection isn't established until the client confirms receipt. In the next page, we'll examine the final ACK—the segment that completes the three-way handshake and transitions both endpoints to the ESTABLISHED state.
You now understand the SYN-ACK segment comprehensively—its dual nature, structure, option negotiation, state transitions, and security implications. This prepares you for understanding how the final ACK completes the connection and why it's essential for reliable bidirectional communication.