TCP Protocol Deep Dive
TCP Header Fields
TCP headers are 20 bytes minimum and contain the following critical fields:
- Source Port / Destination Port (16-bit each): identifies the sending and receiving application process
- Sequence Number (32-bit): byte offset of the first byte in this segment; used for ordering and reassembly
- Acknowledgment Number (32-bit): next byte the receiver expects; confirms receipt of prior data
- Data Offset: header length in 32-bit words (min 5 = 20 bytes, max 15 = 60 bytes)
- Flags (9 bits): SYN, ACK, FIN, RST, PSH, URG, ECE, CWR, NS — each controls a specific behavior
- Window Size (16-bit): receive buffer space available — governs flow control
- Checksum: error detection over header + data + pseudo-header (src IP, dst IP, protocol, length)
- Urgent Pointer: byte offset to urgent data when URG flag is set
Connection Lifecycle
3-Way Handshake (SYN / SYN-ACK / ACK):
- Client → SYN (seq=x) — moves to SYN_SENT
- Server → SYN-ACK (seq=y, ack=x+1) — moves to SYN_RCVD
- Client → ACK (ack=y+1) — both move to ESTABLISHED
Data Transfer: segments sent with incrementing seq numbers; receiver ACKs each. TCP uses cumulative ACKs — ACK=1500 means all bytes up to 1499 received.
4-Way FIN Termination:
- Initiator → FIN — moves to FIN_WAIT_1
- Peer → ACK — moves to CLOSE_WAIT
- Peer → FIN — moves to LAST_ACK
- Initiator → ACK — moves to TIME_WAIT (2×MSL, ~60s) then CLOSED
Flow Control — Sliding Window
The receiver advertises how much buffer space it has in the Window field. Sender cannot have more than that many unacknowledged bytes in flight. When window = 0, sender sends 1-byte probes until receiver opens it again.
ss -tin # real-time socket stats including rcv_space and snd_wnd
sysctl net.ipv4.tcp_rmem # min/default/max receive buffer tuning
Security Attacks
SYN Flood (hping3):
hping3 -S --flood -p 80 192.168.1.1 # basic flood on port 80
hping3 -S --flood -p 80 --rand-source target # spoofed source IPs
Exhausts the server's half-open connection table (SYN_RCVD state). Server allocates memory for each SYN — never freed because the handshake never completes.
RST Injection (Scapy):
from scapy.all import *
send(IP(dst="victim")/TCP(dport=80, flags="R", seq=predicted_seq))
Sends a forged RST with a valid sequence number to tear down an established session.
Sequence Number Prediction: older systems used predictable ISNs (fixed increments), allowing blind injection without on-path access.
TCP Session Hijacking: on a shared segment, sniff seq/ack numbers from an established session, then inject a packet with correct numbers and spoofed source IP.
Wireshark Filters
tcp.flags.syn==1 # all SYN packets (connection starts)
tcp.flags.syn==1 && tcp.flags.ack==0 # SYN-only (half-open, flood detection)
tcp.flags.reset==1 # RST packets (abrupt termination)
tcp.stream eq 5 # follow a specific stream
tcp.analysis.retransmission # dropped packets / congestion
Defense
- SYN cookies: server encodes connection state into the ISN instead of allocating memory — defeats SYN floods without limiting backlog. Enable:
sudo sysctl -w net.ipv4.tcp_syncookies=1 - Firewall rate limiting:
iptables -A INPUT -p tcp --syn -m limit --limit 10/s -j ACCEPT - RFC 5961 challenge ACKs: anti-blind-reset mitigations in modern kernels
- TLS: encrypts payload entirely — TCP session hijacking via payload injection becomes useless
- OS hardening: tune
tcp_max_syn_backlog=4096,tcp_syncookies=1in/etc/sysctl.conf