为什么在 Linux 机器上,除了 icmp 之外的任何数据包都无法通过,但在 Windows 上却可以正确通过

为什么在 Linux 机器上,除了 icmp 之外的任何数据包都无法通过,但在 Windows 上却可以正确通过

proxmox 上有一个集群。集群中有配置了 vm 的路由器 (pfsense)。我们的网络中有 Windows 和 Linux 机器。

存在一个问题:Windows 机器可以访问互联网,但 Linux 机器却不能。

所有 Linux 机器的行为都一样,它发送请求并等待响应,但响应没有返回。我使用 wget、ssh 和 nslookup 检查了外部服务器(例如 8.8.8.8)并执行了 ping。除了 ping 之外,其他都不起作用。ICMP 数据包正确传输,因此我冒昧地认为问题出在 TCP 上。但对于所有 Windows 机器,一切都正常工作。

我没有为 Linux 或 Windows 创建特殊的过滤规则。

我绞尽了脑汁,却还是没能解决这个问题。

基线:

Our External IP:    XX.XXX.XX.XX
External Server IP:   Y.YYY.Y.YYY   (which was used to test)

因此,我进行了两次测试:

测试1.从Linux机器执行wget:

从路由器捕获的数据包:

No.  Time         Source             Destination     Protocol Length Info
      1 0.000000  XX.XXX.XX.XX       Y.YYY.Y.YYY        HTTP     174 GET / HTTP/1.1
      2 21.798340 XX.XXX.XX.XX       Y.YYY.Y.YYY        TCP       74 49656 > http [SYN] Seq=0 Win=14600 Len=0 MSS=1460 SACK_PERM=1 TSval=173036151 TSecr=0 WS=128
      3 21.850793 Y.YYY.Y.YYY        XX.XXX.XX.XX       TCP       74 http > 49656 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 SACK_PERM=1 TSval=1304117522 TSecr=173036151 WS=1024
      4 21.850849 XX.XXX.XX.XX       Y.YYY.Y.YYY        TCP       66 49656 > http [ACK] Seq=1 Ack=1 Win=14720 Len=0 TSval=173036203 TSecr=1304117522
      5 21.850868 XX.XXX.XX.XX       Y.YYY.Y.YYY        HTTP     174 GET / HTTP/1.1
      6 22.101939 XX.XXX.XX.XX       Y.YYY.Y.YYY        HTTP     174 [TCP Retransmission] GET / HTTP/1.1
      7 22.605999 XX.XXX.XX.XX       Y.YYY.Y.YYY        HTTP     174 [TCP Retransmission] GET / HTTP/1.1
      8 23.613997 XX.XXX.XX.XX       Y.YYY.Y.YYY        HTTP     174 [TCP Retransmission] GET / HTTP/1.1
      9 25.629983 XX.XXX.XX.XX       Y.YYY.Y.YYY        HTTP     174 [TCP Retransmission] GET / HTTP/1.1
     10 28.931894 Y.YYY.Y.YYY        XX.XXX.XX.XX       TCP       78 http > 11956 [FIN, ACK] Seq=1 Ack=1 Win=6 Len=0 TSval=1304124610 TSecr=172983238 SLE=109 SRE=110
     11 28.932001 XX.XXX.XX.XX       Y.YYY.Y.YYY        TCP       66 [TCP Previous segment not captured] 11956 > http [ACK] Seq=110 Ack=2 Win=115 Len=0 TSval=173043285 TSecr=1304124610
     12 29.661996 XX.XXX.XX.XX       Y.YYY.Y.YYY        HTTP     174 [TCP Retransmission] GET / HTTP/1.1
     13 31.360021 XX.XXX.XX.XX       Y.YYY.Y.YYY        HTTP     174 [TCP Retransmission] GET / HTTP/1.1

从我的外部服务器捕获的数据包:

No.  Time         Source             Destination     Protocol Length Info
      1 0.000000  XX.XXX.XX.XX       Y.YYY.Y.YYY        TCP       76 49656 > http [SYN] Seq=0 Win=14600 Len=0 MSS=1460 SACK_PERM=1 TSval=173036151 TSecr=0 WS=128
      2 0.000059  Y.YYY.Y.YYY        XX.XXX.XX.XX       TCP       76 http > 49656 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 SACK_PERM=1 TSval=1304117522 TSecr=173036151 WS=1024
      3 0.059242  XX.XXX.XX.XX       Y.YYY.Y.YYY        TCP       68 49656 > http [ACK] Seq=1 Ack=1 Win=14720 Len=0 TSval=173036203 TSecr=1304117522
      4 0.059247  XX.XXX.XX.XX       Y.YYY.Y.YYY        HTTP     176 GET / HTTP/1.1
      5 0.303398  XX.XXX.XX.XX       Y.YYY.Y.YYY        HTTP     176 [TCP Retransmission] GET / HTTP/1.1
      6 0.809767  XX.XXX.XX.XX       Y.YYY.Y.YYY        HTTP     176 [TCP Retransmission] GET / HTTP/1.1
      7 1.815634  XX.XXX.XX.XX       Y.YYY.Y.YYY        HTTP     176 [TCP Retransmission] GET / HTTP/1.1
      8 3.836576  XX.XXX.XX.XX       Y.YYY.Y.YYY        HTTP     176 [TCP Retransmission] GET / HTTP/1.1
      9 7.088059  Y.YYY.Y.YYY        XX.XXX.XX.XX       TCP       80 http > 11956 [FIN, ACK] Seq=1 Ack=1 Win=6 Len=0 TSval=1304124610 TSecr=172983238 SLE=109 SRE=110
     10 7.134903  XX.XXX.XX.XX       Y.YYY.Y.YYY        TCP       68 11956 > http [ACK] Seq=110 Ack=2 Win=115 Len=0 TSval=173043285 TSecr=1304124610
     11 7.864582  XX.XXX.XX.XX       Y.YYY.Y.YYY        HTTP     176 [TCP Retransmission] GET / HTTP/1.1
     12 9.564772  XX.XXX.XX.XX       Y.YYY.Y.YYY        HTTP     176 [TCP Retransmission] GET / HTTP/1.1

测试2.从Windows机器执行wget:

从路由器捕获的数据包:

No.  Time         Source             Destination     Protocol Length Info
      1 0.000000  XX.XXX.XX.XX       Y.YYY.Y.YYY        TCP       66 ampr-info > http [SYN] Seq=0 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1
      2 0.053994  Y.YYY.Y.YYY        XX.XXX.XX.XX       TCP       66 http > ampr-info [SYN, ACK] Seq=0 Ack=1 Win=5840 Len=0 MSS=1460 SACK_PERM=1 WS=1024
      3 0.054129  XX.XXX.XX.XX       Y.YYY.Y.YYY        TCP       54 ampr-info > http [ACK] Seq=1 Ack=1 Win=65536 Len=0
      4 0.054450  XX.XXX.XX.XX       Y.YYY.Y.YYY        HTTP     150 GET / HTTP/1.0
      5 0.110034  Y.YYY.Y.YYY        XX.XXX.XX.XX       TCP       60 http > ampr-info [ACK] Seq=1 Ack=97 Win=6144 Len=0
      6 0.113011  Y.YYY.Y.YYY        XX.XXX.XX.XX       HTTP     931 HTTP/1.1 200 OK  (text/html)
      7 0.115990  XX.XXX.XX.XX       Y.YYY.Y.YYY        TCP       54 ampr-info > http [RST, ACK] Seq=97 Ack=878 Win=0 Len=0

从我的外部服务器捕获的数据包:

No.  Time         Source             Destination     Protocol Length Info
      1 0.000000  XX.XXX.XX.XX       Y.YYY.Y.YYY        TCP       66 ampr-info > http [SYN] Seq=0 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1
      2 0.053994  Y.YYY.Y.YYY        XX.XXX.XX.XX       TCP       66 http > ampr-info [SYN, ACK] Seq=0 Ack=1 Win=5840 Len=0 MSS=1460 SACK_PERM=1 WS=1024
      3 0.054129  XX.XXX.XX.XX       Y.YYY.Y.YYY        TCP       54 ampr-info > http [ACK] Seq=1 Ack=1 Win=65536 Len=0
      4 0.054450  XX.XXX.XX.XX       Y.YYY.Y.YYY        HTTP     150 GET / HTTP/1.0
      5 0.110034  Y.YYY.Y.YYY        XX.XXX.XX.XX       TCP       60 http > ampr-info [ACK] Seq=1 Ack=97 Win=6144 Len=0
      6 0.113011  Y.YYY.Y.YYY        XX.XXX.XX.XX       HTTP     931 HTTP/1.1 200 OK  (text/html)
      7 0.115990  XX.XXX.XX.XX       Y.YYY.Y.YYY        TCP       54 ampr-info > http [RST, ACK] Seq=97 Ack=878 Win=0 Len=0    

请帮帮我,有什么想法吗?

答案1

我以前也见过类似的问题。原来是校验和卸载问题导致的。虚拟化客户操作系统会将校验和卸载到虚拟化主机,而虚拟化主机本应将其卸载到物理网络接口。

但最终校验和从未被计算出来,数据包在网络上发送时没有有效的校验和。在连接的接收端,数据包会因为校验和无效而被丢弃。

在虚拟化主机和客户机上,您可以尝试查找具有以下任意名称的选项并尝试将其关闭:

  • UDP 校验和卸载
  • TCP 校验和卸载
  • UDP 碎片卸载
  • TCP 分段卸载

答案2

有趣的问题。它看起来不像是防火墙问题,否则初始的 3 次 TCP 握手将无法工作。尽管 TCP 重新传输,但它似乎不是 MTU 问题,因为数据包非常小,而且您再次在两端看到它们。看起来 Web 服务器确实没有响应 GET 请求。

DNS 查找将使用 UDP,因此这又是另外一回事了。您在尝试 SSH 的数据包捕获中看到了什么?此外,如果您远程登录到外部服务器的端口 80 并发出手动 GET 请求,结果会怎样:

telnet y.y.y.y 80
GET / HTTP/1.1
host: y.y.y.y
<line feed>

尝试使用上述方法处理 HTTP 1.0 和 1.1。我注意到 Linux 和 Windows 数据包上限中的 GET 请求之间存在差异。应该没什么影响,但值得一试。

答案3

经过几个月的工作,我将 Windows 机器上的网卡驱动程序转换为 virtio,问题也出现在 Windows 机器上。确实如此,问题似乎与个人不兼容 pfSense (或 freebsd)和 virtio-drivers 或 proxmox 的其他组件。

此时,我决定通过以下方式来解决这个问题:

  1. Proxmox 集群直接连接到互联网并配置到路由器。
  2. 在 proxmox 和 pfSense 之间创建了另一个新子网
  3. 对于每台服务器,在这个新子网中创建第二个网络适配器,并在每个 proxmox 上将其配置为默认网关。
  4. 在 proxmox-cluster 上,创建了一条规则,必须将某些端口转发到此服务器并将所有外部流量转发到 pfSense。

结果我得到了以下信息:

  • 我网络上的所有客户端计算机都可以通过 pfSense 访问互联网,并使用 pfSense 的服务(代理服务器、日志等等)
  • proxmox 集群上的所有服务器都可以通过 proxmox 集群直接访问互联网
  • 还有一个好处,如果 pfSense 出现故障,我仍然可以通过 SSH 访问 Proxmox 集群

谢谢你们!

答案4

不幸的是我暂时无法发表评论 :-(
据我所知,您已经查看了通过路由器和往返于目标服务器的数据包。您是否尝试过在任何行为不端的 Linux 主机上使用 tcpdump 或 wireshark 来查看实际到达/离开主机的内容?
另一件需要测试的事情可能是在您的一台 Linux 主机上完全禁用 iptables 以进行测试。虽然您没有在主机上配置任何特殊的防火墙规则,但可能存在一些行为不端的默认规则。

相关内容