在高流量的 Ubuntu 12 Nginx 服务器上,SYN 数据包被忽略。

3
我有一台安装了 nginx 的 Ubuntu 12.04 服务器,端口为 80。只有一个防火墙规则,将端口 26 映射到 25 端口。nginx 设置为监听端口 80,最初是使用相对默认的设置,现在已做了修改。
listen x.x.x.x:80 backlog=5000;

nginx并不那么繁忙,nginx_status显示大约每秒50个请求。

Active connections: 480 
server accepts handled requests
84618 84618 143733
Reading: 0 Writing: 4 Waiting: 474                                                                                                                    

有些用户(占很少一部分)抱怨他们的某台电脑(比如说“只在家里出现这个问题”)似乎忽略了它的SYN数据包。他们可以进行无丢失的ping测试,有时候他们会收到一些TCP请求的响应。例如在pop服务器上可以得到静态端口的响应。但是通常情况下他们会经历长时间的超时。我从他们那里拿到了数据包转储,证实了这一点。

在我的端口,我也可以看到一些IP地址被忽略了。

例如,在这里,从2010端口发送到80端口的多个SYN数据包没有回复,而服务器正在通过2031端口处理先前的连接。

02:21:46.950979 IP 72.38.0.37.2010 > 64.91.255.98.80: Flags [S], seq 3835139709, win 65535, options [mss 1460,nop,wscale 3,nop,nop,TS val 0 ecr 0,nop,nop,sackOK], length 0
02:21:49.887320 IP 72.38.0.37.2010 > 64.91.255.98.80: Flags [S], seq 3835139709, win 65535, options [mss 1460,nop,wscale 3,nop,nop,TS val 0 ecr 0,nop,nop,sackOK], length 0
02:21:55.923151 IP 72.38.0.37.2010 > 64.91.255.98.80: Flags [S], seq 3835139709, win 65535, options [mss 1460,nop,wscale 3,nop,nop,TS val 0 ecr 0,nop,nop,sackOK], length 0
02:22:24.950448 IP 72.38.0.37.2031 > 64.91.255.98.80: Flags [S], seq 4138069869, win 65535, options [mss 1460,nop,wscale 3,nop,nop,TS val 0 ecr 0,nop,nop,sackOK], length 0
02:22:24.950488 IP 64.91.255.98.80 > 72.38.0.37.2031: Flags [S.], seq 248034551, ack 4138069870, win 14480, options [mss 1460,sackOK,TS val 240617577 ecr 0,nop,wscale 7], length 0
02:22:24.982809 IP 72.38.0.37.2031 > 64.91.255.98.80: Flags [.], ack 1, win 50112, options [nop,nop,TS val 372774 ecr 240617577], length 0
02:22:24.982852 IP 72.38.0.37.2031 > 64.91.255.98.80: Flags [P.], seq 1:526, ack 1, win 50112, options [nop,nop,TS val 372774 ecr 240617577], length 525
02:22:24.982869 IP 64.91.255.98.80 > 72.38.0.37.2031: Flags [.], ack 526, win 122, options [nop,nop,TS val 240617585 ecr 372774], length 0
02:22:25.016783 IP 64.91.255.98.80 > 72.38.0.37.2031: Flags [P.], seq 1:265, ack 526, win 122, options [nop,nop,TS val 240617594 ecr 372774], length 264
02:22:25.190570 IP 72.38.0.37.2031 > 64.91.255.98.80: Flags [.], ack 265, win 50079, options [nop,nop,TS val 372777 ecr 240617594], length 0
02:22:45.017288 IP 64.91.255.98.80 > 72.38.0.37.2031: Flags [F.], seq 265, ack 526, win 122, options [nop,nop,TS val 240622594 ecr 372777], length 0
02:22:45.049437 IP 72.38.0.37.2031 > 64.91.255.98.80: Flags [.], ack 266, win 50079, options [nop,nop,TS val 372976 ecr 240622594], length 0
02:22:49.998299 IP 72.38.0.37.2031 > 64.91.255.98.80: Flags [R.], seq 526, ack 266, win 0, length 0
02:23:18.883263 IP 72.38.0.37.2059 > 64.91.255.98.80: Flags [S], seq 2419025537, win 65535, options [mss 1460,nop,wscale 3,nop,nop,TS val 0 ecr 0,nop,nop,sackOK], length 0
02:23:21.890861 IP 72.38.0.37.2059 > 64.91.255.98.80: Flags [S], seq 2419025537, win 65535, options [mss 1460,nop,wscale 3,nop,nop,TS val 0 ecr 0,nop,nop,sackOK], length 0

更简单地说,在20秒的开始附近,这里有一个来自一个IP的孤立数据包,它没有与任何其他数据包(发送到此主机)匹配:

2:48:05.141703 IP 96.48.197.237.1275 > 64.91.255.98.80: Flags [S], seq 2682822499, win 65535, options [mss 1460,nop,wscale 2,nop,nop,TS val 0 ecr 0,nop,nop,sackOK], length 0

我写了一个Perl脚本,用于监视tcpdump并查找/报告悬空SYN的数量。每隔几秒钟它会发现一些悬空SYN(随着我们累积的从未回复的TCP SYN数据包计数稳步上升)。显然未回复SYN的速率约为2500中的1个。当我ping这些IP时,假设它们是可ping通的,没有丢包,也没有与它们通信的问题。
内核日志中没有有用的信息(例如“发送syncookies”)。
nginx有
worker_processes 8
worker_connections 4096

开启了keepalive,使用了open_file_cache模块,但我很难看到哪些其他变量可能会默默地忽略SYN数据包,但只针对特定的IP地址进行重复操作。

除了默认的Ubuntu设置外,sysctl.conf还有:

# increased
net.ipv4.tcp_fin_timeout = 10
net.ipv4.ip_local_port_range = 1024 65535
net.core.somaxconn = 1024
# default
net.ipv4.tcp_tw_reuse = 0
# default
net.netfilter.nf_conntrack_tcp_loose = 1
net.ipv4.netfilter.ip_conntrack_tcp_loose = 1
# reduced
net.netfilter.nf_conntrack_tcp_timeout_established = 86400
net.ipv4.tcp_ecn = 0

我以前从未遇到过这个问题。虽然受众相同,内核版本较早,硬件不同(这是一个虚拟服务器),数据中心也不同。
我的“煤矿中的金丝雀”报告显示,从他们的角度来看,他们在他们的Windows XP电脑上看到了超时和无回复,但如果通过设置为代理的Linux机器进行,则不存在这种情况。因此,他们正在调查这个问题。然而,无论他们得出什么结论,我都不确定为什么我可以嗅探来自端口80的入站SYN数据包,但没有在同一接口上发送出去的后续回复数据包。
2个回答

1
基于这里的信息

https://serverfault.com/questions/235965/why-would-a-server-not-send-a-syn-ack-packet-in-response-to-a-syn-packet

在服务器上关闭TCP时间戳可以防止Windows XP客户端发送tsval为零的SYN数据包被丢弃,未响应的SYN数量降为零并保持不变。

sysctl -w net.ipv4.tcp_timestamps = 0

我的理解是,当启用时间戳时,XP堆栈的行为是众所周知的,因为它已经在与ipv4有关的linux列表上讨论过,在某个时刻启用tcp_timestamps的linux会简单地切换到与XP(或其他有缺陷的客户端)非时间戳会话。现在看来这种行为已经改变了,至少在繁忙的端口上,如果tcp_timestamps为1,则SYN包的tsval 0会被丢弃。

0

你的系统是否启用了三向同步检查?听起来它正在检查三向握手,有些数据包没有通过此检查,即使它们不是恶意的,也会被丢弃。

请检查或发布所有配置,或检查您的路由器/防火墙,因为通常默认情况下会设置此选项。


我在Ubuntu中找不到任何关于这个的参考,并且它也没有被选择启用。除了提到的iptables规则之外,该盒子上没有防火墙,而且由于该盒子是我运行tcpdump的地方,我不确定数据中心中的任何防火墙如何受到责备? - user2603628
1
我目前还不能“回答自己的问题”,但是这个问题的答案已经出现在这个链接中:http://serverfault.com/questions/235965/why-would-a-server-not-send-a-syn-ack-packet-in-response-to-a-syn-packet - user2603628
附注:请注意,使用Linux内核2.6.11和启用TCP时间戳的相同用户群体没有观察到这样的问题,现在使用内核3.2.0,必须禁用TCP时间戳才能回复100%的良好SYN数据包。 - user2603628

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接