我们偶尔也会遇到一个奇怪的networking堆栈问题。 重新引导有问题的服务器清除它。
它发生如下(通过服务器上的tcpdump
收集) :
HTTP客户端开始向Nginx发送请求。
服务器正常响应,确认每个数据包。
在最终客户端发送时,数据包永远不会到达服务器上的接收套接字。
客户端重新发送数据包,然后服务器终于超时并断开连接。
另外,Nginx的strace
证实数据没有达到Nginx。
这里是tcpdump
输出的编辑版本。 我简化了交stream,并匿名了一些细节。
打开iptables日志显示一些数据包被阻止,这可能是相关的:
IN= OUT=lo SRC=client DST=server LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=39670 DPT=80 WINDOW=0 RES=0x00 RST URGP=0 IN= OUT=eth0 SRC=server DST=client LEN=52 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=80 DPT=39669 WINDOW=31 RES=0x00 ACK URGP=0
但是,我们的iptables设置是行人。 我们阻止除RELATED,ESTABLISHED
之外的所有内容,并允许有问题的端口80.我不明白为什么iptables阻止了这个,除非数据包在RELATED
和ESTABLISHED
状态之外。
上面的要点也包含了我们的sysctl
设置。 还有什么我可以看看?
Ubuntu 12.04.3上的Linux 3.8.0,DigitalOcean上。
编辑3 :禁用iptables,同样的问题,所以它不是由坏的iptables规则造成的。
编辑2 :上面我显示iptables阻塞RST
包,但更重要的是它阻塞了很多ACK
。 我只是随便选了一个日志条目, ACK
似乎比较常见。
编辑1 :我添加了iptables跟踪。 这似乎是丢弃一个数据包的部分(但是,再次,不知道这是否与我的问题有关):
TRACE: raw:OUTPUT:rule:2 IN= OUT=lo SRC=client DST=server LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=41572 DPT=8001 SEQ=2118637628 ACK=0 WINDOW=0 RES=0x00 RST URGP=0 TRACE: raw:OUTPUT:policy:3 IN= OUT=lo SRC=client DST=server LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=41572 DPT=8001 SEQ=2118637628 ACK=0 WINDOW=0 RES=0x00 RST URGP=0 TRACE: filter:OUTPUT:rule:3 IN= OUT=lo SRC=client DST=server LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=41572 DPT=8001 SEQ=2118637628 ACK=0 WINDOW=0 RES=0x00 RST URGP=0 TRACE: filter:block:rule:1 IN= OUT=lo SRC=client DST=server LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=41572 DPT=8001 SEQ=2118637628 ACK=0 WINDOW=0 RES=0x00 RST URGP=0 TRACE: filter:logging:rule:1 IN= OUT=lo SRC=client DST=server LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=41572 DPT=8001 SEQ=2118637628 ACK=0 WINDOW=0 RES=0x00 RST URGP=0 iptables: reject: IN= OUT=lo SRC=client DST=server LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=41572 DPT=8001 WINDOW=0 RES=0x00 RST URGP=0
不知道为什么这里介入。 服务器正在接受eth0
stream量。
你的日志肯定会显示在lo
界面上发生的通讯。
INPUT
表默认策略更改为ACCEPT
来禁用iptables
,并禁用可能阻碍的任何REJECT
或DROP
规则 我敢打赌1000美元的事实,你的过滤规则接受stream量绑定到一些eth0
接口,从而拒绝stream量传入。
我会注意到与服务器有关的testing客户端。 如果您在同一台计算机上运行testing客户端,则最有可能使用通常parsing为相同IP地址的127.0.0.1
IP地址或localhost
域名。
这将在特殊的环回接口( lo
)而不是在eth0
上发送stream量。
除非你通过要求nginx监听其IP地址来将nginx绑定到一个特定的接口,否则nginx将在每个接口的0.0.0.0
默认监听。 因此,如果它接受或不接受连接,您将不会注意到。 你可以尝试强制nginx在你的eth0
IP地址上进行监听。
在本地testing服务器时,请确保使用您的一个外部接口( eth[0..]
)IP地址或parsing其中一个的域名。