TCP 数据包未到达应用程序,iptables 丢失?

TCP 数据包未到达应用程序,iptables 丢失?

我们偶尔会遇到奇怪的网络堆栈问题,但这种情况并不常见。重新启动相关服务器即可解决问题。

事情发生如下(从tcpdump服务器上收集到)

  • HTTP 客户端开始向 Nginx 发送请求。

  • 服务器正常响应,确认收到的每个数据包。

  • 最终的客户端发送,数据包永远不会到达服务器上的接收套接字。

  • 客户端多次重新发送数据包,最终服务器超时并断开连接。

此外,straceNginx 确认数据是不是到达 Nginx。

这里这是输出的编辑版本tcpdump。我简化了交流并匿名化了一些细节。

打开 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上面的要点中包含了我们的设置。还有什么我可以看看的吗?

DigitalOcean 上的 Ubuntu 12.04.3 上的 Linux 3.8.0。


编辑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

不知道lo这里为什么会涉及此问题。服务器正在接受流量eth0

答案1

您的日志确实显示了lo接口上正在发生的通信。

  1. iptables通过将INPUT表默认策略更改为来禁用ACCEPT并停用任何可能妨碍的REJECT或规则DROP
  2. 再次测试并检查它是否正常工作。如果没有,则问题出在其他地方

我敢打赌 1000 美元,你的接受流量的过滤规则与某个eth0接口绑定,从而拒绝传入的流量lo

我会注意测试客户端与服务器的关系。如果您在同一台机器上运行测试客户端,它很可能使用 IP127.0.0.1地址或localhost通常解析为同一 IP 地址的域名。

这样将会在特殊的环回接口(lo)上发送流量,而不是在那个接口上发送eth0

除非您通过要求 nginx 监听其 IP 地址将 nginx 绑定到特定接口,否则 nginx 将默认监听0.0.0.0,即每个接口。因此,您不会注意到它是否接受连接lo。您可以尝试强制 nginx 监听您的eth0IP 地址以确保万无一失。

在本地测试您的服务器时,请确保使用您的一个外部接口(eth[0..])IP 地址,或解析为其中一个接口的域名。

相关内容