Part XVII — Security
This part is defensive: recognize attacks in traffic and counter them. TCP/IP was designed with security as priority #7 (Ch. 1), so most of these are structural, not bugs.
52. Spoofing, SYN floods, RST injection, and off-path attacks
52.1 IP source spoofing — the root enabler
Nothing in IP proves the source address. A host can put any source IP in a packet it sends. This works for the attacker whenever they don't need to see the reply (one-way / blind attacks) or they're on-path (can see replies).
Defense — BCP 38 / BCP 84 (ingress/egress filtering): every network drops outbound packets whose source isn't from its own prefixes, and drops inbound packets claiming to be from its own prefixes. uRPF (unicast Reverse Path Forwarding) automates it: drop a packet if the route back to its source doesn't point out the interface it arrived on (strict) or isn't in the table at all (loose). Widely deployed but not universal — which is why spoofed-source DDoS still exists.
52.2 SYN flood
Send many SYNs (usually spoofed source) and never complete the handshake. Each
fills a slot in the server's SYN queue (half-open connections), and the
server wastes a SYN-ACK + retransmits. Legit clients can't get a slot → denial of
service, at very low attacker bandwidth.
Defenses:
- SYN cookies (
net.ipv4.tcp_syncookies=1, Ch. 24.5) — server keeps no state for half-open connections; reconstructs from the final ACK. The primary defense; engages only under overflow. - Larger
tcp_max_syn_backlog, shortertcp_synack_retries. - SYN proxy at a firewall/LB/XDP (
synproxyin netfilter, or hardware) — completes the handshake on the server's behalf and only hands over real connections. - Upstream scrubbing for volumetric versions.
- Rate-limit SYNs per source (weak vs spoofing) / per subnet.
52.3 RST injection & connection reset attacks
If an attacker can guess or observe the 4-tuple and a valid sequence number
window, they can forge a RST (or data) segment and the endpoint will act on it:
- On-path (same LAN, compromised router, nation-state middlebox): trivial — they see everything. The Great Firewall forges RSTs to both ends to kill connections; some ISPs used RST to throttle P2P.
- Off-path (blind): must guess the tuple (server IP/port known; client IP maybe known; client port and sequence are the entropy). RFC 5961 makes this much harder: an in-window-but-not-exact RST triggers a challenge ACK instead of an immediate reset, so the attacker needs a near-exact sequence number. (Ironically, the shared rate limit on challenge ACKs became a side-channel — CVE-2016-5696 — now randomized.)
Defenses: randomized ISNs (RFC 6528), RFC 5961 checks, ephemeral source port randomization (more tuple entropy), and — the real fix — TLS/SSH: a forged RST can tear the TCP connection but can't inject or read application data, and the app just reconnects. TCP-AO (RFC 5925, replaces TCP-MD5) authenticates segments for infrastructure sessions like BGP.
52.4 Session hijacking / data injection
On-path attacker injects application data into an unauthenticated stream (classic
telnet, http, unencrypted SMTP). Or predicts sequence numbers to do it blind
(historic). Defense: encrypt + authenticate everything (TLS, SSH, IPsec,
WireGuard). Assume the path is hostile.
52.5 TCP-based reconnaissance
- SYN scan (
nmap -sS): SYN →SYN-ACK(open) /RST(closed) / nothing (filtered). Doesn't complete the handshake ("half-open"). - FIN/NULL/Xmas scans: rely on RFC-793 behavior (closed port → RST, open → nothing) to slip past stateless filters. Modern stacks/firewalls detect these.
- Idle/zombie scan: uses a third host's predictable IP ID field to scan fully blind. Defense: randomized IP ID (Linux does per-destination).
- OS fingerprinting (
nmap -O,p0f): initial TTL, window size, MSS, option order/presence, DF bit → identifies the OS. Defense: normalization at a firewall (scrubin pf), or accept that it's low-risk. - Banner grabbing, TLS
JA3/JA4client fingerprints.
Defenses: default-deny firewall, rate-limit + alert on scan patterns
(nf_conntrack + hashlimit, fail2ban, an IDS), don't expose management ports,
and reduce attack surface (fewer listening sockets — audit with ss -tlnp).
52.6 Amplification / reflection (covered more in Ch. 54)
Spoof the victim's IP as source of a small UDP request to a service that
returns a large response → the victim is flooded, attacker's bandwidth
multiplied. Amplification factors: DNS ANY ~50×, NTP monlist ~550×, memcached
~10 000–50 000×, SSDP ~30×, CLDAP ~55×. Defense: BCP 38 (kills spoofing at
source), disable/restrict the abusable services (no open resolvers, NTP
noquery, memcached not on UDP/not on the internet), rate-limit responses
(DNS RRL).
52.7 Other classics to recognize
| Attack | Mechanism | Defense |
|---|---|---|
| ARP spoofing | forged ARP → LAN MITM | Dynamic ARP Inspection + DHCP snooping, static ARP for gateways, 802.1X |
| Rogue DHCP / rogue RA | hand out attacker as gateway/DNS | DHCP snooping, RA Guard |
| DNS cache poisoning (Kaminsky) | race a forged answer into a resolver | source-port + query-ID randomization (32-bit entropy), DNSSEC, DoT/DoH to a trusted resolver, 0x20 encoding |
| DNS rebinding | public name flips to 127.0.0.1/RFC1918 after TTL → browser attacks internal services |
resolver/app rebinding protection (reject private answers for public names), Host allow-listing |
| TCP "sequence prediction" | guess ISN → blind spoof a whole connection | RFC 6528 randomized ISN |
| Slowloris / slow POST / R-U-Dead-Yet | open many connections, send headers/body 1 byte at a time → exhaust worker slots | request header/body timeouts, min data-rate, connection limits per IP, an async/event-driven front proxy (nginx/HAProxy) that buffers |
| TCP request smuggling | front proxy & backend disagree on request boundaries (CL vs TE) |
normalize/reject ambiguous framing at the edge, HTTP/2 end-to-end |
| LAND / teardrop / ping-of-death | malformed/overlapping packets crash old stacks | patched kernels; drop obviously bogus packets |
52.8 War story
A service saw thousands of connections stuck in SYN_RECV and legit users
timing out. nstat showed TcpExtTCPReqQFullDoCookies climbing — a SYN flood
with spoofed sources. tcp_syncookies was already on and doing its job at the
kernel, but the upstream firewall's own connection table was also filling. Adding
an XDP SYN filter on the edge hosts (drop SYNs exceeding a per-source rate,
validate with cookies before passing) plus asking transit to enable uRPF on the
customer link absorbed it. Lesson: SYN floods are cheap and old; have SYN
cookies on, know your nstat cookie counters, and have an XDP/scrubbing layer
ready.
Try it yourself (defensive)
ss -tlnp # audit every listening socket - attack surface
nstat -az | grep -Ei 'syncookie|challengeack|embryonic|ReqQFull|PAWS|ListenDrops'
sysctl net.ipv4.tcp_syncookies net.ipv4.conf.all.rp_filter net.ipv4.tcp_rfc1337
sysctl net.ipv4.conf.all.accept_redirects net.ipv4.conf.all.send_redirects # set 0
sysctl net.ipv4.conf.all.accept_source_route # set 0
sudo nft add rule inet filter input tcp flags syn limit rate 200/second accept # SYN rate-limit