netstat vs ss: Phân tích kết nối mạng và port listening trên Linux

Network tutorial - IT technology blog
Network tutorial - IT technology blog

Khi mình mới bắt đầu quản lý server, cứ thấy ai dùng netstat là mình làm theo. Thói quen từ các tutorial cũ, và mình không đặt câu hỏi gì cả. Cho đến khi cần debug kết nối chậm trên production server với vài nghìn socket đang mở — netstat chạy mất hơn 30 giây mới ra kết quả. Hôm đó mình mới thực sự tìm hiểu về ss.

Mình quản lý network cho office 50 người và một datacenter nhỏ — bài này tổng hợp từ thực tế sau khoảng 6 tháng chuyển dần từ netstat sang ss, và học cách kết hợp cả hai cho từng tình huống khác nhau.

netstat vs ss: Hai công cụ, một mục tiêu

Cả hai đều cho bạn thấy trạng thái kết nối mạng, port đang lắng nghe, và socket đang hoạt động. Nhưng cách chúng hoạt động bên dưới hoàn toàn khác nhau.

netstat thuộc gói net-tools, đọc thông tin từ /proc/net/ theo cách truyền thống. Trên Ubuntu 20.04+ và Debian 11+, nó không được cài sẵn nữa — bạn phải cài thủ công nếu cần.

ss (socket statistics) thuộc gói iproute2, giao tiếp trực tiếp với kernel qua netlink socket. Đây là lý do nó nhanh hơn rõ rệt khi có nhiều kết nối đang mở — thay vì parse file text trong /proc, nó lấy dữ liệu thẳng từ kernel.

Phân tích ưu nhược của từng công cụ

netstat: Quen thuộc nhưng đã lỗi thời

Ưu điểm:

  • Syntax mình nhớ mà không cần Google; tutorial StackOverflow từ 2012 vẫn chạy đúng
  • Output dễ đọc với người mới — cột rõ ràng, không cần giải thích nhiều
  • Xem routing table và interface statistics trong cùng một tool (dù ip route làm tốt hơn)

Nhược điểm:

  • Chậm khi có nhiều kết nối — parse /proc/net/tcp dạng text, không scale được
  • Gói net-tools gần như không còn được cập nhật; nhiều distro đã bỏ khỏi default install
  • Filter options ít và kém linh hoạt hơn ss nhiều

ss: Nhanh, hiện đại, nhưng cần làm quen syntax

Ưu điểm:

  • Trên server với 5.000+ socket, ss trả kết quả dưới 1 giây; netstat có thể mất cả phút
  • Filter expression language rất mạnh — lọc theo IP, subnet, port, state, process trong một lệnh
  • Hiển thị thêm thông tin TCP timer, congestion window — thứ netstat không có
  • Đang được phát triển tích cực, là công cụ chuẩn trên mọi distro Linux hiện đại

Nhược điểm:

  • Syntax filter khác hoàn toàn với netstat, mất vài buổi để nhớ
  • Output lần đầu nhìn vào hơi lạ, đặc biệt cột Process với format users:(("nginx",pid=5678,fd=7))

Chọn công cụ nào cho tình huống nào?

Sau 6 tháng dùng cả hai, mình rút ra được quy tắc khá đơn giản:

  • Server production, nhiều kết nối: Dùng ss — không bàn cãi. Trên server có vài nghìn connection đang mở, ss trả kết quả trong vài giây trong khi netstat có thể mất cả phút.
  • Debug nhanh trên máy dev hoặc workstation: Cả hai đều được, nhưng mình vẫn dần chuyển về ss để giữ thói quen nhất quán.
  • Cần routing table hoặc interface statistics: Dùng ip routeip -s link từ iproute2 thay vì netstat -r — cùng gói với ss, nhất quán hơn.

Hướng dẫn sử dụng thực tế

Kiểm tra port đang lắng nghe

Tác vụ mình làm nhiều nhất — xem service nào đang chiếm port nào:

# Dùng ss (khuyến nghị)
ss -tlnp

# Giải thích flags:
# -t : TCP only
# -l : listening sockets
# -n : hiển thị số port thay vì tên service (nhanh hơn)
# -p : hiển thị process name và PID

# Dùng netstat tương đương
netstat -tlnp

Output của ss -tlnp trông như sau:

State   Recv-Q  Send-Q  Local Address:Port  Peer Address:Port  Process
LISTEN  0       128     0.0.0.0:22          0.0.0.0:*          users:(("sshd",pid=1234,fd=3))
LISTEN  0       511     0.0.0.0:80          0.0.0.0:*          users:(("nginx",pid=5678,fd=6))
LISTEN  0       511     0.0.0.0:443         0.0.0.0:*          users:(("nginx",pid=5678,fd=7))

Tìm process nào đang chiếm một port cụ thể

Tình huống hay gặp nhất: service không start được, báo port đã bị chiếm:

# Kiểm tra port 8080 đang bị chiếm bởi ai
ss -tlnp | grep :8080

# Hoặc dùng filter expression của ss
ss -tlnp 'sport = :8080'

# Output sẽ có dạng: users:(("node",pid=12345,fd=10))
# Kill process đó bằng:
kill -9 12345

Xem tất cả kết nối đang hoạt động

# Tất cả TCP connections đang ESTABLISHED
ss -tn state established

# Đếm số kết nối theo trạng thái
ss -tan | awk 'NR>1 {print $1}' | sort | uniq -c | sort -rn

# Tổng quan nhanh bằng ss -s
ss -s

Output ss -s rất hữu ích để đánh giá nhanh tình trạng server:

Total: 234 (kernel 312)
TCP:   45 (estab 23, closed 5, orphaned 0, timewait 17)
UDP:   8

Filter kết nối theo IP hoặc subnet

Tính năng này mình dùng nhiều khi quản lý office — cần xem máy nào đang kết nối đến server nội bộ, hoặc kiểm tra xem traffic từ một IP cụ thể đang đổ vào port nào:

# Xem tất cả kết nối từ subnet 192.168.1.0/24
ss -tn 'dst 192.168.1.0/24'

# Kết nối đến một IP cụ thể
ss -tn 'dst 192.168.1.100'

# Kết nối từ một IP cụ thể
ss -tn 'src 10.0.0.5'

# Kết hợp: kết nối từ subnet đến port 443
ss -tn 'src 192.168.1.0/24 and dport = :443'

Xem TCP timer — tính năng chỉ có trên ss

# Xem TCP timer (keepalive, retransmit timeout...)
ss -tn -o

# Output sẽ có thêm cột timer:
# timer:(keepalive,1min3sec,0)
# Nghĩa: keepalive timer còn 1 phút 3 giây, 0 lần retransmit

Theo dõi realtime

# Cập nhật mỗi 2 giây
watch -n 2 'ss -s'

# Hoặc theo dõi số kết nối theo trạng thái
watch -n 2 'ss -tan | awk "NR>1 {print \$1}" | sort | uniq -c | sort -rn'

Debugging workflow khi phát hiện kết nối bất thường

Hồi mình phát hiện một server trong datacenter đang bị scan port từ IP lạ, quy trình debug như sau:

# Bước 1: Xem có SYN flood không
ss -tn state syn-recv

# Bước 2: Đếm kết nối theo IP nguồn — phát hiện IP đang flood
ss -tn | awk 'NR>1 {print $5}' | grep -oP '^[\d.]+' | sort | uniq -c | sort -rn | head -20

# Bước 3: Xem toàn bộ kết nối từ IP đáng ngờ
ss -tn 'src 203.0.113.50'

# Bước 4: Kiểm tra TIME_WAIT có bất thường không
ss -tan state time-wait | wc -l

Với netstat, bước 2 mất cả phút khi server có nhiều kết nối mở. Đây chính là lý do thực tế mình chuyển sang ss — không phải vì đọc blog kêu hay, mà vì ngồi chờ output trong lúc đang debug incident thật sự rất ức chế.

Alias tiện dụng để dùng nhanh hàng ngày

Ba alias này mình thêm vào ~/.bashrc trên tất cả server, tiết kiệm được khá nhiều lần gõ:

# Thêm vào ~/.bashrc
alias ports='ss -tlnp'                        # Xem port đang listen
alias conns='ss -tn state established'         # Kết nối đang active
alias socksum='ss -s'                          # Tổng quan socket statistics

# Reload
source ~/.bashrc

Cài đặt nếu chưa có

# Debian/Ubuntu
sudo apt install iproute2     # ss (thường đã có sẵn)
sudo apt install net-tools    # netstat (nếu cần)

# CentOS/RHEL/Rocky Linux
sudo dnf install iproute      # ss
sudo dnf install net-tools    # netstat

# Kiểm tra version
ss -V
netstat --version

Trên Ubuntu 22.04 và Debian 12, ss đã được cài sẵn. netstat thì không — bạn phải cài thêm nếu cần.

Tổng kết

Học từ đầu? Học ss luôn, bỏ qua netstat. Syntax hơi khác một chút nhưng đáng bỏ thời gian làm quen. Đã quen netstat và muốn chuyển? Nhớ vài lệnh core của ss là đủ cho 90% tác vụ hàng ngày.

Với mình, sau nửa năm dùng ss trên production, mình không quay lại netstat nữa. Không phải vì ai bảo — mà vì nó nhanh hơn và filter mạnh hơn đúng lúc thực sự cần.

Share: