Lệnh ss: kiểm tra cổng và tiến trình trên Linux, so sánh với netstat
Trên máy chủ Linux, bạn kiểm tra cổng nào đang mở và ai đang kết nối bằng lệnh ss. ss là công cụ tra cứu socket của iproute2 thay cho netstat. Khi dùng ss tra cứu các cổng đang lắng nghe (LISTEN) và các kết nối trên máy chủ Debian 12, chúng tôi xác nhận rằng ở tài khoản thường, dù thêm -p thì tên chương trình do tài khoản khác khởi chạy vẫn không hiện trong cột Process.
Kết quả bên dưới được chạy với locale tiếng Anh. Địa chỉ của máy chủ và phía bên kia được ghi bằng địa chỉ ví dụ.
1️⃣ Cách dùng cơ bản lệnh ss và các cột trong kết quả
Nếu chạy ss không kèm tùy chọn, các cổng đang lắng nghe sẽ bị bỏ qua và chỉ hiện các socket đã thiết lập kết nối. Trên máy chủ thử nghiệm, những dòng đầu tiên đều là socket Unix (u_str, u_dgr) mà các chương trình bên trong máy chủ dùng để giao tiếp với nhau.
ss | head -n 5Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
u_str ESTAB 0 0 * 1013903 * 1013904
u_dgr ESTAB 0 0 * 1013960 * 13394
u_str ESTAB 0 0 * 1013907 * 1013908
u_str ESTAB 0 0 * 46066198 * 46066199Vì vậy, để chỉ xem kết nối TCP, hãy thêm -t. Socket Unix biến mất và ở vị trí cổng hiện tên dịch vụ như ssh và https thay cho số.
ss -tState Recv-Q Send-Q Local Address:Port Peer Address:Port Process
ESTAB 0 0 203.0.113.10:ssh 198.51.100.7:51114
ESTAB 0 0 203.0.113.10:26676 192.0.2.15:https
ESTAB 0 0 203.0.113.10:29714 192.0.2.16:httpsNếu thêm cả -n, số cổng sẽ giữ nguyên mà không bị đổi thành tên dịch vụ.
ss -tnState Recv-Q Send-Q Local Address:Port Peer Address:Port Process
ESTAB 0 0 203.0.113.10:22 198.51.100.7:51114
ESTAB 0 0 203.0.113.10:26676 192.0.2.15:443
ESTAB 0 0 203.0.113.10:29714 192.0.2.16:443Cột Recv-Q và Send-Q mang ý nghĩa khác nhau tùy trạng thái của socket. Ở socket đang kết nối, Recv-Q là số byte đã nhận nhưng chương trình chưa đọc, còn Send-Q là số byte đã gửi nhưng phía bên kia chưa xác nhận đã nhận.
Ở socket đang lắng nghe, Recv-Q là số kết nối đang chờ trong hàng đợi, còn Send-Q là kích thước tối đa của hàng đợi. Ý nghĩa của hai cột này lấy theo phần giải thích trong trang man netstat(8) của net-tools.
2️⃣ Kiểm tra cổng trên Linux (-tln, -uln, -tulpn)
Kết quả không kèm tùy chọn không hiện các cổng đang chờ kết nối, nên khi kiểm tra cổng đang mở, hãy thêm -l để chỉ chọn socket đang lắng nghe. [ss -tln] in các cổng TCP đang lắng nghe dưới dạng số.
ss -tlnState Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
LISTEN 0 511 0.0.0.0:443 0.0.0.0:*
LISTEN 0 511 127.0.0.1:8080 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 511 [::]:80 [::]:*
LISTEN 0 511 [::]:443 [::]:*Nếu Local Address là 0.0.0.0, socket nhận kết nối đến mọi địa chỉ IPv4 của máy chủ; nếu là 127.0.0.1 thì chỉ có thể kết nối từ bên trong máy chủ. [::] nghĩa là mọi địa chỉ IPv6, nên các cổng 22, 80 và 443 đều mở trên cả IPv4 lẫn IPv6.
Bỏ -n thì số cổng sẽ đổi thành tên dịch vụ. Cổng 8080 hiện thành http-alt.
ss -tlState Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 128 0.0.0.0:ssh 0.0.0.0:*
LISTEN 0 511 0.0.0.0:http 0.0.0.0:*
LISTEN 0 511 0.0.0.0:https 0.0.0.0:*
LISTEN 0 511 127.0.0.1:http-alt 0.0.0.0:*
LISTEN 0 128 [::]:ssh [::]:*
LISTEN 0 511 [::]:http [::]:*
LISTEN 0 511 [::]:https [::]:*UDP không thiết lập kết nối, nên ngay cả socket đang lắng nghe cũng không có trạng thái LISTEN. Cột trạng thái trong kết quả [ss -uln] đều là UNCONN. Cổng 68 (bootpc) là máy khách DHCP, còn cổng 123 (ntp) là cổng đồng bộ thời gian.
ss -ulnState Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
UNCONN 0 0 0.0.0.0:68 0.0.0.0:*
UNCONN 0 0 203.0.113.10:123 0.0.0.0:*
UNCONN 0 0 127.0.0.1:123 0.0.0.0:*
UNCONN 0 0 0.0.0.0:123 0.0.0.0:*
UNCONN 0 0 [::1]:123 [::]:*
UNCONN 0 0 [::]:123 [::]:*Để xem TCP và UDP cùng lúc, hãy gộp các tùy chọn như [ss -tulpn]. Khi có từ hai loại trở lên, cột Netid sẽ được thêm ở đầu.
ss -tulpnNetid State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
udp UNCONN 0 0 0.0.0.0:68 0.0.0.0:*
udp UNCONN 0 0 203.0.113.10:123 0.0.0.0:*
udp UNCONN 0 0 127.0.0.1:123 0.0.0.0:*
udp UNCONN 0 0 0.0.0.0:123 0.0.0.0:*
udp UNCONN 0 0 [::1]:123 [::]:*
udp UNCONN 0 0 [::]:123 [::]:*
tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
tcp LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
tcp LISTEN 0 511 0.0.0.0:443 0.0.0.0:*
tcp LISTEN 0 511 127.0.0.1:8080 0.0.0.0:*
tcp LISTEN 0 128 [::]:22 [::]:*
tcp LISTEN 0 511 [::]:80 [::]:*
tcp LISTEN 0 511 [::]:443 [::]:*3️⃣ Kiểm tra tiến trình bằng lệnh ss (-p)
-p là tùy chọn in chương trình đang dùng socket vào cột Process. Thế nhưng khi chạy [ss -tlnp] ở tài khoản thường trên máy chủ thử nghiệm, cột Process lại trống như bên dưới, trông như tùy chọn không có tác dụng.
ss -tlnpState Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
LISTEN 0 511 0.0.0.0:443 0.0.0.0:*
LISTEN 0 511 127.0.0.1:8080 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 511 [::]:80 [::]:*
LISTEN 0 511 [::]:443 [::]:*ss tìm tiến trình đang dùng socket bằng cách đọc thư mục fd của từng tiến trình trong /proc. Tài khoản thường không mở được thư mục fd của tiến trình do tài khoản khác khởi chạy, nên tên chương trình đó không được đưa vào cột. Nếu mở thư mục của tiến trình số 1 do root khởi chạy từ tài khoản thường, bạn sẽ gặp lỗi quyền.
ls /proc/1/fdls: cannot open directory '/proc/1/fd': Permission deniedChương trình khởi chạy bằng tài khoản của chính bạn vẫn hiện trong cột Process dù ở tài khoản thường. Điều này đã được kiểm tra bằng cách chạy máy chủ web đơn giản của python3 ở cổng 8000 của 127.0.0.1.
python3 -m http.server 8000 --bind 127.0.0.1 &Sau khi chạy, hãy thêm [sport = :8000] để chỉ tra cứu dòng của cổng 8000.
ss -tlnp sport = :8000State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 5 127.0.0.1:8000 0.0.0.0:* users:(("python3",pid=343015,fd=3))Trong dấu ngoặc sau users lần lượt có tên chương trình, pid và số mô tả tệp (fd).
Kiểm tra xong, hãy tắt máy chủ web đơn giản bằng [kill %1]. Sau khi tắt, nếu chạy lại [ss -tln sport = :8000] thì chỉ còn dòng tiêu đề và dòng của cổng 8000 không xuất hiện nữa.
Khi chạy bằng tài khoản root, ss đọc được thông tin của mọi tiến trình nên cột Process được điền đầy. Nếu nhiều tiến trình cùng lắng nghe trên một cổng, trong ngoặc users sẽ có số mục tương ứng nối tiếp nhau. Tên chương trình và pid trong kết quả của root bên dưới là giá trị ví dụ.
ss -tlnp sport = :443State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 511 0.0.0.0:443 0.0.0.0:* users:(("app",pid=2101,fd=6),("app",pid=2100,fd=6))
LISTEN 0 511 [::]:443 [::]:* users:(("app",pid=2101,fd=7),("app",pid=2100,fd=7))Để tìm chương trình theo số cổng, bạn cũng có thể dùng lệnh lsof theo dạng [lsof -i :443].
Cột Process thay đổi thế nào theo từng tài khoản, bạn có thể so sánh bằng cách đổi tài khoản trong sơ đồ bên dưới.
4️⃣ Tùy chọn lọc theo trạng thái và cổng của ss
Ngay cả sau khi đã kiểm tra các cổng đang mở, bạn vẫn phải lọc riêng xem ai đang kết nối vào các cổng đó lúc này. ss chỉ giữ lại các dòng bạn muốn khi bạn thêm điều kiện lọc sau tùy chọn.
Ghi tên trạng thái sau state thì chỉ còn lại các socket ở trạng thái đó. Kết quả của [ss -tn state established] không có cột State và bắt đầu từ cột Recv-Q.
ss -tn state establishedRecv-Q Send-Q Local Address:Port Peer Address:Port Process
0 0 203.0.113.10:22 198.51.100.7:51114
0 0 203.0.113.10:26676 192.0.2.15:443
0 0 203.0.113.10:29714 192.0.2.16:443Cổng được lọc bằng dport (cổng phía bên kia) và sport (cổng phía mình). Các kết nối đi từ máy chủ ra máy chủ https bên ngoài được chọn bằng [dport = :443].
ss -tn dport = :443State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
ESTAB 0 0 203.0.113.10:26676 192.0.2.15:443
ESTAB 0 0 203.0.113.10:29714 192.0.2.16:443Dùng sport cùng với -l thì bạn chỉ kiểm tra được cổng đó có đang lắng nghe hay không.
ss -tln sport = :22State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*Nhiều điều kiện thì gộp bằng dấu ngoặc và or, rồi bọc trong dấu nháy đơn để shell không đọc dấu ngoặc trước. Bên dưới là kết quả chỉ chọn kết nối ssh theo ví dụ trong trang man.
ss -tn state established '( dport = :ssh or sport = :ssh )'Recv-Q Send-Q Local Address:Port Peer Address:Port Process
0 0 203.0.113.10:22 198.51.100.7:51114TIME-WAIT là trạng thái còn lưu lại một lúc sau khi kết nối bị ngắt. Trạng thái này không hiện trong kết quả mặc định, nên phải chọn riêng bằng [state time-wait] mới thấy.
ss -tn state time-waitRecv-Q Send-Q Local Address:Port Peer Address:PortProcess
0 0 127.0.0.1:28750 127.0.0.1:80
0 0 127.0.0.1:57698 127.0.0.1:8080
0 0 [::1]:31936 [::1]:80Nếu ghi sai tên trạng thái, lệnh sẽ kết thúc ngay và chỉ để lại một dòng lỗi [wrong state name]. Bên dưới là kết quả khi cố tình nhập foo. Các tên dùng được có trong dòng TCP-STATES của kết quả [ss -h].
ss -tn state fooss: wrong state name: foo📌 Tùy chọn chính: kết quả chạy trong bài này
| Tùy chọn | Chức năng | Kết quả trong bài này | |
|---|---|---|---|
| -t | Chỉ in socket TCP | Socket Unix biến mất, ở vị trí cổng hiện tên dịch vụ như ssh và https | |
| -n | In số cổng thay vì tên dịch vụ | Trong ss -tn, ssh hiện là 22 và https là 443 | |
| -l | Chỉ in socket đang lắng nghe (LISTEN) | ss -tln hiện các cổng đang lắng nghe như 22, 80 và 443 | |
| -u | Chỉ in socket UDP | Cột trạng thái của ss -uln đều là UNCONN | |
| -p | In chương trình đang dùng socket vào cột Process | Ở tài khoản thường, chỉ python3 do tài khoản tôi khởi chạy là hiện tên và pid, chương trình của tài khoản khác để trống | |
| -s | Tóm tắt số lượng theo loại thay vì liệt kê socket | estab 9 ở dòng TCP khớp với 9 dòng kết quả state established khi bỏ dòng tiêu đề | |
| -4 | Chỉ in socket IPv4 | Trong ss -t4ln, các dòng bắt đầu bằng [::] bị bỏ | |
| -6 | Chỉ in socket IPv6 | Trong ss -t6ln, các dòng bắt đầu bằng 0.0.0.0 và 127.0.0.1 bị bỏ | |
| -H | Chỉ in các dòng socket, không có dòng tiêu đề | Số dòng của ss -H -tln | wc -l không tính dòng tiêu đề | |
| state TRẠNG_THÁI | Chỉ giữ socket ở trạng thái đó | Kết quả state established bắt đầu từ Recv-Q và không có cột State; tên không tồn tại cho ra [wrong state name: foo] | |
| dport = :CỔNG | Lọc theo cổng phía bên kia | dport = :443 cho hai dòng kết nối đi ra máy chủ https bên ngoài | |
| sport = :CỔNG | Lọc theo cổng phía mình | sport = :22 dùng cùng -l cho hai dòng cổng 22 đang lắng nghe, IPv4 và IPv6 | |
| src ĐỊA_CHỈ | Chỉ giữ socket của địa chỉ đó | ss -tln src 127.0.0.1 chỉ hiện các cổng phía 127.0.0.1, vốn chỉ nhận kết nối từ bên trong máy chủ |
📎 Tùy chọn khác: theo tài liệu hướng dẫn chính thức
| Tùy chọn | Chức năng | |
|---|---|---|
| -a, --all | In cùng lúc socket đang lắng nghe và socket đang kết nối | |
| -r, --resolve | Phân giải địa chỉ và số cổng thành tên | |
| -e, --extended | In thông tin chi tiết của từng socket như uid và inode | |
| -o, --options | In thông tin bộ hẹn giờ như truyền lại TCP và keepalive | |
| -m, --memory | In bộ nhớ mà từng socket sử dụng | |
| -i, --info | In thông tin nội bộ của TCP (rtt, cwnd, v.v.) | |
| -x, --unix | Chỉ in socket miền Unix | |
| -w, --raw | Chỉ in socket RAW | |
| -f HỌ | Chọn theo họ socket như unix, inet, inet6, link hoặc netlink | |
| -Q, --no-queues | In kết quả không có cột Recv-Q và Send-Q | |
| -K, --kill | Buộc đóng các socket khớp với bộ lọc; socket mà nhân không hỗ trợ sẽ bị bỏ qua | |
| -E, --events | Liên tục in các socket đang bị đóng | |
| -V, --version | In thông tin phiên bản |
🔲 Trình mô phỏng lệnh ss
Trong trình mô phỏng bên dưới, bạn có thể tự nhập các tùy chọn và bộ lọc đã nêu từ đầu đến giờ và so sánh kết quả với [netstat -tln].
5️⃣ Tóm tắt socket của ss (-s)
-s in bản tóm tắt số lượng theo loại thay vì danh sách socket. Theo trang man, nó không đếm từng mục trong danh sách mà gom số liệu từ nhiều nguồn thống kê.
ss -sTotal: 340
TCP: 48 (estab 9, closed 15, orphaned 0, timewait 13)
Transport Total IP IPv6
RAW 0 0 0
UDP 8 4 4
TCP 33 25 8
INET 41 29 12
FRAG 0 0 0estab ở dòng TCP là số kết nối đang được thiết lập lúc này. Vì vậy có thể đối chiếu nó với số dòng mà [state established] in ra cùng thời điểm.
ss -tn state established | wc -l10Bỏ một dòng tiêu đề khỏi 10 dòng kết quả thì còn 9 dòng, đúng bằng estab 9 của -s. timewait 13 là số socket TIME-WAIT, vốn chỉ thấy khi chọn bằng [state time-wait].
6️⃣ So sánh lệnh ss với netstat
netstat nằm trong gói net-tools, và trang man của gói này ghi netstat là chương trình gần như không còn được dùng (mostly obsolete), đồng thời khuyên dùng ss thay thế. Tuy vậy, các script viết theo định dạng kết quả của netstat sẽ không đọc nguyên được kết quả của ss, vì thứ tự cột và cách ghi địa chỉ khác nhau.
Khi in các cổng TCP đang lắng nghe trên cùng máy chủ bằng cả hai lệnh, netstat đặt trạng thái ở cuối cùng và ghi địa chỉ IPv6 như :::22.
netstat -tlnActive Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN
tcp6 0 0 :::22 :::* LISTEN
tcp6 0 0 :::80 :::* LISTEN
tcp6 0 0 :::443 :::* LISTENỞ ss, trạng thái nằm đầu tiên và địa chỉ IPv6 được bọc trong ngoặc vuông như [::]:22.
ss -tlnState Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
LISTEN 0 511 0.0.0.0:443 0.0.0.0:*
LISTEN 0 511 127.0.0.1:8080 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 511 [::]:80 [::]:*
LISTEN 0 511 [::]:443 [::]:*Các tùy chọn netstat hay dùng khi chuyển sang lệnh ss và ip sẽ như sau.
| netstat | Lệnh thay thế / nội dung hiển thị |
|---|---|
| netstat -tln | ss -tlnCổng TCP đang lắng nghe, dạng số |
| netstat -tulpn | ss -tulpnCổng TCP và UDP đang lắng nghe cùng chương trình |
| netstat -tan | ss -tanMọi socket TCP, dạng số |
| netstat -r | ip routeBảng định tuyến |
| netstat -i | ip -s linkThống kê giao diện mạng |
🔢 FAQ & nội dung đề xuất









ℹ️ Thông báo tiếp thị liên kết
Nội dung trên trang này có chứa liên kết affiliate (tiếp thị liên kết). Khi khách truy cập mua sản phẩm hoặc dịch vụ qua các liên kết này, trang sẽ nhận hoa hồng từ bên bán. Trong quá trình đó, số tiền người mua phải trả (sẽ giảm khi có chương trình khuyến mãi ↓) không hề tăng lên. Giá, khuyến mãi và tình trạng hàng được đăng theo thời điểm viết bài và có thể khác với thực tế, vì vậy hãy kiểm tra lại lần cuối với bên bán trước khi mua. Việc chọn và đánh giá sản phẩm dựa trên tiêu chí riêng của trang; việc có nhận hoa hồng hay không không ảnh hưởng đến thứ tự giới thiệu hay nội dung đánh giá.
