上一篇 下一篇 分享链接 返回 返回顶部

香港服务器上的CentOS系统如何通过内核sysctl参数强化TCP安全,抵御大规模DDoS攻击?

发布人:Minchunlin 发布时间:2025-08-22 10:44 阅读量:714


我要先说一句大实话:靠 sysctl 并不能“无脑硬扛”一切 DDoS,但在“上游清洗/黑洞未就位、硬件设备来不及调”的那几分钟里,内核参数就是把服务从“立即崩盘”拉回“能喘上气”的最短杠杆。下面这篇,是我在香港机房值夜班时,真刀真枪调过的那份 SOP 和复盘。

香港葵涌机房的2:13 分,PagerDuty 把我从椅子上“弹”起来:

  • SYN flood 突增,接入层 Nginx 连接建立率骤降,p99 超 8s,业务 502 断续出现。

CDN 走的是业务分流(并非全站强制回源保护),攻击点是直连 IP 的 L4 SYN 洪泛,峰值约 1.1–1.4 Mpps / 8–12 Gbps,源地址明显被伪造,ASN 分布集中在亚洲几家廉价云段。清洗线路要和运营商确认,BGP Flowspec 需要上游批准;这些都得花时间。第一响应只有一条路:先稳住 Linux 内核的队列与 TCP 行为。

1)现场环境与基线(我们到底在什么“车”上开)

项目 配置/版本
机房/链路 香港 HGC + PCCW 双上联,10G 接入,默认开本地 ACL
服务器 Dell R740(2 × Intel Xeon Silver 4210R,128GB RAM)
网卡 Intel X710-10G(ixgbe 驱动)单口上行
OS CentOS 7.9,内核 3.10.0-1160.el7.x86_64
角色 L4/L7 接入(Nginx + Envoy),后端 gRPC
内核调优基线 tuned-profiles throughput-performance,其余接近默认
业务特点 短连接占比高,峰值新建连接 180k cps,报文小,RTT 亚太混合

问题征象(攻击初期 2–3 分钟内):

  • netstat -s 中 listen queue overflows 快速增长
  • ss -s 显示大量 SYN-RECV 与 orphaned 连接
  • dmesg 有 TCP: Possible SYN flooding on port 443 日志
  • 应用日志 accept() 超时,Nginx recv() failed (104: Connection reset by peer) 间歇出现

2)调优思路(顺序重要)

优先级:

网卡/驱动与收包队列 → 内核收包 backlog → TCP 三次握手与半连接 → Listen 队列与应用 backlog → 连接生命周期与内存水位 → 异常/片段/ICMP 行为 → 观察与回滚。

目标:

  • 在 CPU 可承受范围内 更快丢弃垃圾、更少阻塞正当连接
  • 让关键队列有“弹性”,但不被无限放大拖垮内存
  • 把“危险的默认值”改成攻击期更稳妥的行为

3)核心 sysctl 参数与推荐值(CentOS 7 / 3.10 内核实测)

注:下面“默认值”指 CentOS 7 典型默认/接近默认;不同环境会略有差异。不要照抄到生产就跑,请先在压测或灰度机验证。加粗的为在本场景最关键的几项。

A. 队列与握手抗性

参数 默认 建议(攻击期) 说明
net.core.somaxconn 128 32768 上调监听上限,配合应用 backlog(如 Nginx backlog=
net.ipv4.tcp_max_syn_backlog 256/1024 16384–65535 半连接队列增大,配合 syncookies
net.ipv4.tcp_syncookies 1(有时 0) 1 必须启用,内核在半连接溢出时使用
net.ipv4.tcp_synack_retries 5 3 降低重试,减少 SYN-ACK 压力
net.ipv4.tcp_syn_retries 6 3–4 降低主动发起方重试;服务端影响较小
net.core.netdev_max_backlog 1000 50000–100000 NIC → 内核队列的积压上限,防突发丢包

B. 连接生命周期与内存

参数 默认 建议(攻击期) 说明
net.ipv4.tcp_fin_timeout 60 20–30 缩短 FIN-WAIT-2 停留时间
net.ipv4.tcp_max_orphans 16384 65536–262144 孤儿连接上限,避免内核过早杀连接
net.ipv4.tcp_orphan_retries 7 3–4 孤儿重试次数
net.ipv4.ip_local_port_range 32768 61000 20000 65000 视 SNAT/主动连接需要扩大
net.core.rmem_max / wmem_max 212992 16M / 16M 上调最大缓冲(结合 tcp_rmem/wmem
net.ipv4.tcp_rmem 4096 87380 6291456 4096 131072 16777216 自适应接收窗口
net.ipv4.tcp_wmem 4096 16384 4194304 4096 65536 16777216 自适应发送窗口

C. 协议安全与异常行为

参数 默认 建议(攻击期) 说明
net.ipv4.tcp_rfc1337 0 1 修复 TIME-WAIT 相关 RST 攻击
net.ipv4.tcp_timestamps 1 1(保留) 关闭会失去 RTT 估计;一般保持 1
net.ipv4.tcp_challenge_ack_limit 100 1000–5000 抗 blind spoofing,提升 ACK 限额
net.ipv4.icmp_echo_ignore_broadcasts 0/1 1 忽略广播 ICMP
net.ipv4.icmp_ignore_bogus_error_responses 0 1 忽略异常 ICMP 错误
net.ipv4.conf.all.accept_redirects 1 0 拒绝 ICMP 重定向
net.ipv4.conf.all.send_redirects 1 0 不发送重定向
net.ipv4.conf.all.accept_source_route 0/1 0 禁止源路由
net.ipv4.conf.all.rp_filter 0 2(loose) 多上联/清洗回注时避免 strict=1 导致丢包
net.ipv4.conf.all.log_martians 0 1 记录异常源地址
net.ipv4.ipfrag_high_thresh / low_thresh 4MB/3MB 256MB / 192MB 提升碎片缓冲水位,抗 fragment 洪泛(视内存)

⚠️ 不要启用:net.ipv4.tcp_tw_recycle(新内核已移除,会在 NAT/多路径场景下误杀),net.ipv4.tcp_abort_on_overflow=1(把拥塞直接 RST 给用户,极端情况下才考虑短时开启)。

4)一次性落地的配置文件

在 CentOS 7 上,我把临时参数集中写到了一个文件里,便于切换和回滚:

/etc/sysctl.d/99-ddos-hardening.conf

# Queue & handshake
net.core.somaxconn = 32768
net.core.netdev_max_backlog = 100000
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_synack_retries = 3
net.ipv4.tcp_syn_retries = 4

# Lifecycle & memory
net.ipv4.tcp_fin_timeout = 25
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_orphan_retries = 3
net.ipv4.ip_local_port_range = 20000 65000
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 131072 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

# Protocol safety
net.ipv4.tcp_rfc1337 = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_challenge_ack_limit = 5000

# ICMP & routing
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
# Loose rp_filter,适配清洗回注/不对称路由
net.ipv4.conf.all.rp_filter = 2
net.ipv4.conf.default.rp_filter = 2
net.ipv4.conf.eth0.rp_filter = 2
net.ipv4.conf.all.log_martians = 1

# IP fragments
net.ipv4.ipfrag_low_thresh = 201326592   # 192MB
net.ipv4.ipfrag_high_thresh = 268435456  # 256MB

应用与验证:

# 备份现有
sudo cp /etc/sysctl.conf /etc/sysctl.conf.bak.$(date +%F_%H%M)

# 加载新增文件
sudo sysctl --system

# spot check
sysctl net.core.somaxconn
sysctl net.ipv4.tcp_max_syn_backlog
sysctl net.ipv4.tcp_syncookies

5)NIC / 中断层的两把“螺丝刀”(非 sysctl,但决定能不能吃下包)

(1)增大 ring buffer & 开多队列收包:

# 查看 ring
ethtool -g eth0
# 典型把 RX/TX 都调到网卡上限(如 4096/4096)
ethtool -G eth0 rx 4096 tx 4096

# 开启多队列 RSS(X710 默认支持),核对 ethtool -l
ethtool -l eth0

(2)中断亲和 / RPS:

# 查看中断分布
cat /proc/interrupts | egrep 'eth0|ixgbe'

# 把网卡队列中断 pin 到不同 CPU(示例:队列0→CPU0,队列1→CPU1...)
echo 1  > /proc/irq/$(grep eth0-TxRx-0 -n /proc/interrupts | awk '{print $1}' | tr -d :) /smp_affinity
echo 2  > /proc/irq/$(grep eth0-TxRx-1 -n /proc/interrupts | awk '{print $1}' | tr -d :) /smp_affinity
# ...按位掩码设置

若 gro/gso/tso 导致 CPU 抖动,可短期关闭 gro 试验丢包改善(权衡吞吐):

ethtool -K eth0 gro off

6)应用层与内核配合(以 Nginx 为例)

# /etc/nginx/nginx.conf
events {
    worker_connections  65535;   # 与 net.core.somaxconn 对齐
    multi_accept        on;
    use                 epoll;
    accept_mutex        off;     # 攻击期更快 accept
}
http {
    server {
        listen 443 backlog=32768 ssl reuseport; # reuseport 拆分 accept 锁
        # 其它 SSL/路由配置...
    }
}

reuseport 在多 worker 下能把 accept 队列拆散,减少锁竞争;但需要与 somaxconn、backlog、worker_processes 一起看。

7)观测:怎么知道“救回来没”

即时观察:

watch -n1 'ss -s'
netstat -s | egrep -i "listen|SYN|cookies|backlog"
watch -n1 'tail -n +1 /proc/net/netstat /proc/net/snmp | egrep "(ListenOverflows|ListenDrops|Syncookies|OutOfWindowIcmps|InCsumErrors)"'
dmesg --follow | egrep -i "SYN flooding|martian"

期望变化(5–10 分钟内):

  • TCP: Possible SYN flooding 仍可能出现,但ListenOverflows 不再线性飙升
  • SyncookiesSent 上升,但 Established 比例恢复
  • 应用的 502/超时明显下降,p99 从 >8s 回落到 <1.5s(我那次 12 分钟后基本稳定)

8)结果对比(本次处置的关键指标)

指标 调整前(峰值) 调整后(稳定 10 分钟)
入向包速(pps) 1.3 Mpps 1.3 Mpps(攻击未停)
ListenOverflows 每秒 +4k 每秒 <50
SyncookiesSent 少量 持续 5–8k/s
新建连接成功率 40–55% >95%
Nginx 502 比例 18% <0.5%
p99 延迟 8–12s 0.9–1.4s
CPU(总/软中断) 70% / 35% 65% / 28%

没有“降流”,但让正当流量能排上队、握上手。随后上游 Flowspec 生效、ACL 精准封段,整体才彻底回到常态。

9)部署中遇到的坑 & 现场解法

rp_filter=1(strict)把清洗回注的流量当作伪造给干掉了

现象:上游清洗开启后,丢包反而加重。

解决:切到 rp_filter=2(loose),并针对回注接口明确设置。这个在多上联/不对称路由时非常关键。

只拉大 somaxconn 忘了应用 backlog

现象:内核 OK,但 Nginx 仍报 accept queue full。

解决:应用层 listen backlog 同步拉大,并启用 reuseport。

盲目关 tcp_timestamps 导致 RTT 估计失真 & 重传暴涨

现象:延迟指标古怪、吞吐下降。

解决:在我们的场景保留 tcp_timestamps=1,把重心放在 syncookies、syn_backlog。

被“优化建议”误导去开 tcp_tw_recycle

结论:坚决不要。在 NAT 背后会出现诡异连接复用导致的间歇失败;而且新内核已经移除了该选项。

tcp_abort_on_overflow=1 的副作用

它会在队列满时直接给客户端 RST——看似“清爽”,但用户体验极差,除非压测验证、并仅在极端短时使用。

IP 碎片洪泛撑爆 ipfrag

拉高 ipfrag_high/low_thresh 后配合上游过滤,效果明显;但要监控内存水位,避免 OOM。

10)回滚与分层预案

秒级回滚:

sysctl -w key=oldvalue 逐项恢复;或 mv 99-ddos-hardening.conf{,.bak}; sysctl --system

分层预案:

上游:BGP Flowspec/RTBH、接入 ACL

服务器:sysctl + NIC 队列 + 应用 backlog

应用:灰度降级、只读模式、动态开关某些重流控逻辑

11)可直接复用的最小化“急救清单”(攻防拉锯的前 10 分钟)

# 1. 开启 cookies + 拉大半连接/监听
sysctl -w net.ipv4.tcp_syncookies=1
sysctl -w net.ipv4.tcp_max_syn_backlog=65535
sysctl -w net.core.somaxconn=32768
sysctl -w net.core.netdev_max_backlog=100000

# 2. 降低握手重试,避免积压
sysctl -w net.ipv4.tcp_synack_retries=3
sysctl -w net.ipv4.tcp_syn_retries=4

# 3. 连接生命周期与孤儿控制
sysctl -w net.ipv4.tcp_fin_timeout=25
sysctl -w net.ipv4.tcp_max_orphans=262144
sysctl -w net.ipv4.tcp_orphan_retries=3

# 4. 安全项(不破路由)
sysctl -w net.ipv4.tcp_rfc1337=1
sysctl -w net.ipv4.tcp_challenge_ack_limit=5000
sysctl -w net.ipv4.conf.all.rp_filter=2
sysctl -w net.ipv4.conf.default.rp_filter=2

# 5. 观察关键计数器
watch -n1 'netstat -s | egrep -i "listen|SYN|cookie|backlog"'

同时联系上游开清洗/ACL/黑洞;sysctl 是争取时间,不是终局武器。

12)结尾:把“夜里救火”写进白天的 Runbook

那天凌晨 2:41,我们把队列稳住,上游也把几段 ASN 封了。机房走廊的安全门“咔哒”一声,保安巡检路过,冲我点了点头。

我把这套参数做成 Ansible role,写进了 “香港接入层 DDoS 紧急处置 Runbook”,并加了三个醒目的注释:

优先保证路由正确(rp_filter=2),否则清洗回注也是白搭

syncookies 必开,backlog“三件套”对齐(syn_backlog / somaxconn / 应用 backlog)

所有改动都要可回滚,并且配套观测项

后来再遇到类似的突发,我们从“手忙脚乱”变成了“有条不紊”。sysctl 不会替你打赢所有仗,但它足够快、足够可靠,能把你和你的用户一起,从溺水边缘拖回到能继续游的地方。

附:参数速查表(打印贴在机柜门内侧)

分类 关键参数(建议值)
队列 somaxconn=32768netdev_max_backlog=100000tcp_max_syn_backlog=65535
握手 tcp_syncookies=1tcp_synack_retries=3tcp_syn_retries=4
生命周期 tcp_fin_timeout=25tcp_max_orphans=262144tcp_orphan_retries=3
内存 rmem_max/wmem_max=16Mtcp_rmem=4k 128k 16Mtcp_wmem=4k 64k 16M
安全 tcp_rfc1337=1tcp_challenge_ack_limit=1000–5000rp_filter=2
其它 ipfrag_high/low_thresh=256M/192Micmp_*redirects 全部收紧
目录结构
全文