我花了大约 6 个小时试图弄清楚这一点,现在我相信 CentOS/Linux 在连接到具有 IPv6 地址的主机名时无法绑定到特定的虚拟 IPv4 地址。这是具有多个 IP 地址的服务器的问题。
我正在使用 Centos 6(Linux 内核 2.6.32-573.12.1.el6.x86_64)
要重现这个大:
- 查找至少具有 /29 IPv4 公共地址空间和 IPv6 公共 IP 的 Linux 机器。
- 将至少一个附加 IPv4 别名到主接口(eth0 或其他)。对于这个例子,我会说 30.0.0.1 作为机器的主要 eth0 IPv4 地址,而 30.0.0.2 是绑定到 30.0.0.0/29 网络上的 eth0:2 的别名。
- 查找同时具有 IPv4 和 IPv6 地址的主机名。例如,www.microsoft.com。
telnet -b 30.0.0.2 www.microsoft.com 80
(这测试使用特定的 ipv4 地址建立出站连接)- IPv4 请求在尝试主机名的 IPv6 地址失败后连接成功,但 TCP 连接实际上是从机器的主 IP (30.0.0.1) 发起的,而不是您想要的 IP (30.0.0.2)。Netstat 另有说法,但这是错误的。如果您连接到您拥有的主机名并可以查看其日志,则连接来自主 IP (30.0.0.1) 而不是您想要的 IP (30.0.0.2)。
- 尝试另一个没有 IPv6 地址的域,例如:
telnet -b 30.0.0.2 serverfault.com
. 有用。它从您想要的 IP 建立连接。
这是一个问题,因为某些程序,例如mail(exim),在发出出站TCP请求时需要使用某些IP,而这不一定是主机的IP。机器上的某些客户端/程序在建立出站 TCP 连接时依赖 ACL 或反向 DNS 来正确匹配。
因此,如果其他人在进行传出连接时注意到他们的程序无法绑定到正确接口的同样奇怪的问题,这可能就是原因。
此问题仅影响 IPv4 连接。IPv6 连接正确绑定到您机器上的任何传出 IP。
这不是 telnet 的问题。我也使用我的邮件服务器(exim)测试了这个问题,并得到了类似的结果。如果目标主机名具有 IPv6 地址,它会从错误的 IP 建立 IPv4 连接。
也许有人对这个奇怪的问题有解决方案,但此时,我认为这可能是一个 Linux 网络错误。
Ps-如果有人想知道如果主机名解析为 IPv6 地址,为什么不建立 IPv6 连接……有时 IPv6 地址已关闭或无法建立连接,然后它会恢复到其 IPv4 地址。
您可以相信
netstat
会为您提供有关 IP 地址的正确信息(至少在-n
使用时如此)。如果 TCP 连接的端点在使用哪些 IP 地址上存在分歧,则意味着两者之间存在 NAT。
从评论中提供的附加信息中,我们了解到在这种特殊情况下,多余的 iptables 规则
-A POSTROUTING -j MASQUERADE
是问题的原因。