这篇文章上次修改于 899 天前,可能其部分内容已经发生变化,如有疑问可询问作者。
1 现象
# -w 表示只输出 HTTP 状态码及总时间,
# -o表 示将响应重定向到 /dev/null
# --connect-timeout 表示连接超时时间
$ curl -w 'Http code: %{http_code}\nTotal time:%{time_total}s\n' -o /dev/null --connect-timeout 10 http://192.168.0.30
...
Http code: 000Total time:10.001scurl: (28) Connection timed out after 10000 milliseconds
客户端连接超时,且没有收到服务端的响应。
2 排查
查看网络:
$ sar -n DEV 1
08:55:49 IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil
08:55:50 docker0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
08:55:50 eth0 22274.00 629.00 1174.64 37.78 0.00 0.00 0.00 0.02
08:55:50 lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
网络接收的 PPS 已经达到了 20000 多,但是 BPS 却只有 1174 kB,这样每个包的大小就只有 54(1174*1024/22274=54)。
用 tcpdump 查看小包是什么:
# -i eth0 只抓取eth0网卡,
# -n 不解析协议名和主机名
# tcp port 80 表示只抓取 tcp 协议并且端口号为 80 的网络帧
$ tcpdump -i eth0 -n tcp port 80
09:15:48.287047 IP 192.168.0.2.27095 > 192.168.0.30: Flags [S], seq 1288268370, win 512, length
009:15:48.287050 IP 192.168.0.2.27131 > 192.168.0.30: Flags [S], seq 2084255254, win 512, length
009:15:48.287052 IP 192.168.0.2.27116 > 192.168.0.30: Flags [S], seq 677393791, win 512, length
009:15:48.287055 IP 192.168.0.2.27141 > 192.168.0.30: Flags [S], seq 1276451587, win 512, length
009:15:48.287068 IP 192.168.0.2.27154 > 192.168.0.30: Flags [S], seq 1851495339, win 512, length 0
...
都是 SYN 包,可见是受到了 SYN Flood 攻击。
查看 SYN 包的数量:
$ netstat -n -p | grep SYN_REC | wc -l
193
3 缓解 DDos 攻击
限制单个攻击源:
# 限制syn并发数为每秒1次
$ iptables -A INPUT -p tcp --syn -m limit --limit 1/s -j ACCEPT
# 限制单个IP在60秒新建立的连接数为10
$ iptables -I INPUT -p tcp --dport 80 --syn -m recent --name SYN_FLOOD --update --seconds 60 --hitcount 10 -j REJECT
对 TCP 优化:
$ cat /etc/sysctl.conf
# 降低连接每个 SYN_RECV 失败时的默认的重试次数
sysctl -w net.ipv4.tcp_synack_retries=1
# 开启 SYN Cookies,不需要维护半开连接状态
sysctl -w net.ipv4.tcp_syncookies=1
要使 /etc/sysctl.conf 生效,需执行 sysctl -p 命令。写到 /etc/sysctl.conf 中后,重启仍然会生效。
参考
倪朋飞. Linux 性能优化实战.
没有评论