跑网站迟早会遇到 DDoS 攻击。小站可能只是被扫一下就过去了,但要是真被盯上,几分钟就能把服务器打瘫。这篇文章整理了 6 种防御思路和应急处理办法,都是从实际经历里总结的。
先搞清楚 DDoS 是怎么回事
DDoS(分布式拒绝服务)说白了就是用大量请求把你的服务器带宽或资源耗尽,让正常用户访问不了。常见的有三类:
- 流量型:直接用 UDP、ICMP 洪水把带宽塞满,小水管服务器特别容易中招
- 协议型:利用 TCP 三次握手的缺陷,发大量 SYN 包但不完成连接,耗尽服务器连接数
- 应用层:模拟正常用户发 HTTP 请求,比如疯狂刷某个数据库查询很重的页面,这种最难防
大多数小站遇到的是前两种,用 Cloudflare 免费版就能扛住。第三种需要更细的策略。
怎么判断自己被打了
服务器突然变慢或者完全打不开,先别急着重启,看看是不是被攻击了:
# 看当前连接数,正常小站一般不超过几百
netstat -an | wc -l
# 看 SYN_RECV 状态的连接,如果几千个就不对劲了
netstat -an | grep SYN_RECV | wc -l
# 看哪些 IP 连接最多
netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20
# 用 iftop 看实时流量(需要先装)
sudo apt install iftop -y && sudo iftop -n如果某个 IP 有几百上千个连接,或者入站流量远超平时,基本可以确认了。
6 种防御方法
1. 接入 Cloudflare(最简单)
对大多数小站来说,把域名 DNS 切到 Cloudflare 就行了。免费版能防住大部分流量型和协议型攻击。设置也简单:
- 注册 Cloudflare,添加域名,按提示改 NS 记录
- SSL 模式选 Full(Strict),前提是源站有证书
- 开启"Under Attack Mode"可以在被打时临时启用,会给访客一个 5 秒验证页
注意一点:接了 Cloudflare 之后,源站 IP 不要泄露。检查一下 DNS 历史记录、邮件头、API 接口有没有暴露真实 IP。
2. 内核参数调优
调整 Linux 内核参数能提高服务器对 SYN Flood 的抵抗力:
# 编辑 /etc/sysctl.conf,加入以下内容
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_tw_reuse = 1
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 65535
# 生效
sudo sysctl -p其中 tcp_syncookies 最关键,开启后内核在 SYN 队列满时会用 cookie 验证连接,不会直接拒绝。
3. 用 iptables/nftables 做限流
针对单 IP 连接数和请求频率做限制:
# 限制单 IP 每秒新建连接不超过 20 个
iptables -A INPUT -p tcp --syn -m connlimit --connlimit-above 20 -j DROP
# 限制单 IP 每秒请求数
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
# 丢弃明显的扫描包
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP被打的时候如果能确定攻击源 IP 段,直接封掉最快:
# 封一个 IP
iptables -A INPUT -s 1.2.3.4 -j DROP
# 封一个 C 段
iptables -A INPUT -s 1.2.3.0/24 -j DROP4. Nginx 层面的防护
如果用 Nginx 做反向代理,可以加限流配置:
# 在 http 块中定义限流区
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
# 在 server 块中使用
server {
limit_req zone=req_limit burst=20 nodelay;
limit_conn conn_limit 10;
# 屏蔽没有 User-Agent 的请求(很多攻击工具不带)
if ($http_user_agent = "") {
return 444;
}
}444 是 Nginx 特有的状态码,直接断开连接不返回任何内容,比返回 403 省资源。
5. Fail2Ban 自动封禁
Fail2Ban 可以自动分析日志,把异常 IP 加入防火墙黑名单:
sudo apt install fail2ban -y创建配置文件 /etc/fail2ban/jail.local:
[nginx-limit-req]
enabled = true
filter = nginx-limit-req
action = iptables-multiport[name=nginx-limit-req, port="80,443"]
logpath = /var/log/nginx/error.log
findtime = 60
maxretry = 10
bantime = 3600这样 Nginx 限流触发后,对应 IP 会被自动封禁一小时。
6. 换 IP 或者上高防
如果攻击直接打 IP 而不是域名,而且流量超过服务器带宽(比如几十 G),上面那些方法都没用。这时候要么:
- 联系云厂商换一个 IP,然后不要暴露新 IP
- 买高防 IP 或高防 CDN,阿里云、腾讯云都有,按月或按量计费
- 临时把站停了等攻击停——说起来窝囊,但有时候最实际
被打的时候应急处理
真被打了别慌,按这个顺序来:
- 先确认是 DDoS 还是自己代码有 bug 导致的高负载
- 开启 Cloudflare 的 Under Attack Mode(如果接了的话)
- SSH 登录服务器看连接状况,找出攻击特征(IP 段、请求路径、User-Agent)
- 用 iptables 封掉攻击源,或者直接在宝塔面板的防火墙里加规则
- 如果带宽已经被打满连 SSH 都上不去,联系云厂商客服,他们可以在上游帮你过滤
几个容易忽略的点
- 宝塔面板自带的防火墙(Nginx 防火墙插件)其实挺好用的,能做 CC 防护和 IP 黑名单,先用起来
- 定期检查有没有泄露源站 IP:用 SecurityTrails 或者
dig命令查历史 DNS 记录 - 数据库查询慢的页面容易被应用层攻击利用,给这些页面加缓存
- 攻击结束后记得把临时加的 iptables 规则清理掉,别把正常用户也封了
DDoS 防御没有一劳永逸的方案,但对于大多数小站来说,Cloudflare 免费版加上基本的内核和 Nginx 调优就足够了。真被大流量打了,花钱上高防是最直接的办法。
评论
暂无评论