TCP/IP, UDP & Giao Thức Mạng: Nền Tảng Chuyên Sâu Cho Kỹ Sư Hệ Thống

Cẩm nang chuyên sâu về bộ giao thức TCP/IP, mổ xẻ cơ chế bắt tay 3 bước TCP, đóng kết nối 4 bước, giải mã trạng thái TIME_WAIT/CLOSE_WAIT, thuật toán BBR, UDP và tối ưu hóa Socket Kernel trên Linux.

Trong hạ tầng máy chủ và hệ thống phân tán, gần như mọi yêu cầu từ phía người dùng—từ việc tải một trang web, gọi một gRPC API, đến việc truy vấn cơ sở dữ liệu—đều phụ thuộc vào bộ giao thức TCP/IP và UDP.

Đối với một Kỹ sư Hệ thống / SRE, việc hiểu rõ cách thức hoạt động của TCP và UDP không chỉ dừng lại ở lý thuyết mà là chìa khóa then chốt để:

  • Giải quyết triệt để các sự cố nghẽn cổ chai (Bottlenecks) và tăng độ trễ (Latency spikes).
  • Xử lý hiện tượng cạn kiệt cổng kết nối (Ephemeral Port Exhaustion) và ngập tràn trạng thái TIME_WAIT hay CLOSE_WAIT.
  • Tối ưu hóa các thông số Kernel Linux (Kernel Network Tuning) giúp hệ thống chịu tải hàng triệu kết nối đồng thời.

🏗️ Kiến Trúc Ngăn Xếp TCP/IP (The 4-Layer Model)

Trái ngược với mô hình OSI 7 tầng mang tính hàn lâm, mạng Internet thực tế hoạt động hoàn toàn dựa trên ngăn xếp TCP/IP 4 tầng (được định nghĩa theo tiêu chuẩn RFC 1122):

graph TD
    App[Tầng Ứng Dụng - Application Layer<br/>HTTP/HTTPS, DNS, SSH, gRPC, SMTP] --> Trans[Tầng Giao Vận - Transport Layer<br/>TCP, UDP, SCTP, QUIC]
    Trans --> Net[Tầng Mạng - Internet Layer<br/>IPv4, IPv6, ICMP, ARP]
    Net --> Link[Tầng Truy Cập Mạng - Network Access Layer<br/>Ethernet, Wi-Fi, MAC, VLAN]

Các thông số đóng gói cốt lõi: MTU vs MSS

  • MTU (Maximum Transmission Unit): Kích thước tối đa của một gói tin (Frame) mà card mạng có thể truyền đi tại Tầng 2 mà không bị phân mảnh. Chuẩn Ethernet thông thường là 1500 bytes (hoặc 9000 bytes đối với Jumbo Frames).
  • MSS (Maximum Segment Size): Kích thước dữ liệu ứng dụng (Payload) lớn nhất mà một phân đoạn TCP có thể chứa:

    MSS = MTU - IP Header (20B) - TCP Header (20B) = 1500 - 40 = 1460 bytes

Cạm bẫy MTU trong môi trường Cloud & Kubernetes:

Khi chạy các mạng ảo hóa Overlay (như VXLAN trong Kubernetes CNI Calico/Flannel, hoặc VPN WireGuard/IPsec), mỗi gói tin sẽ bị bọc thêm một Header phụ từ 20 đến 50 bytes. Nếu giữ nguyên MTU 1500, gói tin sẽ bị vượt kích thước gây ra hiện tượng Packet Drop bí ẩn (Black Hole) nếu cờ DF (Don't Fragment) được bật. Kỹ sư luôn cần điều chỉnh MTU của giao diện ảo về mức 1450 hoặc 1420 bytes.


⚡ Giao Thức TCP: Độ Tin Cậy & Hướng Kết Nối

TCP (Transmission Control Protocol) là giao thức hướng kết nối (Connection-oriented), đảm bảo mọi byte dữ liệu gửi đi đều đến nơi đích chính xác, đầy đủ và đúng thứ tự.

1. Cấu Trúc TCP Header & Các Cờ (Flags) Trọng Yếu

Một TCP Header tiêu chuẩn có độ dài tối thiểu là 20 bytes:

Trường (Field)Kích thướcMục đích kỹ thuật
Source Port / Dest Port16 bits mỗi trườngĐịnh danh ứng dụng nguồn và ứng dụng đích (0 - 65535).
Sequence Number (Seq)32 bitsSố thứ tự đánh dấu byte đầu tiên của phân đoạn này trong luồng dữ liệu.
Acknowledgment (Ack)32 bitsSố thứ tự của byte tiếp theo mà bên nhận đang mong đợi nhận được.
Control Flags9 bitsCác cờ điều khiển trạng thái kết nối (SYN, ACK, FIN, RST, PSH, URG).
Window Size16 bitsKích thước bộ đệm nhận (Buffer) mà bên gửi được phép truyền trước khi cần ACK.

Ý Nghĩa Các Cờ (TCP Flags) Khi Debug:

  • SYN (Synchronize): Khởi tạo và đồng bộ số thứ tự kết nối.
  • ACK (Acknowledgment): Xác nhận đã nhận được dữ liệu thành công.
  • FIN (Finish): Yêu cầu đóng kết nối một cách êm đẹp (Graceful shutdown).
  • RST (Reset): Ngắt kết nối ngay lập tức (thường xảy ra khi gửi request vào port không có ứng dụng lắng nghe, hoặc firewall từ chối).
  • PSH (Push): Yêu cầu tầng giao vận đẩy ngay dữ liệu lên ứng dụng, không chờ gom đầy bộ đệm.

2. Thiết Lập Kết Nối: Bắt Tay 3 Bước (Three-Way Handshake)

Trước khi bất kỳ dữ liệu nào được trao đổi, hai máy chủ phải hoàn tất quy trình bắt tay 3 bước:

sequenceDiagram
    autonumber
    actor Client
    actor Server
    Note over Client: Trạng thái: CLOSED
    Note over Server: Trạng thái: LISTEN
    Client->>Server: Gói 1: SYN (Seq = x)
    Note over Client: Trạng thái: SYN-SENT
    Note over Server: Trạng thái: SYN-RECEIVED
    Server->>Client: Gói 2: SYN + ACK (Seq = y, Ack = x + 1)
    Note over Client: Trạng thái: ESTABLISHED
    Client->>Server: Gói 3: ACK (Ack = y + 1)
    Note over Server: Trạng thái: ESTABLISHED
    Note over Client,Server: Bắt đầu truyền dữ liệu thực tế (Data Transfer)

Các sự cố thường gặp ở bước bắt tay:

  1. SYN Flood Attack: Kẻ tấn công gửi hàng triệu gói SYN nhưng không bao giờ gửi lại gói ACK cuối cùng, khiến bảng chờ kết nối bán mở (SYN Backlog Queue) của server bị đầy, từ chối mọi người dùng hợp lệ.
    • Giải pháp: Kích hoạt cơ chế SYN Cookies trong Linux Kernel:
      sysctl -w net.ipv4.tcp_syncookies=1
      
  2. TCP Fast Open (TFO): Cho phép gửi kèm dữ liệu ngay trong gói SYN đầu tiên của các kết nối lặp lại, tiết kiệm trọn vẹn 1 RTT (Round Trip Time) độ trễ mạng.

3. Đóng Kết Nối: 4 Bước (Four-Way Handshake) & Ác Mộng Trạng Thái

Do TCP là kênh truyền song công toàn phần (Full-duplex), việc đóng kết nối mỗi chiều phải được thực hiện độc lập:

sequenceDiagram
    autonumber
    actor Client as Bên Đóng Trước (Active Close)
    actor Server as Bên Đóng Sau (Passive Close)
    Client->>Server: Gói 1: FIN (Seq = u)
    Note over Client: FIN_WAIT_1
    Server->>Client: Gói 2: ACK (Ack = u + 1)
    Note over Server: CLOSE_WAIT
    Note over Client: FIN_WAIT_2
    Server->>Client: Gói 3: FIN (Seq = v, Ack = u + 1)
    Note over Server: LAST_ACK
    Client->>Server: Gói 4: ACK (Ack = v + 1)
    Note over Client: TIME_WAIT (2 x MSL)
    Note over Server: CLOSED
    Note over Client: Sau thời gian chờ -> CLOSED

Giải Mã Trạng Thái TIME_WAIT và CLOSE_WAIT:

1

Hiểu rõ trạng thái TIME_WAIT

  • Tại sao cần tồn tại? Bên chủ động đóng kết nối (Active Close) phải giữ socket ở trạng thái TIME_WAIT trong khoảng thời gian bằng 2 x MSL (Maximum Segment Life - mặc định khoảng 60 giây). Điều này nhằm:
    1. Đảm bảo gói tin ACK cuối cùng đã đến đích an toàn (nếu bị mất, server gửi lại FIN, client vẫn còn đó để ACK lại).
    2. Đảm bảo các gói tin cũ "lạc trôi" trên đường truyền biến mất hoàn toàn trước khi cùng một cặp IP:Port được cấp phát cho kết nối mới.
  • Vấn đề khi tải cao: Hàng chục nghìn kết nối TIME_WAIT làm cạn kiệt dải cổng tạm thời (Ephemeral Ports), dẫn đến lỗi Cannot assign requested address.
  • Khắc phục: Tái sử dụng socket với tcp_tw_reuse:
    sysctl -w net.ipv4.tcp_tw_reuse=1
    
2

Hiểu rõ trạng thái CLOSE_WAIT (Lỗi nghiêm trọng)

  • Khi bạn thấy hàng nghìn socket bị kẹt ở trạng thái CLOSE_WAIT: Đây 100% là lỗi logic của tầng ứng dụng (Application Bug)!
  • Đối phương đã gửi FIN và hệ điều hành của bạn đã tự động gửi ACK. Tuy nhiên, mã nguồn ứng dụng của bạn (Java, Node.js, Go, Python...) bị quên hoặc không chịu gọi hàm socket.close() để đóng chiều còn lại. Socket sẽ bị rò rỉ (Leak) mãi mãi cho đến khi tiến trình sập.

4. Kiểm Soát Luồng & Kiểm Soát Tắc Nghẽn (Congestion Control)

  • Flow Control (Kiểm soát luồng): Ngăn chặn bên gửi làm tràn bộ đệm của bên nhận bằng cơ chế Sliding Window (Cửa sổ trượt). Bên nhận liên tục thông báo giá trị Receive Window (rwnd) để bên gửi điều chỉnh tốc độ.
  • Congestion Control (Kiểm soát tắc nghẽn): Ngăn chặn bên gửi làm nghẽn đường truyền mạng công cộng.
    • Các thuật toán truyền thống (Reno, Cubic): Dựa trên việc mất gói (Packet Loss) để nhận biết nghẽn. Khi mất gói, tốc độ gửi bị giảm đột ngột một nửa (Multiplicative Decrease). Cách này hoạt động rất kém trên các đường truyền mạng hiện đại có tỷ lệ mất gói tự nhiên nhỏ nhưng băng thông lớn.
    • Thuật toán Google BBR (Bottleneck Bandwidth and RTT): Đo lường trực tiếp băng thông cổ chai thực tế và thời gian trễ khứ hồi tối thiểu thay vì chờ mất gói. Giúp tăng throughput từ 2x đến 20x trên các kết nối xuyên lục địa.
# Kiểm tra thuật toán kiểm soát tắc nghẽn hiện tại trên Linux
sysctl net.ipv4.tcp_congestion_control

# Bật thuật toán tối ưu Google BBR trên Linux (Kernel >= 4.9)
sudo modprobe tcp_bbr
sudo sysctl -w net.core.default_qdisc=fq
sudo sysctl -w net.ipv4.tcp_congestion_control=bbr

🚀 Giao Thức UDP: Tốc Độ & Sự Đơn Giản

UDP (User Datagram Protocol) là giao thức không hướng kết nối (Connectionless). Nó loại bỏ hoàn toàn cơ chế bắt tay, không đảm bảo thứ tự, không gửi lại gói tin mất và không kiểm soát tắc nghẽn.

Cấu Trúc UDP Header Siêu Gọn Nhẹ (Chỉ 8 Bytes)

 0                   16                  31 bit
+-------------------+-------------------+
|    Source Port    | Destination Port  |
+-------------------+-------------------+
|      Length       |     Checksum      |
+-------------------+-------------------+
|                Data ...               |
+---------------------------------------+

Tại sao UDP lại quan trọng đối với thế giới hiện đại?

  1. Độ trễ tối thiểu (Zero Handshake RTT): Gửi dữ liệu ngay lập tức mà không cần chờ 1 RTT thiết lập kết nối như TCP.
  2. Ứng dụng thời gian thực: DNS query (Port 53), Streaming âm thanh/video, Game online (bỏ qua frame cũ bị mất để cập nhật frame mới nhất).
  3. Thu thập Metrics hệ thống: StatsD, Syslog UDP (Port 514)—khi server gửi hàng triệu metric mỗi giây, việc mất một vài metric không quan trọng bằng việc làm chậm ứng dụng chính.
  4. Nền tảng của HTTP/3 (Giao thức QUIC): HTTP/2 chạy trên TCP vẫn bị nghẽn toàn bộ luồng khi một gói tin bị mất (Head-of-Line Blocking). Giao thức QUIC chuyển toàn bộ luồng HTTP/3 chạy trên nền UDP, tự xử lý cơ chế tin cậy và mã hóa TLS 1.3 ở tầng ứng dụng, mang lại tốc độ tải trang vượt trội.

⚖️ Bảng So Sánh Chi Tiết: TCP vs UDP

Tiêu chíTCP (Transmission Control Protocol)UDP (User Datagram Protocol)
Bản chấtHướng kết nối (Connection-oriented)Không kết nối (Connectionless)
Kích thước Header20 bytes (hoặc lên đến 60 bytes với Options)Cố định 8 bytes
Độ tin cậy100% tin cậy (Truyền lại gói mất)Không đảm bảo (Best-effort delivery)
Thứ tự dữ liệuCam kết tuyệt đối đúng thứ tựGói tin đến trước/sau ngẫu nhiên
Kiểm soát nghẽnCó (Cubic, BBR, Reno)Không có
Tốc độ truyềnChậm hơn do overhead bắt tay và kiểm traCực nhanh, tiêu tốn ít tài nguyên CPU/RAM
Phương thức phátUnicast (Một - Một)Unicast, Broadcast, Multicast
Trường hợp sử dụngHTTP/HTTPS, SSH, Database, File transferDNS, Video call, VoIP, Gaming, Metrics, HTTP/3 (QUIC)

🧰 Bộ Lệnh Linux Thực Chiến Dành Cho SRE

1. Phân tích trạng thái Socket với lệnh ss

# Thống kê tổng số kết nối mạng theo từng trạng thái (ESTAB, TIME_WAIT, LISTEN)
ss -s

# Liệt kê tất cả kết nối TCP đang mở kèm tên tiến trình
ss -tanp

# Đếm số lượng kết nối theo từng trạng thái trên máy chủ
ss -ant | awk '{print $1}' | sort | uniq -c | sort -nr

2. Bắt và mổ xẻ gói tin TCP với tcpdump

# Bắt gói tin bắt tay 3 bước (các gói có cờ SYN hoặc FIN)
sudo tcpdump -nn -i eth0 'tcp[tcpflags] & (tcp-syn|tcp-fin) != 0'

# Bắt các gói tin bị trả về cờ RST (Reset kết nối)
sudo tcpdump -nn -i eth0 'tcp[tcpflags] & tcp-rst != 0'

3. Kiểm tra kết nối nhanh với Netcat (nc)

# Kiểm tra xem cổng TCP 443 của máy chủ từ xa có mở và bắt tay thành công không
nc -zv 10.0.0.5 443

# Kiểm tra cổng UDP 53 (DNS)
nc -zvu 8.8.8.8 53

⚙️ Tối Ưu Hóa Kernel Linux Cho Hệ Thống Chịu Tải Cao (Kernel Network Tuning)

Thêm các cấu hình sau vào /etc/sysctl.conf trên các máy chủ chịu tải cao (High Traffic Load Balancer / API Gateway):

# Tăng kích thước hàng đợi chứa các kết nối đang chờ ứng dụng accept
net.core.somaxconn = 65535

# Tăng dung lượng hàng đợi SYN Backlog (chống tràn kết nối bắt tay)
net.ipv4.tcp_max_syn_backlog = 65535

# Kích hoạt tính năng tái sử dụng socket ở trạng thái TIME_WAIT
net.ipv4.tcp_tw_reuse = 1

# Mở rộng dải cổng tạm thời cấp cho các kết nối outgoing
net.ipv4.ip_local_port_range = 1024 65535

# Giảm thời gian chờ keepalive để phát hiện sớm các kết nối chết
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.tcp_keepalive_probes = 5

# Tăng kích thước bộ đệm gửi và nhận dữ liệu mạng tối đa (16MB)
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

# Bật thuật toán điều khiển tắc nghẽn BBR
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr

Sau khi sửa file, áp dụng ngay lập tức mà không cần khởi động lại máy chủ:

sudo sysctl -p

📚 Bài Viết Liên Quan Tiếp Theo

Khám phá tiếp các kiến trúc mạng nâng cao trong chuyên mục Mạng Máy Tính: