环境准备
预先安装 docker、sysstat、sar 、hping3、tcpdump 等工具,比如 apt-get install docker.io sysstat hping3 tcpdump。
操作和分析
在第一个终端,执行下面的命令运行案例,也就是一个最基本的 Nginx 应用:
# 运行Nginx服务并对外开放80端口
docker run -itd --name=nginx -p 80:80 nginx
在第二个终端,使用 curl 访问 Nginx 监听的端口,确认 Nginx 正常启动。假设 xxx.xxx.xxx.xxx是 Nginx 所在虚拟机的 IP 地址,运行 curl 命令后你应该会看到下面这个输出界面:
$ curl http://xxx.xxx.xxx.xxx/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
还是在第二个终端,我们运行 hping3 命令,来模拟 Nginx 的客户端请求:
# -S参数表示设置TCP协议的SYN(同步序列号),-p表示目的端口为80
# -i u100表示每隔100微秒发送一个网络帧
# 注:如果你在实践过程中现象不明显,可以尝试把100调小,比如调成10甚至1
$ hping3 -S --flood -p 80 xxx.xxx.xxx.xxx
第一个终端感觉系统响应明显变慢了,即便只是在终端中敲几个回车,都得很久才能得到响应?
在实际的生产环境中,如果遇到系统响应变慢要怎么分析呢?
top 看看是不是出现了 CPU 的瓶颈。我们在第一个终端运行 top 命令,看一下系统整体的资源使用情况。
平均负载全是 0,就绪队列里面只有一个进程(1 running)。
每个 CPU 的使用率都挺低,最高的 CPU的使用率也只有 1.0%,并不算高。
再看进程列表,CPU 使用率最高的进程也只有 0.3%,还是不高呀。
那为什么系统的响应变慢了呢?既然每个指标的数值都不大,那我们就再来看看,这些指标对应的进程
进程列表里面的软中断ksoftirqd有CPU使用率
查看/proc/softirqs 文件的内容,你就能知道各种软中断类型的次数。
watch -d cat /proc/softirqs
TIMER(定时中断)、NET_RX(网络接收)、SCHED(内核调度)、RCU(RCU 锁)等这几个软中断都在不停变化。其中,NET_RX,也就是网络数据包接收软中断的变化速率最快。
分析网络数据包接收软中断
sar 可以用来查看系统的网络收发情况,还有一个好处是,不仅可以观察网络收发的吞吐量(BPS,每秒收发的字节数),还可以观察网络收发的 PPS,即每秒收发的网络帧数。
sar -n DEV 1
rxpck/s 和 txpck/s 分别表示每秒接收、发送的网络帧数,也就是 PPS
rxkB/s 和 txkB/s 分别表示每秒接收、发送的千字节数,也就是 BPS
接收的 PPS 比较大,达到 588,而接收的 BPS 却很小,只有 35KB。直观来看网络帧应该都是比较小的,我们稍微计算一下,35*1024/588 = 1.8字节,说明平均每个网络帧只有 54 字节,这显然是很小的网络帧,也就是我们通常所说的小包问题。
BPS还有PPS计算参考
https://blog.csdn.net/weixin_51617086/article/details/127286395?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170441516716800182717323%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=170441516716800182717323&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v1~rank_v31_ecpm-2-127286395-null-null.142v99pc_search_result_base3&utm_term=PPS%20BPS&spm=1018.2226.3001.4187
网络帧从哪里发过来的呢?使用 tcpdump 抓取 eth0 上的包就可以了。我们事先已经知道, Nginx 监听在 80 端口,它所提供的 HTTP 服务是基于 TCP 协议的,所以我们可以指定 TCP 协议和 80 端口精确抓包。
# -i eth0 只抓取eth0网卡,-n不解析协议名和主机名
# tcp port 80表示只抓取tcp协议并且端口号为80的网络帧
tcpdump -i eth0 -n tcp port 80
IP1.18238 > IP2.80 ,表示网络帧从 IP1 的 18238 端口发送到 IP2 的 80 端口,也就是从运行 hping3 机器的 18238 端口发送网络帧,目的为 Nginx 所在机器的 80 端口。
Flags [S] 则表示这是一个 SYN 包。再加上前面用 sar 发现的, PPS 超过 588的现象,现在我们可以确认,这就是从 IP1这个地址发送过来的 SYN FLOOD 攻击。
SYN FLOOD 问题最简单的解决方法,就是从交换机或者硬件防火墙中封掉来源 IP,这样 SYN FLOOD 网络帧就不会发送到服务器中。
总结一下
先用TOP查看软中断进程,通过 /proc/softirqs 文件的变化情况,判断出软中断类型是网络接收中断;再通过 sar 和 tcpdump ,确认这是一个 SYN FLOOD 问题。