TCP 连接数暴涨排查:确认是否遭到异常流量(完整手册)
来源:微信公众号「马哥Linux运维」《一台机器 TCP 连接数暴涨,怎样确认是不是遭到了异常流量》
定位:生产环境连接数从几千暴涨到几万甚至十几万时——是正常流量增长还是攻击?什么类型攻击?来源在哪、封哪些 IP?系统撑得住吗?按本页六步流程走,每个步骤都带命令、输出示例和判断阈值。
问题背景与误判后果
TCP 连接数暴涨两大来源:
正常场景: 营销活动用户激增、业务高峰期(秒杀/抢票)、上游故障重试风暴、新功能上线流量模式变化。
异常场景: SYN Flood(大量 SYN 包,连接停 SYN_RECV)、CC 攻击(大量 HTTP 请求,连接停 ESTABLISHED)、慢速连接攻击(大量连接不释放)、爬虫/恶意扫描(大量短连接快速建立断开)。
判断错误的代价: 误封正常用户 IP 影响业务;未及时封禁攻击源服务崩溃;盲目扩容浪费资源成本。
适用:收到连接数告警需快速判断、怀疑 DDoS(SYN Flood/CC)、需定位攻击来源与封禁 IP、需优化 TCP 参数抗攻击。方法适用于 Linux(CentOS/Ubuntu/Debian),部分命令需 root。
核心知识点
TCP 连接状态机
三次握手: 客户端 SYN → 服务端 SYN_RECV → 服务端 SYN-ACK → 客户端 ESTABLISHED → 客户端 ACK → 服务端 ESTABLISHED。
四次挥手: 客户端 FIN → 服务端 CLOSE_WAIT → 服务端 ACK → 服务端 FIN → 客户端 TIME_WAIT → 客户端 ACK → 关闭。
常见状态: LISTEN(监听等待)、SYN_SENT(客户端等 SYN-ACK)、SYN_RECV(服务端收 SYN 等 ACK)、ESTABLISHED(已建立正常通信)、FIN_WAIT1/FIN_WAIT2(主动关闭方等待)、CLOSE_WAIT(被动关闭方等应用层关闭)、TIME_WAIT(主动关闭方等 2MSL)。
异常流量的连接状态特征
| 攻击类型 | 特征 | 原理 | 危害 |
|---|---|---|---|
| SYN Flood | 大量 SYN_RECV | 发 SYN 不回复 ACK,耗尽半连接队列 | 正常用户无法建立连接 |
| CC 攻击 | 大量 ESTABLISHED | 建立大量 HTTP 连接并发请求 | CPU/内存/带宽占满,服务变慢或崩溃 |
| 慢速连接(Slow HTTP) | 大量 ESTABLISHED 但流量很小 | 建立连接后缓慢发数据长期占用 | 连接池占满,正常用户无法访问 |
| 连接泄漏 | 大量 CLOSE_WAIT 或 TIME_WAIT | 应用未正确关闭连接 / 主动关闭方过多 | 连接资源耗尽 |
半连接队列与全连接队列
- 半连接队列(SYN Queue):存 SYN_RECV 连接,大小由 net.ipv4.tcp_max_syn_backlog 控制;满时新 SYN 被丢弃
- 全连接队列(Accept Queue):存已完成握手等待应用 accept 的连接,由 listen(sockfd, backlog) 与 net.core.somaxconn 共同决定;满时按 net.ipv4.tcp_abort_on_overflow 配置丢弃或发 RST
netstat -s | grep "SYNs to LISTEN" # 半连接队列溢出次数
netstat -s | grep "overflowed" # 全连接队列溢出次数
conntrack 连接跟踪
iptables/nftables 用 conntrack 跟踪所有连接状态:每个连接占一个表项,数量由 net.netfilter.nf_conntrack_max 限制;表满时新连接被拒绝,日志显示 nf_conntrack: table full。
conntrack -C # 当前 conntrack 条目数
sysctl net.netfilter.nf_conntrack_max # 最大条目数
conntrack -L | head -20 # 查看 conntrack 表
常见攻击工具识别
- hping3:构造任意 TCP/UDP/ICMP 包,常用 SYN Flood;特征 = 源 IP 可能伪造、源端口随机
- slowhttptest:模拟慢速 HTTP;特征 = 请求头缓慢发送、User-Agent 可识别
- ab/wrk/vegeta:HTTP 压测工具被用于攻击;特征 = User-Agent 含工具名
- 僵尸网络:分布式攻击;特征 = 大量不同 IP、请求模式相似
快速判断流程(六步)
第一步:连接总数与状态分布
ss -tan | awk '{print $1}' | sort | uniq -c | sort -rn
# 或用 netstat(较慢)
netstat -tan | awk '{print $6}' | sort | uniq -c | sort -rn
正常输出: 3500 ESTABLISHED / 500 TIME_WAIT / 50 LISTEN / 10 SYN_SENT SYN Flood 异常: 50000 SYN_RECV / 3000 ESTABLISHED / 500 TIME_WAIT CC 攻击异常: 80000 ESTABLISHED / 5000 TIME_WAIT / 50 LISTEN
判断阈值: SYN_RECV > 10000 可能 SYN Flood;ESTABLISHED > 正常基线 2 倍可能 CC 或正常增长;CLOSE_WAIT > 5000 应用未正确关闭连接;TIME_WAIT > 30000 主动关闭过多需优化。
第二步:连接增长速度
watch -n 1 'ss -tan | wc -l'
# 或记录变化
for i in {1..10}; do
echo "$(date +%T): $(ss -tan | wc -l) connections"
sleep 1
done
判断阈值: 增速 > 1000 连接/秒 可能攻击;< 100 连接/秒 可能正常波动。
第三步:源 IP 分布
ss -tan | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20
判断阈值: 单个 IP 连接数 > 1000 可能单点攻击;TOP 10 IP 占比 > 80% 可能分布式攻击;TOP 10 占比 < 20% 可能正常流量或大规模僵尸网络。
第四步:目标端口分布
ss -tan | awk '{print $4}' | cut -d: -f2 | sort | uniq -c | sort -rn | head -10
大量非业务端口(80/443/22/8080/3306 分散)→ 端口扫描;业务端口集中 → 针对性攻击。
第五步:半连接/全连接队列溢出
netstat -s | grep -E "SYNs to LISTEN|overflowed|dropped"
判断阈值: SYNs dropped > 10000/分钟 为 SYN Flood;listen queue overflowed > 5000/分钟 为全连接队列满(应用处理慢或 CC 攻击)。
第六步:conntrack 表使用率
current=$(conntrack -C)
max=$(sysctl -n net.netfilter.nf_conntrack_max)
usage=$(echo "scale=2; $current * 100 / $max" | bc)
echo "Conntrack使用率: $current/$max ($usage%)"
dmesg | grep "nf_conntrack: table full"
判断阈值: 使用率 > 90% 可能连接过多或攻击;出现 table full 连接跟踪表已满、新连接被拒。
深入分析:区分正常流量与攻击
生命周期分析
ss -tan | awk '{print $5,$1}' | awk -F: '{print $1,$NF}' | sort | uniq -c | sort -rn | head -20
正常:大部分 ESTABLISHED + 少量 TIME_WAIT + SYN_RECV 很少(<1%)。SYN Flood:大量 SYN_RECV,来自同一或大量随机 IP,ESTABLISHED 很少。CC:大量 ESTABLISHED,来自特定 IP 段或大量 IP,连接持续时间短(快速建立断开)。
请求模式分析(Nginx 日志)
tail -1000 /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -20 # 源 IP
tail -1000 /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -20 # URL 分布
tail -1000 /var/log/nginx/access.log | awk -F'"' '{print $6}' | sort | uniq -c | sort -rn | head -20 # User-Agent
正常:UA 多样化(浏览器/移动端/爬虫)、URL 符合业务逻辑、请求间隔随机。CC:UA 单一或伪造、URL 集中某几个接口(通常复杂查询或写操作)、请求间隔规律(每秒固定次数)。恶意爬虫:UA 含爬虫关键词或为空、大量 404(扫隐藏页面)、速度极快无视 robots.txt。
流量大小分析
iftop -i eth0 # 实时流量
vnstat -l -i eth0 # 流量统计
iftop -P -i eth0 # 按 IP 看流量
SYN Flood:连接多但流量很小(只有 SYN 包)、几乎只有入站。CC:连接多流量也大(大量 HTTP 请求响应)。慢速攻击:连接多流量小、持续时间长。
源 IP 地理位置与 ASN
whois 203.0.113.50 | grep -E "OrgName|Country"
geoiplookup 203.0.113.50
# 批量查询 TOP 10 IP
ss -tan | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -10 | awk '{print $2}' | while read ip; do
echo -n "$ip: "
geoiplookup $ip | awk -F: '{print $2}'
done
正常:国家符合业务覆盖、ASN 属正规 ISP/云厂商。异常:来源集中在某小国家/地区、ASN 属数据中心或代理、IP 在黑名单(可查 AbuseIPDB)。
TCP 标志位分布(tcpdump)
tcpdump -i eth0 -nn -c 1000 'tcp[tcpflags] & tcp-syn != 0' | wc -l # SYN 包数量
tcpdump -i eth0 -nn -c 1000 'tcp[tcpflags] & tcp-ack != 0' | wc -l # ACK 包数量
ss -s # 统计概览
正常:SYN ≈ ACK(正常握手)、RST 很少。SYN Flood:SYN >> ACK、大量未完成握手。连接重置攻击:大量 RST、连接频繁断开。
应对措施(按优先级)
紧急封禁攻击 IP
单 IP: iptables -I INPUT -s 203.0.113.50 -j DROP;IP 段 iptables -I INPUT -s 203.0.113.0/24 -j DROP;查规则 iptables -L INPUT -n --line-numbers;删除 iptables -D INPUT 1。
批量封禁 TOP 攻击 IP(连接数 > 1000):
ss -tan | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | awk '$1 > 1000 {print $2}' | while read ip; do
if ! iptables -C INPUT -s $ip -j DROP 2>/dev/null; then
echo "封禁 $ip"
iptables -I INPUT -s $ip -j DROP
fi
done
ipset 批量(性能更好):
ipset create blacklist hash:ip
ss -tan | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | awk '$1 > 1000 {print $2}' | while read ip; do
ipset add blacklist $ip
done
iptables -I INPUT -m set --match-set blacklist src -j DROP
ipset list blacklist
ipset flush blacklist
限流与连接限制
每 IP 每秒最多 20 个新连接(recent):
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --set
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --update --seconds 1 --hitcount 20 -j DROP
每 IP 最多 100 并发(connlimit): iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 100 --connlimit-mask 32 -j REJECT
Nginx 限流:
http {
# 每 IP 每秒 10 个请求
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
# 每 IP 并发连接数
limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
location / {
limit_req zone=one burst=20 nodelay;
limit_conn addr 10;
}
}
}
内核 TCP 参数(SYN Flood 防御 + 队列 + 回收):
sysctl -w net.ipv4.tcp_syncookies=1
sysctl -w net.ipv4.tcp_max_syn_backlog=8192
sysctl -w net.ipv4.tcp_synack_retries=2
sysctl -w net.ipv4.tcp_syn_retries=2
sysctl -w net.ipv4.tcp_tw_reuse=1
sysctl -w net.netfilter.nf_conntrack_max=1000000
cat >> /etc/sysctl.conf << EOF
net.ipv4.tcp_syncookies=1
net.ipv4.tcp_max_syn_backlog=8192
net.ipv4.tcp_synack_retries=2
net.ipv4.tcp_syn_retries=2
net.ipv4.tcp_tw_reuse=1
net.netfilter.nf_conntrack_max=1000000
EOF
sysctl -p
应用层防护
- 验证码 / JS Challenge:对可疑 IP 返回挑战,区分真实用户与自动化工具
- CDN 与 DDoS 防护:Cloudflare、Akamai、AWS Shield、阿里云 DDoS 防护
- WAF:ModSecurity、Nginx WAF 模块、云厂商 WAF
监控告警(Prometheus)
groups:
- name: tcp_alerts
rules:
- alert: TCPConnectionSpike
expr: node_netstat_Tcp_CurrEstab > 10000
for: 1m
labels:
severity: warning
annotations:
summary: "TCP连接数异常"
- alert: SYNFloodSuspected
expr: rate(node_netstat_Tcp_PassiveOpens[1m]) > 1000
for: 2m
labels:
severity: critical
annotations:
summary: "疑似SYN Flood攻击(被动打开速率/s)"
- alert: ConntrackTableFull
expr: node_nf_conntrack_entries / node_nf_conntrack_entries_limit > 0.9
for: 5m
labels:
severity: warning
annotations:
summary: "Conntrack表使用率超过90%"
实战案例
案例 1:单点 SYN Flood
现象: 告警连接数从 3000 暴涨到 50000。排查: 状态分布 48000 SYN_RECV;源 IP 分布 45000 来自 203.0.113.50;半连接队列溢出 500000 SYNs to LISTEN sockets dropped。判断: 单 IP SYN Flood。
处理与结果: 封禁 iptables -I INPUT -s 203.0.113.50 -j DROP + 启用 tcp_syncookies=1 + tcp_max_syn_backlog=16384 + watch -n 1 'ss -tan | wc -l' 验证——连接数 1 分钟内降到正常水平 3000。
案例 2:分布式 CC 攻击
现象: 服务响应慢,CPU 90%,连接数 80000。排查: 75000 ESTABLISHED;每 IP 约 300-500 连接,TOP 200 IP 占 90%;Nginx 日志每 IP 请求数相近、URL 集中在 /api/search;UA 全是 Mozilla/5.0 (compatible)。判断: 分布式 CC 攻击,目标接口 /api/search。
处理与结果: 批量封禁 TOP IP(连接 > 200 的入 ipset)+ Nginx location /api/search { limit_req zone=search_zone burst=5 nodelay; } + nginx -t && nginx -s reload + Cloudflare——连接数降到 10000,CPU 降到 30%,服务恢复。
案例 3:连接泄漏 CLOSE_WAIT 堆积
现象: 连接数持续增长,重启应用恢复,几小时后又增长。排查: 30000 CLOSE_WAIT;ss -tanp state close-wait 显示 28000 来自 users:(("java",pid=12345))。判断: 应用未正确关闭连接。
根因: Java HttpClient 发送请求后未调用 response.close()/client.close(),连接未释放。修复(try-with-resources):
// 错误写法
HttpResponse response = client.execute(request);
String body = EntityUtils.toString(response.getEntity());
// 正确写法
try (CloseableHttpResponse response = client.execute(request)) {
String body = EntityUtils.toString(response.getEntity());
}
临时措施 systemctl restart app.service;长期修复代码确保 finally/资源块中关闭连接。
预防措施
- 基线监控: 用 avg_over_time(node_netstat_Tcp_CurrEstab[7d]) 记录 tcp:connections:baseline;告警规则 node_netstat_Tcp_CurrEstab > baseline * 2,for 5m
- 定期压测:wrk -t 10 -c 1000 -d 60s http://example.com/;测试环境用 hping3 -S -p 80 --flood example.com 验证 SYN Flood 防护
- 自动化响应:Alertmanager webhook 到本地 /block 服务(Flask + subprocess 执行 ipset add blacklist
),自动封禁攻击 IP - 云 DDoS 防护:大规模攻击单机难挡——Cloudflare(免费基础防护)、AWS Shield、阿里云/腾讯云 DDoS 防护
- 网络架构:Web 服务放 CDN/负载均衡后、Anycast 分散攻击、隔离关键服务与公网、管理端口白名单
深入分析工具:tcpdump 抓包
# 抓 1000 个 SYN 包(排除 ACK)
tcpdump -i eth0 -nn -c 1000 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0' -w syn.pcap
# 统计源 IP 分布
tcpdump -r syn.pcap -nn | awk '{print $3}' | cut -d. -f1-4 | sort | uniq -c | sort -rn
# 检查源端口是否随机(SYN Flood 常见特征)
tcpdump -r syn.pcap -nn | awk '{print $3}' | cut -d. -f5 | cut -d: -f1 | sort | uniq | wc -l
# 抓 HTTP GET 请求
tcpdump -i eth0 -nn -A -s 0 'tcp port 80 and (tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420)'
检查清单
排查清单: 连接状态分布 → 连接增长速度 → 源 IP 分布 → 目标端口 → 队列溢出 → conntrack 使用率 → 进程关联 → 分析 HTTP 日志(Web 攻击)→ 系统资源(CPU/内存/带宽)。
应对清单: 封禁 TOP 攻击 IP(iptables/ipset)→ 启用 SYN Cookies → 配置连接速率限制 → 并发连接数限制 → 调整内核 TCP 参数 → Nginx 层配置限流 → 启用 CDN/DDoS 防护 → 记录攻击日志留存证据。
预防清单: 建立连接数基线 → 配置监控告警 → 定期压测验证防护 → 自动化响应脚本 → 云 DDoS 防护 → 优化网络架构 → 定期 Review 防护策略 → 演练应急响应。
配置持久化: iptables 规则写 /etc/sysconfig/iptables;sysctl 写 /etc/sysctl.conf;Nginx 配置写配置文件;ipset 规则写启动脚本;配置开机自动加载防护规则。
总结
快速判断流程: 连接状态分布 → 识别攻击类型;连接增长速度 → 判断攻击强度;源 IP 分布 → 定位攻击源;目标端口 → 确定攻击目标;队列溢出 → 评估影响范围;conntrack → 判断系统资源。
攻击类型特征:
| 攻击类型 | 连接状态 | IP 特征 | 流量特征 |
|---|---|---|---|
| SYN Flood | 大量 SYN_RECV | 单个或随机 IP | 只有 SYN 包,流量小 |
| CC 攻击 | 大量 ESTABLISHED | 分布式,每 IP 连接数相近 | 大量 HTTP 请求 |
| 慢速攻击 | 大量 ESTABLISHED | 单个或少量 IP | 连接持续时间长,流量小 |
| 端口扫描 | 大量 SYN_SENT | 单个 IP | 大量不同端口 |
应对措施优先级: 紧急封禁(iptables/ipset)→ 限流防护(SYN Cookies + 连接限制)→ 调整参数(队列大小/内核参数)→ 应用防护(Nginx 限流/WAF)→ 架构优化(CDN/DDoS 防护)。
预防措施: 建立基线监控设合理阈值 → 定期压测了解承载能力 → 配置自动化响应快速封禁 → 使用云服务 DDoS 防护 → 优化网络架构隔离关键服务。
关联页面
| 页面 | 关联点 |
|---|---|
| tcp-connection-attack-vs-bug | TCP 连接数爆表:攻击还是 Bug 排查指南(快速鉴别的精简版) |
| network-packet-loss-troubleshooting | 网络丢包排查全链路:ping 到 tcpdump 逐层排查 |
| network-troubleshooting-order | 服务器网络排障方法论:分层定位七步法 |
| linux-kernel-tuning-production | Linux 内核调优(tcp_syncookies/tcp_max_syn_backlog/somaxconn 等) |
| server-suddenly-slow-troubleshooting-sop | 服务器突然变慢 SOP(连接数/负载/IO 快速诊断) |
| k8s-dns-conntrack-5s-timeout | conntrack 竞态导致 DNS 5s 解析超时(conntrack 原理侧) |
| anti-brute-force-script | iptables 自动封禁脚本(批量封禁的自动化参考) |
| server-security-hardening-checklist | 服务器安全加固清单(内核参数与 SSH 加固) |
| nginx-log-spike-crawler-troubleshooting | Nginx 访问日志暴涨排查手册:14 步定位异常 URI 与爬虫流量 |