TCP/IP#
The protocol stack underneath every networking command on this page. Each layer maps to a Linux data structure operators query daily.
Layer |
Examples |
Linux interface |
Tool |
|---|---|---|---|
Application |
HTTP, DNS, SSH, SMTP |
Sockets via |
|
Transport |
TCP, UDP |
|
|
Network |
IPv4, IPv6, ICMP |
|
|
Link |
Ethernet, ARP, VLAN |
|
|
Physical |
NIC / cable / PHY |
Driver / firmware |
|
TCP vs UDP#
Feature |
TCP |
UDP |
|---|---|---|
Connection |
3-way handshake |
Connectionless |
Reliability |
Acknowledged, retransmitted |
Best-effort |
Order |
In-order delivery |
May reorder |
Flow control |
Yes (window-based) |
No |
Congestion control |
Yes (BBR / CUBIC / …) |
No |
Header overhead |
20+ bytes |
8 bytes |
Use cases |
HTTP, SSH, SMTP, file transfer |
DNS, NTP, QUIC, video, gaming |
3-way handshake#
sequenceDiagram
participant C as client
participant S as server
Note over S: LISTEN
C->>S: SYN (seq = X)
Note over C: SYN_SENT
Note over S: SYN_RECV
S->>C: SYN-ACK (seq = Y, ack = X+1)
C->>S: ACK (ack = Y+1)
Note over C,S: ESTABLISHED, data flows
TCP states#
Visible in ss -tan and /proc/net/tcp. The ones operators see most:
State |
Meaning |
|---|---|
|
Server waiting for a connection |
|
Client sent SYN, waiting for SYN-ACK |
|
Server received SYN, sent SYN-ACK |
|
Connected; data can flow either way |
|
Local side initiated close, waiting for peer FIN-ACK / FIN |
|
Peer closed; local app must call |
|
Local side closed; lingering 2 × MSL to absorb stragglers |
|
Socket gone |
Tip
A pile of CLOSE_WAIT on the server side means the application
is not calling close(); a classic file-descriptor leak.
A pile of TIME_WAIT on a busy client means it’s churning short
connections; reuse via connection pools or tune
net.ipv4.tcp_tw_reuse.
IPv4 vs IPv6#
Feature |
IPv4 |
IPv6 |
|---|---|---|
Address size |
32 bits, |
128 bits, |
Address space |
~4.3 billion (exhausted) |
~3.4 × 10³⁸ |
Notation |
Dotted decimal |
Colon-hex, |
Header |
20 bytes (variable) |
40 bytes (fixed) |
Loopback |
|
|
Private range |
|
|
Link-local |
|
|
Fragmentation |
Routers + sender |
Sender only |
NAT typical? |
Yes, near-universal |
No, end-to-end addressing |
CIDR#
CIDR (Classless Inter-Domain Routing) writes a network as
ADDR/PREFIX where PREFIX is the number of leading bits that
identify the network; the rest are host bits.
Notation |
Mask |
Hosts |
Common use |
|---|---|---|---|
|
255.255.255.255 |
1 |
Single host |
|
255.255.255.252 |
2 |
Point-to-point link |
|
255.255.255.248 |
6 |
Tiny LAN |
|
255.255.255.0 |
254 |
Standard LAN |
|
255.255.0.0 |
65 534 |
Campus network |
|
255.0.0.0 |
16 M |
|
|
0.0.0.0 |
all |
Default route |
Ports#
Range |
Class |
Examples |
|---|---|---|
0-1023 |
Well-known (root binds) |
22 SSH, 53 DNS, 80 HTTP, 443 HTTPS |
1024-49151 |
Registered |
3306 MySQL, 5432 Postgres, 6379 Redis |
49152-65535 |
Ephemeral (kernel-selected) |
Client source ports |
The local ephemeral range is in
/proc/sys/net/ipv4/ip_local_port_range and can be widened on
high-connection-rate servers.
MTU and MSS#
The Maximum Transmission Unit (MTU) is the largest L3 packet a
link will carry. The Maximum Segment Size (MSS) is the largest
TCP payload, MSS = MTU − IP header − TCP header. Mismatched MTUs
across a path cause silent stalls when intermediaries drop too-big
packets without sending the ICMP “fragmentation needed” reply
(path-MTU black-hole).
Link |
Typical MTU |
|---|---|
Ethernet |
1500 bytes |
PPPoE / DSL |
1492 |
Wi-Fi |
1500 (lower in practice) |
GRE / IPsec |
≤ 1476 |
Loopback |
65 536 |
Jumbo frames |
9000 |
$ ip -s link show eth0 # MTU on the interface
$ ping -M do -s 1472 example.com # don't-fragment probe (1472 + 28 = 1500)
$ ss -nti # MSS, RTT, cwnd per connection
$ tracepath example.com # discover effective path MTU
See also: man 7 tcp, man 7 udp, man 7 ip, man 7 ipv6, RFC 793 (TCP), RFC 791 (IPv4), RFC 8200 (IPv6).