主题
⚡ DDoS 防护
DDoS(Distributed Denial of Service)攻击的目标不是入侵服务器,而是用海量流量把它"淹死"——CPU 打满、带宽塞满、连接表耗尽,正常用户完全无法访问。
DDoS 类型一览
| 类型 | 原理 | 攻击目标 | 难度 |
|---|---|---|---|
| SYN Flood | 发送大量 TCP SYN 包但不完成握手,耗尽连接队列 | 服务器 TCP 栈 | ★★☆ |
| UDP Flood | 发送海量 UDP 包,占满带宽 | 网络带宽 | ★☆☆ |
| HTTP Flood(CC) | 大量合法的 HTTP 请求,消耗应用层资源 | Web 应用(CPU/内存) | ★★★ |
| Slowloris | 建立连接后极慢地发送请求头,占满连接池 | Web 服务器连接池 | ★★★ |
| DNS Amplification | 伪造源 IP 向 DNS 发送小请求,DNS 返回大响应打到目标 | 网络带宽 | ★★☆ |
| NTP Amplification | 类似 DNS 放大,利用 NTP monlist 漏洞 | 网络带宽 | ★☆☆ |
放大攻击
DNS Amplification 和 NTP Amplification 的"放大倍数"可达 50-200 倍——攻击者发送 1Mbps 请求,目标收到 200Mbps 垃圾数据。这种攻击依赖网络中开放的 DNS/NTP 服务器作为"反射器"。
Nginx 限流:防 CC 攻击
CC 攻击(Challenge Collapsar)是应用层 DDoS,用大量看似正常的 HTTP 请求消耗服务器资源。
请求频率限制(limit_req)
在 nginx.conf 的 http 块中定义:
nginx
http {
# 定义一个限流区域:binary_remote_addr 为键,每秒 10 个请求,突发 20
limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s;
# 针对特定路径更严格的限制
limit_req_zone $binary_remote_addr zone=login:10m rate=3r/m;
server {
# 对全站应用
limit_req zone=perip burst=20 nodelay;
# 登录接口更严格:每分钟 3 次,突发 5
location /login {
limit_req zone=login burst=5 nodelay;
}
}
}参数说明:
rate=10r/s:每秒 10 个请求burst=20:允许额外 20 个突发请求排队等待nodelay:突发请求不排队,立即处理(不设则排队等待)
并发连接限制(limit_conn)
nginx
http {
# 每个 IP 最多 10 个并发连接
limit_conn_zone $binary_remote_addr zone=perconn:10m;
# 按 server_name 限制总连接
limit_conn_zone $server_name zone=perserver:10m;
server {
limit_conn perconn 10;
limit_conn perserver 500;
}
}完整防 CC 配置模板
nginx
http {
# === 基础调优 ===
# 减少 keepalive 时间
keepalive_timeout 15;
keepalive_requests 100;
# 关闭慢客户端
client_body_timeout 10;
client_header_timeout 10;
send_timeout 10;
# body 大小限制
client_max_body_size 10m;
client_body_buffer_size 128k;
# === 限流区域 ===
# 全局:每秒 30 请求,突发 50
limit_req_zone $binary_remote_addr zone=global:10m rate=30r/s;
# API:每秒 10 请求,突发 20
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
# 静态文件:每秒 100 请求
limit_req_zone $binary_remote_addr zone=static:10m rate=100r/s;
# IP 并发限制
limit_conn_zone $binary_remote_addr zone=connperip:10m;
server {
limit_req zone=global burst=50 nodelay;
limit_conn connperip 20;
location / {
try_files $uri $uri/ =404;
}
location /api/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://backend;
}
location ~* \.(jpg|jpeg|png|gif|css|js|woff2)$ {
limit_req zone=static burst=200 nodelay;
expires 7d;
add_header Cache-Control "public, immutable";
}
# 拒绝空 User-Agent 和常见扫描器
if ($http_user_agent ~* (scrapy|curl|wget|python|nikto|sqlmap|nmap)) {
return 444;
}
}
}iptables 限制连接频率
在 Nginx 之前,iptables 可以做第一层过滤:
bash
# === 限制每个 IP 的新连接速率 ===
# 每秒最多 5 个新的 TCP 连接
iptables -A INPUT -p tcp -m state --state NEW \
-m hashlimit \
--hashlimit-name conn_rate \
--hashlimit-above 5/sec \
--hashlimit-burst 10 \
--hashlimit-mode srcip \
-j DROP
# === 限制每个 IP 的并发连接 ===
# HTTP/HTTPS 每个 IP 最多 50 个并发
iptables -A INPUT -p tcp --dport 80 \
-m connlimit --connlimit-above 50 --connlimit-mask 32 \
-j DROP
iptables -A INPUT -p tcp --dport 443 \
-m connlimit --connlimit-above 50 --connlimit-mask 32 \
-j DROP
# === 限制 SSH 并发连接 ===
iptables -A INPUT -p tcp --dport 22 \
-m connlimit --connlimit-above 5 --connlimit-mask 32 \
-j DROPsysctl 防 SYN Flood 参数
config
# /etc/sysctl.d/99-ddos.conf
# SYN Cookie:队列满时用 cookie 验证
net.ipv4.tcp_syncookies = 1
# 增大 SYN 队列
net.ipv4.tcp_max_syn_backlog = 65536
# SYN+ACK 重试次数(默认 5,调低减少半开连接)
net.ipv4.tcp_synack_retries = 1
# SYN 包重传次数
net.ipv4.tcp_syn_retries = 2
# 缩短 TIME_WAIT 回收
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
# 增大连接追踪表(防装满)
net.netfilter.nf_conntrack_max = 2097152
net.netfilter.nf_conntrack_tcp_timeout_established = 1200
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 30
net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 30
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 5
# 快速回收孤儿 socket
net.ipv4.tcp_max_orphans = 65536
# 开启 TCP fastopen(服务端/客户端)
net.ipv4.tcp_fastopen = 3
# 防止 TIME_WAIT 泛洪
net.ipv4.tcp_max_tw_buckets = 1440000bash
sudo sysctl -p /etc/sysctl.d/99-ddos.confCDN 缓解:Cloudflare
对于大规模 DDoS(几百 Gbps 级别),单台服务器无论怎么调参都没用——带宽早就打满了。这时候必须有 CDN 在前面"挡刀"。
Cloudflare 免费版就提供基础 DDoS 保护:
- DNS 托管:把域名的 NS 记录指向 Cloudflare
- 代理模式:Cloudflare 的 CDN 节点承接所有流量,只转发合法请求到源站
- 源站隐藏:Cloudflare 的 IP 暴露在公网,你的服务器真实 IP 不暴露
- WAF 规则:可配置速率限制、IP 封禁、挑战验证
源站 IP 泄露
如果攻击者知道了你的源站真实 IP,他们可以直接绕过 Cloudflare 攻击你的服务器。泄露途径包括:邮件头中的源站 IP、DNS 历史记录、直接访问源站 IP 的 Web 服务。确保源站只接受来自 Cloudflare IP 段的请求,或者配置防火墙白名单。
bash
# 源站 iptables 只允许 Cloudflare IP(需要定期更新)
# Cloudflare IP 列表:https://www.cloudflare.com/ips/
sudo ufw allow from 173.245.48.0/20 to any port 443
sudo ufw allow from 103.21.244.0/22 to any port 443
# ... (完整列表请从 Cloudflare 获取)
sudo ufw deny 443检测当前是否在遭受攻击
bash
# 查看每个 IP 的连接数,发现异常高者
ss -tan | awk '{print $1}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20
# netstat 版本
netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr | head -20
# 查看 SYN_RECV 状态连接数(SYN Flood 特征)
ss -tan state syn-recv | wc -l
# 实时查看 nginx 请求频率
tail -f /var/log/nginx/access.log | awk '{print $1}' | uniq -c
# 带宽监控
nload
iftop🧪 练习题
- 用
ab(Apache Bench)或wrk对你的 Nginx 发起 1000 并发请求,验证limit_req是否生效 - 尝试用
hping3模拟 SYN Flood(仅在本地虚拟机测试!),观察tcp_syncookies的效果 - 配置 Cloudflare 代理你的域名,用 iptables 限制源站只接受 Cloudflare 的请求
DDoS 打的是"量",更难对付的是已经渗透进来的攻击者——应急响应。
🎯 本章要点
- CC 攻击是应用层 DDoS,请求本身合法,但海量请求耗尽服务器 CPU/内存。
- limit_req 基于令牌桶算法限制请求速率(如每秒 10 个请求),超限返回 503。
加载练习题中...