Linux服务器如何查看实时连接数?连接统计与异常流量分析

服务器跑着跑着突然卡顿,用户说"网站打不开",一查 CPU 不高、内存不满,问题很可能出在连接上:要么连接数暴涨把资源吃光了,要么某个 IP 正在疯狂扫端口。这时候第一件事不是重启服务,而是把"当前有多少连接、都是谁连过来的、处于什么状态"看清楚。

这篇文章讲三件事。先讲实时连接数到底该从哪几个维度看,避免只盯着一个总数而误判;再讲 ss、netstat、conntrack 这些工具的统计用法,把连接按状态、按来源 IP 聚合出来;最后讲怎么从统计结果里识别异常流量,比如端口扫描、SYN Flood、连接泄漏,并用 tcpdump 抓包印证。

文中的命令都标注了 RHEL/CentOS/Rocky 与 Debian/Ubuntu 的差异,连接数、速率等量级都标明是经验值,实际以你的业务基线为准。改内核参数或防火墙属于危险操作,文末会给出风险提示和回滚方式。

一、实时连接数要看哪几个维度

很多人查连接数只跑一句 netstat -an | wc -l,得到一个总数就下结论,这是最容易误判的做法。同样是一万个连接,全是 ESTABLISHED 的正常长连接和全是 SYN-RECV 的异常堆积,含义天差地别。所以要从下面几个维度分开看:

  • 连接总数:所有 TCP 连接的条数,反映整体负载量级。单机几万到几十万连接是常见量级(经验值),具体看内存和业务模型。
  • 按状态分布:ESTABLISHED、TIME-WAIT、SYN-RECV、CLOSE-WAIT 各有多少,异常堆积往往藏在非 ESTABLISHED 状态里。
  • 按对端 IP 分布:哪个来源 IP 连接最多,是识别扫描和攻击的关键。
  • 按本地端口分布:哪个服务端口承载了最多连接,帮助定位是哪项业务在高负载。
  • 新建连接速率:每秒新建多少连接,反映的是"流量强度"而不是"存量",短连接业务尤其要看这个。

只看存量不看速率,会漏掉"连接数不高但每秒新建上万次"的短连接攻击;只看总数不看状态,会把正常的 TIME-WAIT 当成故障。把这两个维度结合起来,判断才靠谱。

二、基础统计命令:ss 与 netstat

ss 属于 iproute2 包,现代发行版基本自带。没装的话,RHEL/CentOS/Rocky 用 yum install iproute(或 dnf install iproute),Debian/Ubuntu 用 apt install iproute2。netstat 属于 net-tools,很多新系统默认不再安装,RHEL 系用 yum install net-tools,Debian 系用 apt install net-tools。

# 连接总数(最粗暴但最常用的方式)
ss -tan | wc -l
ss -s                       # 更推荐,直接给出状态汇总

# 只看已建立连接的数量
ss -tan state established | wc -l

# 监听端口列表
ss -lntp

# 每秒实时刷新连接总数
watch -n 1 'ss -s'

ss -s 的输出直观给出各类连接的汇总,比手工数行数方便得多:

Total: 1532
TCP:   1284 (estab 842, closed 402, orphaned 0, synrecv 0, timewait 400/0)
Transport Total     IP        IPv6
RAW       0         0         0
UDP       12        8         4
TCP       1284      1200      84

这里 estab 是已建立连接数,timewait 是处于 TIME-WAIT 的连接数,synrecv 是半连接排队数。正常情况下 estab 占大头、timewait 占一小部分、synrecv 应该接近 0。如果 synrecv 明显不为 0 甚至持续增长,就要往 SYN Flood 方向查。

如果确实需要 netstat(比如老脚本兼容),用法类似:

netstat -an | wc -l
netstat -an | grep -c ESTABLISHED
netstat -nat | awk '{print $6}' | sort | uniq -c | sort -rn
netstat -anp | grep :80 | wc -l

但要记住 netstat 在大连接数时性能差。上万连接时它可能要遍历 /proc 卡上几十秒,而 ss 直接读内核 netlink 接口,几乎秒出。生产环境诊断优先用 ss。

三、把连接按状态与来源聚合

有了基础总量,下一步是把连接拆分,让异常无处藏身。最实用的是按状态统计和按对端 IP 统计两个维度。

# 按状态聚合,一眼看出哪些状态堆积
ss -tan | awk 'NR>1 {print $1}' | sort | uniq -c | sort -rn

# 按对端 IP 聚合(取 Peer Address 的 IP 部分),找连接最多的来源
ss -tan | awk 'NR>1 {print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20

# 只看某状态的具体连接
ss -tan state syn-recv
ss -tan state close-wait
ss -tan state time-wait | wc -l

# 统计连接某端口(如 80)的来源分布
ss -tan state established '( sport = :80 )' | awk 'NR>1 {print $4}' | cut -d: -f1 | sort | uniq -c | sort -rn | head

这几个命令能快速回答"是不是某个 IP 在刷我"。正常情况下,单个来源 IP 的连接数一般在几十到几百量级(经验值,看业务)。如果某个 IP 突然占了全局连接的一大半,比如总数一万而它一个人占八千,那基本可以判定异常。

对于使用连接跟踪(conntrack)的系统,还能看到更底层的跟踪表情况,NAT 网关和防火墙服务器尤其重要:

# 查看 conntrack 表条目数(需要安装 conntrack-tools)
# RHEL/CentOS/Rocky:
yum install conntrack-tools
# Debian/Ubuntu:
apt install conntrack-tools

conntrack -C                       # 当前跟踪表条目总数
conntrack -L | wc -l               # 列出所有条目
sysctl net.netfilter.nf_conntrack_max   # 跟踪表上限
sysctl net.netfilter.nf_conntrack_count # 当前使用量

nf_conntrack_count 逼近 nf_conntrack_max 时,新连接会被丢弃并打印 nf_conntrack: table full, dropping packet,表现就是"服务正常但偶发连不上"。这是 NAT 网关类服务器的高发故障。

四、异常流量的特征与判断阈值

把上面的统计结果对照下表,能快速缩小怀疑范围:

异常现象 连接状态特征 常见成因 印证命令
端口扫描 大量 SYN-RECV,来源 IP 单一或成段 攻击者探活、扫服务 ss -tan state syn-recv
SYN Flood SYN-RECV 激增且分散,CPU 软中断升高 半连接队列被占满 netstat -s \| grep -i syn
连接泄漏 CLOSE-WAIT 持续堆积不下降 应用未正确 close ss -tanp state close-wait
短连接风暴 ESTABLISHED 不高但 TIME-WAIT 极高,新建速率高 客户端未复用连接 ss -s 看 timewait
连接跟踪打满 新建连接失败,日志报 table full conntrack 上限太低 sysctl nf_conntrack_count
慢速攻击 大量 ESTABLISHED 但数据少、存活久 Slowloris 类攻击 ss -tin 看 Send-Q

判断"多少算异常"没有放之四海皆准的阈值,得先建立自己业务的基线:在业务正常时段跑几次统计,记下连接总数、各状态占比、单个 IP 连接上限,之后偏离基线就是信号。几条经验值可以参考:SYN-RECV 常态应接近 0,超过几百条且持续增长就值得查;单个来源 IP 的连接数超过全局的百分之几(比如大于 5%)要看;TIME-WAIT 占 TCP 连接总数的一半以上属于偏高,但短连接业务可能本来就高。

五、用 tcpdump 抓包印证

统计是"看现象",抓包是"看证据"。当统计指向某个 IP 或某个状态异常时,用 tcpdump 抓一小段流量确认。

# RHEL 系安装
yum install tcpdump
# Debian/Ubuntu 安装
apt install tcpdump

# 抓某来源 IP 的 SYN 包,确认是不是在扫端口
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0 and src host 203.0.113.7'

# 抓发往本机 80 端口的新建连接
tcpdump -i any -nn 'tcp port 80 and tcp[tcpflags] & tcp-syn != 0'

# 抓包写文件供 Wireshark 分析,限制数量避免占满磁盘
tcpdump -i eth0 -nn -c 1000 -w /tmp/cap.pcap 'tcp port 80'

# 看某 IP 的包速率(每秒大致多少包)
tcpdump -i eth0 -nn -c 100 'src host 203.0.113.7' | wc -l

抓包时务必加过滤条件(host、port、flags),并对 -w 写文件加 -c 数量限制。无过滤地全量抓包在高流量下会迅速产生几百兆甚至上 G 的文件,把磁盘写满,反而制造新故障。文件名建议写到 /tmp,分析完及时删除。

六、持续监控与告警

临时排查之外,连接数更应纳入日常监控。可以写个简单脚本定时采集并落盘,或用现有监控系统(如主流开源监控平台)采集 ss 的输出。

# 一个最简的每分钟采样脚本,追加到日志
# /etc/cron.d/conn_stat
* * * * * root /bin/bash -c 'echo "$(date +\%F\ \%T) total=$(ss -tan|wc -l) estab=$(ss -tan state established|wc -l) tw=$(ss -tan state time-wait|wc -l) syn=$(ss -tan state syn-recv|wc -l)" >> /var/log/conn_stat.log'

# 对新连接速率做粗略估算(每秒 SYN 数)
ss -s | grep -o 'estab [0-9]*'
nstat -az | grep -iE 'TcpActiveOpens|TcpPassiveOpens'

告警规则建议这样设(数值为参考,需按业务基线调整):连接总数连续几分钟超过基线的 2 倍、SYN-RECV 持续大于 500、单个来源 IP 连接数超过 5000、conntrack 使用率超过 80%,任意一条命中就告警。

常见问题

Q:连接数到底多少算多?有没有一个标准上限?

没有统一上限。单机 TCP 连接数的瓶颈通常在内存(每个 socket 占几 KB 内核内存)和文件描述符数(ulimit -n)。几万连接对现代服务器很轻松,几十万需要调优内核参数和 fd 上限。关键不是绝对数,而是相对你自己的业务基线有没有突变。

Q:ss -s 显示的 closed 是什么意思?

"closed" 通常指那些已经关闭但还没被回收的连接,很多是处于 TIME-WAIT 或已断开的连接计数。它偏大不一定是故障,要结合 timewait 数量和是否是短连接业务判断。

Q:为什么 ss -tanp 没显示进程名?

显示进程信息需要 root 权限(或相应 capability)。普通用户运行 -p 只能看到自己进程的连接,看不到别人的。排查时用 sudo ss -tanp。

Q:TIME-WAIT 很多需要处理吗?

要看业务。短连接高并发导致 TIME-WAIT 多是正常现象,只要本地端口没被耗尽就不必动。可以开启 net.ipv4.tcp_tw_reuse=1 缓解,但绝不要用已从新内核移除、且跨 NAT 有坑的 tcp_tw_recycle。

Q:发现某个 IP 疯狂连接,直接封 IP 可以吗?

可以临时封,但先确认不是自己的 NAT 出口或健康检查节点,误封会造成业务中断。用 iptables 或 firewalld 临时封禁时,务必记录规则以便回滚,并优先考虑限速(如 hashlimit)而不是一刀切封禁,避免影响正常用户。

总结

  • 查实时连接数不要只看总数,要分维度看:状态分布、来源 IP 分布、本地端口分布、新建速率,四者结合才能准确定位。
  • 首选 ss(ss -s、ss -tan、ss -lntp),netstat 仅作兼容保留;上万连接时 netstat 会明显卡顿。
  • 按状态和按来源 IP 聚合是发现异常最有效的手段:SYN-RECV 指向扫描和 SYN Flood,CLOSE-WAIT 指向应用连接泄漏,TIME-WAIT 偏多通常是短连接造成。
  • 判断异常阈值要靠业务基线,不要套用固定数字;统计发现嫌疑后用 tcpdump 加过滤条件抓包印证,抓包务必限流限量。
  • 连接数与 conntrack 使用率应纳入日常监控并对突变告警;涉及封 IP、改内核参数前先记录原状、准备回滚,优先限速而非直接封禁。