文章目录
一、简介
ss(Socket Statistic )是一个用于查看网络套接字统计信息的命令行工具,是netstat的现代替代品。它使用 Linux 内核的 TCP 控制块(TCP Control Block)直接获取信息,因此速度更快、效率更高。
netstat:
- 主要通过读取
/proc文件系统中的文件(如/proc/net/tcp、/proc/net/udp等)来获取网络连接信息。- 这些文件是由内核在用户空间请求时动态生成的,涉及大量字符串格式化和文本解析。
- 每次调用
netstat都会重新读取并解析这些伪文件,开销较大。ss:
- 使用 Netlink sockets (特别是
NETLINK_INET_DIAG)直接与内核通信。- 能以二进制结构体的形式高效获取 TCP/UDP 套接字的原始数据,避免了文本解析的开销。
- 数据是【按需】从内核的 TCP 控制块等数据结构中直接导出的,效率更高。
二、语法
bash
ss [选项] [过滤器]
1、常用选项
| 选项 | 说明 |
|---|---|
-h, --help |
显示帮助信息 |
-V, --version |
显示版本信息 |
-n, --numeric |
不解析服务名称(显示端口号而非服务名) |
-r, --resolve |
解析主机名和端口名(默认不解析) |
-a, --all |
显示所有套接字(包括监听和非监听) |
-l, --listening |
仅显示监听状态的套接字 |
-o, --options |
显示定时器信息(如 keepalive) |
-e, --extended |
显示详细/扩展信息 |
-m, --memory |
显示套接字内存使用情况 |
-p, --processes |
显示使用套接字的进程信息(需 root 或 CAP_NET_ADMIN 权限) |
-i, --info |
显示内部 TCP 信息(如 cwnd、rtt 等) |
-s, --summary |
打印套接字使用摘要(类似 netstat -s) |
默认情况下,
ss显示除监听套接字外的所有已建立连接。若要查看监听端口,请使用-l。
2、协议类型过滤
| 选项 | 说明 |
|---|---|
-t, --tcp |
显示 TCP 套接字 |
-u, --udp |
显示 UDP 套接字 |
-d, --dccp |
显示 DCCP 套接字 |
-w, --raw |
显示 RAW 套接字 |
-x, --unix |
显示 Unix 域套接字 |
-f FAMILY, --family=FAMILY |
指定地址族(如 inet, inet6, unix, netlink 等) |
-4, --ipv4 |
仅显示 IPv4 协议的套接字,相当于 -f inet |
-6, --ipv6 |
仅显示 IPv6 协议的套接字,相当于 -f inet6 |
这些协议类型可以常规选项组合在一起写成
-tuln,这是POSIX 风格的选项简写,等价于-t -u -l -n。
3、过滤器
过滤器用于进一步筛选 已选定的套接字,使用类似 SQL 的表达式语法,必须放在所有选项之后,并以空格分隔。
bash
ss [选项] [ state STATE-FILTER ] [ EXPRESSION ]
# 示例
ss -t state established dst 10.0.0.5
1) 连接状态过滤
bash
STATE-FILTER := {all|connected|synchronized|bucket|big|TCP-STATES}
TCP-STATES := {established|syn-sent|syn-recv|fin-wait-{1,2}|time-wait|closed|close-wait|last-ack|listening|closing}
connected := {established|syn-sent|syn-recv|fin-wait-{1,2}|time-wait|close-wait|last-ack|closing}
synchronized := {established|syn-recv|fin-wait-{1,2}|time-wait|close-wait|last-ack|closing}
bucket := {syn-recv|time-wait}
big := {established|syn-sent|fin-wait-{1,2}|closed|close-wait|last-ack|listening|closing}
这些是 ss 提供的高层抽象状态组,用于简化常用场景的过滤:
| 名称 | 包含的状态 | 语义说明 |
|---|---|---|
all |
所有 TCP 状态 | 显示全部连接(默认行为) |
connected |
{established, syn-sent, syn-recv, fin-wait-1, fin-wait-2, time-wait, close-wait, last-ack, closing} |
表示【已建立或正在关闭】的连接(排除 listening 和 closed) |
synchronized |
{established, syn-recv, fin-wait-1, fin-wait-2, time-wait, close-wait, last-ack, closing} |
已完成三次握手后的连接(排除 syn-sent 和 listening 等) |
bucket |
{syn-recv, time-wait} |
内核中使用【小内存桶】(small memory buckets)管理的状态,通常用于优化高并发 |
big |
{established, syn-sent, fin-wait-1, fin-wait-2, closed, close-wait, last-ack, listening, closing} |
需要完整 struct tcp_sock 结构的状态(占用更多内存) |
Linux 内核对某些轻量级 TCP 状态(如
time-wait和syn-recv)使用精简数据结构(称为tcp_tw_bucket或request_sock),以节省内存。bucket就是指这些状态。
原始 TCP 状态(RFC 793 定义)
这是 TCP 协议标准中定义的具体状态,可直接用于精确过滤:
| 状态(TCP-STATES) | 说明 |
|---|---|
established |
连接已建立,正在通信 |
syn-sent |
客户端已发送 SYN,等待 ACK+SYN |
syn-recv |
服务端收到 SYN,已回复 SYN+ACK,等待最终 ACK(处于半开连接) |
fin-wait-1 |
主动关闭方已发送 FIN,等待对方 ACK 或 FIN |
fin-wait-2 |
已收到对方对 FIN 的 ACK,等待对方发送 FIN |
time-wait |
主动关闭方在收到对方 FIN 并 ACK 后,进入 2MSL 等待(确保对方收到 ACK) |
closed |
套接字未使用(极少出现在 ss 输出中) |
close-wait |
被动关闭方已收到 FIN,等待本地应用调用 close() |
last-ack |
被动关闭方已发送 FIN,等待对方 ACK |
listening |
服务端监听状态(LISTEN) |
closing |
双方同时发送 FIN(较少见) |
按连接生命周期阶段分类:
| 阶段 | 对应状态 |
|---|---|
| 监听阶段 | listening |
| 连接建立阶段 | syn-sent, syn-recv |
| 数据传输阶段 | established |
| 连接关闭阶段 | fin-wait-1, fin-wait-2, close-wait, last-ack, closing, time-wait |
| 未使用/空闲 | closed |
2) 地址与端口过滤表达式
| 表达式语法 | 说明 | 示例 |
|---|---|---|
dst ADDR |
目标 IP 地址(对 TCP/UDP 客户端连接,表示远端) | dst 192.168.1.100 |
src ADDR |
源 IP 地址(本地地址) | src 10.0.0.5 |
dport OP PORT |
目标端口(远端端口),OP 可为 =, !=, <, <=, >, >= |
dport = :80 dport > :1024 |
sport OP PORT |
源端口(本地端口) | sport = :22 |
ADDR:PORT |
同时匹配地址和端口(较少用,建议分开写) | 192.168.1.1:80(不推荐) |
( expr ) |
分组逻辑,支持嵌套 | ( dport = :80 or dport = :443 ) |
and / or / not |
逻辑运算符(可省略 and,空格即表示 and) |
dst 10.0.0.1 and dport = :22 not dst 127.0.0.1 |
端口写法注意:
- 端口前必须加冒号
:,如:80、:ssh(若未使用-n,可解析服务名)- 使用
-n时,只能用数字端口(如:80),否则会尝试解析/etc/services
示例
bash
# 查看目标端口为 22 的连接
ss dport = :22
# 查看本地监听 80 端口
ss -ltn sport = :80
# 查看与 192.168.1.100 的所有连接
ss dst 192.168.1.100
# 查看源 IP 为 10.0.0.5 且目标端口为 443 的连接
ss src 10.0.0.5 dport = :443
# 查看非本地回环的所有 TCP 连接
ss -tn not dst 127.0.0.1
三、输出字段说明
| 字段名 | 说明 |
|---|---|
| State | 连接状态(如 ESTAB、LISTEN) |
| Recv-Q | 接收队列中的字节数(或监听套接字的已完成连接数) |
| Send-Q | 发送队列中的字节数(或监听套接字的最大未完成连接数) |
| Local Address:Port | 本地地址和端口 |
| Peer Address:Port | 对端地址和端口 |
扩展字段(需 -e 或 -i) |
说明 |
|---|---|
| uid | 套接字所属用户的用户 ID(User ID) |
| ino | 套接字的 inode 编号,可用于关联 /proc/net/tcp 或 lsof |
| ts | 若启用了 TCP 时间戳选项(Timestamps),显示字符串 ts |
| sack | 若启用了选择性确认(Selective ACK),显示字符串 sack |
| ecn | 若启用了显式拥塞通知(ECN),显示字符串 ecn |
| ecnseen | 若在接收的数据包中检测到 ECN 标记,显示字符串 ecnseen |
| fastopen | 若启用了 TCP Fast Open,显示字符串 fastopen |
| cong_alg | 当前使用的拥塞控制算法名称(如 cubic, reno, bbr 等) |
| wscale:<snd_wscale>:<rcv_wscale> | 窗口缩放因子,分别表示发送端和接收端的 scale 值(若启用 window scaling) |
| rto:<icsk_rto> | 重传超时时间(Retransmission Timeout),单位:毫秒 |
| backoff:<icsk_backoff> | 指数退避计数器,实际 RTO = rto << backoff |
| rtt:<rtt>/<rttvar> | 平均往返时间(RTT)及其方差(RTTVAR),单位:毫秒 |
| ato:<ato> | 延迟 ACK 超时时间(ACK Timeout),单位:毫秒 |
| mss:<mss> | 最大报文段大小(Maximum Segment Size),单位:字节 |
| cwnd:<cwnd> | 拥塞窗口大小(Congestion Window),单位:MSS 个数 |
| pmtu:<pmtu> | 路径 MTU(Path MTU),单位:字节 |
| ssthresh:<ssthresh> | 慢启动阈值(Slow Start Threshold),单位:MSS 个数 |
| bytes_acked:<bytes_acked> | 已被确认的字节数(累计) |
| bytes_received:<bytes_received> | 已接收的字节数(累计) |
| segs_out:<segs_out> | 已发送的 TCP 段数量 |
| segs_in:<segs_in> | 已接收的 TCP 段数量 |
| send <send _bps> | 当前发送速率(egress bandwidth),单位:bps |
| lastsnd:<lastsnd> | 距离上次发送数据包的时间,单位:毫秒 |
| lastrcv:<lastrcv> | 距离上次接收数据包的时间,单位:毫秒 |
| lastack:<lastack> | 距离上次收到 ACK 的时间,单位:毫秒 |
| pacing_rate <pacing_rate>bps/<max_pacing_rate> | 当前 pacing 发送速率及最大允许速率(用于 BBR 等算法) |
| rcv_space:<rcv_space> | 接收缓冲区自动调优机制使用的参考空间大小(字节) |
| tcp-ulp-mptcp flags:[...] | 若使用 MPTCP(多路径 TCP)作为 ULP(Upper Layer Protocol),显示其标志位(如 M=master, m=backup, B=backup available 等) |
- 上述字段并非每次都会全部出现,仅当内核中对应功能启用或有相关状态时才会显示。
-e(extended):显示uid、ino等基本扩展信息。-i(info):显示 TCP 内部状态信息,如cwnd、rtt、timer等,主要用于网络性能分析。- 两者可同时使用:
ss -ti或ss -ei。
四、示例
bash
# 1. 列出所有监听的 TCP 端口(数字形式)
ss -tln
# 2. 列出所有 UDP 连接
ss -u
# 3. 显示使用套接字的进程
ss -pl
# 4. 查看所有已建立的 SSH 连接
ss -tn dport = :22 state established
# 5. 统计各类套接字数量
ss -s
# 6. 查看 Unix 域套接字
ss -x
# 7. 查找哪个进程在监听 3306 端口
ss -ltnp 'sport = :3306'
# 8. 显示 TCP 连接的详细信息(含 RTT、cwnd)
ss -ti
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
ESTAB 0 48 192.168.40.233:ssh 192.168.40.183:51586
cubic wscale:8,7 rto:240 rtt:39.95/12.792 ato:40 mss:1460 pmtu:1500 rcvmss:1460 advmss:1460 cwnd:10 bytes_sent:17725 bytes_acked:17677 bytes_received:18828 segs_out:385 segs_in:419 data_segs_out:156 data_segs_in:315 send 2.92Mbps lastsnd:2 lastrcv:2 lastack:2 pacing_rate 5.85Mbps delivery_rate 187Mbps delivered:156 busy:4005ms unacked:1 rcv_space:14600 rcv_ssthresh:64076 minrtt:0.101