Sau bài này bạn làm được: SSH vào server và trong 5 phút biết: IP nào đang gắn, service nào đang listen, connection nào đang mở; giải thích tại sao refusedtimeout có nghĩa khác nhau ở tầng firewall.


Bức tranh mạng trên một Linux host

[Ứng dụng / container]
         │  socket API (bind, connect, send…)
[Kernel: TCP/IP stack]
         │  routing table, conntrack, netfilter (iptables/nftables)
[Network interface: eth0, ens5, bond0…]
[Vật lý / cloud NIC / overlay network]

Mọi traffic đi qua kernel — hiểu kernel networking là hiểu hành vi thực sự của hệ thống.


Interface và địa chỉ IP: lệnh ip

# Liệt kê interface và địa chỉ IP
ip -4 addr show

# Output mẫu:
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP>
    inet 10.0.1.50/24 brd 10.0.1.255 scope global eth0

# Liệt kê link layer (MAC, trạng thái UP/DOWN)
ip link show

# Xem routing table
ip route show
# Output:
default via 10.0.1.1 dev eth0
10.0.1.0/24 dev eth0 proto kernel scope link src 10.0.1.50
172.17.0.0/16 dev docker0 proto kernel  # Docker bridge

# Trace packet tới đích sẽ đi đường nào
ip route get 8.8.8.8
# 8.8.8.8 via 10.0.1.1 dev eth0 src 10.0.1.50

Ghi nhớ: ip addrip route thay thế ifconfigroute (deprecated).


Socket và process: lệnh ss

# Tất cả TCP đang LISTEN
ss -lntp

# Tất cả TCP ESTABLISHED
ss -tnp state established

# Tất cả UDP đang LISTEN
ss -lnup

# Lọc theo cổng
ss -lntp sport = :443

# Đếm theo trạng thái
ss -tan | awk '{print $1}' | sort | uniq -c | sort -rn

Đọc output:

State    Recv-Q  Send-Q  Local Addr:Port   Peer Addr:Port  Process
LISTEN   0       128     0.0.0.0:80        0.0.0.0:*       ("nginx",pid=123)
LISTEN   0       128     127.0.0.1:5432    0.0.0.0:*       ("postgres",pid=456)
ESTAB    0       0       10.0.1.50:443     1.2.3.4:55123   ("nginx",pid=123)
  • Recv-Q cao: dữ liệu đang chờ application đọc — app bị block?
  • Send-Q cao: dữ liệu chờ gửi — network bị tắc nghẽn?
  • Postgres chỉ bind 127.0.0.1 → không truy cập được từ ngoài (đúng hay sai tùy thiết kế).

Firewall: iptables / nftables khái niệm

Linux kernel dùng netfilter để lọc gói tin. iptables (cũ) và nftables (mới) là front-end để cấu hình netfilter.

Ghi chú 2025: nhiều distro hiện đại (Debian 11+, RHEL 9+, Ubuntu 22.04+) đã mặc định nftables backend; lệnh iptables thực chất là wrapper (iptables-nft). Kubernetes từ 1.29+ hỗ trợ kube-proxy nftables mode; CNI hiện đại (Cilium, Calico eBPF) có thể bỏ qua netfilter hoàn toàn bằng eBPF — xem bài 10.

Hiểu action — quan trọng hơn cú pháp:

ACCEPT  → cho gói qua
DROP    → im lặng bỏ gói (client thấy timeout)
REJECT  → bỏ gói + gửi ICMP/RST về (client thấy refused hoặc unreachable nhanh hơn)

DROP vs REJECT trong debug:

Firewall DROP:   client gửi SYN → (im lặng) → client timeout sau vài giây/phút
Firewall REJECT: client gửi SYN → RST/ICMP ngay lập tức → client báo "refused"

Hầu hết cloud SG dùng DROP (stateful). Khi “không vào được” và timeout dài → nghĩ ngay tới DROP rule.

Xem rule hiện tại:

# iptables (cần root)
iptables -L -n -v --line-numbers

# nftables
nft list ruleset

# Kiểm tra chain INPUT / FORWARD / OUTPUT
iptables -L INPUT -n -v

sysctl — tham số kernel ảnh hưởng mạng

# Xem tất cả tham số mạng
sysctl -a | grep net.core

# Các tham số quan trọng:
sysctl net.core.somaxconn             # backlog tối đa cho accept queue
sysctl net.ipv4.ip_local_port_range   # dải ephemeral port (VD: 32768 60999)
sysctl net.ipv4.tcp_max_tw_buckets    # số socket TIME_WAIT tối đa trên hệ thống
sysctl net.ipv4.tcp_fin_timeout       # thời gian chờ FIN trước khi đóng (s)
sysctl net.ipv4.tcp_tw_reuse          # bật tái dùng TIME_WAIT cho outbound (cẩn trọng)

Khi nào cần tune:

  • somaxconn thấp: server đang nhận burst connection → SYN DROP, client timeout.
  • ip_local_port_range nhỏ: khi một server mở ra rất nhiều kết nối outbound (proxy, crawler) → port exhaustion, connection failed.

Đổi tạm thời (mất sau reboot):

sysctl -w net.core.somaxconn=65535

Đổi vĩnh viễn:

echo "net.core.somaxconn = 65535" >> /etc/sysctl.d/99-custom.conf
sysctl -p /etc/sysctl.d/99-custom.conf

Kiểm tra connectivity từ server

# Ping (ICMP — có thể bị chặn, không phải TCP)
ping -c 4 8.8.8.8

# Trace route tới đích
mtr --report 8.8.8.8         # realtime, tốt hơn traceroute
traceroute 8.8.8.8

# Test TCP connect (không cần curl)
nc -vz api.example.com 443

# Kiểm tra DNS từ server
dig +short A api.example.com

Tóm tắt

  • ip addr + ip route = bức tranh routing trên host.
  • ss -lntp = biết ai đang nghe cổng nào.
  • DROP → timeout; REJECT → refused — quan trọng khi phân biệt firewall rule.
  • Tune sysctl cẩn thận: ghi lại giá trị cũ trước khi thay đổi.

Câu hỏi hay gặp

Service chỉ listen 127.0.0.1:8080 — gọi từ máy khác vào 8080 thì sao? Expose an toàn ra sao?

Trả lời: Không kết nối được từ IP khác vì chỉ lắng nghe loopback. Muốn public: bind 0.0.0.0 hoặc IP máy dùng reverse proxy + TLS + firewall (chỉ mở 443), không nên mở thẳng app port ra internet nếu không cần.

Recv-Q trên LISTEN tăng mãi — nghĩa là gì?

Trả lời: Hàng chờ accept đầy: kernel đã hoàn tất handshake nhưng tiến trình accept() chậm (app bị block, single-thread, hoặc quá tải). Cần tăng capacity app hoặc somaxconn/tune phù hợp.

iptables DROP cổng 5432 — client thấy refused hay timeout?

Trả lời: Thường là timeout (gói SYN bị drop, không có RST). Refused là khi có RST (không có process listen hoặc REJECT).


Bài tiếp theo (Giai đoạn III): Mạng trong Docker — khi workload chạy trong container, mạng có thêm một lớp abstraction.