我正在编写一个绑定到多个本地端口(包括80
和443
)的服务器。每当我在 Google 计算机引擎 (GCE) 上使用其容器优化操作系统 (COS) 和 Docker 容器运行它时,端口都会绑定到 IPv6,而不是 IPv4。
$ netstat -tuln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.1:36265 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp6 0 0 :::80 :::* LISTEN
tcp6 0 0 :::443 :::* LISTEN
udp 0 0 10.128.0.33:68 0.0.0.0:*
这是一个重要的区别,因为我的程序中存在尝试使用 IPv4 地址直接连接到本地接口的逻辑127.0.0.1
。
如何指定我的 GCE 实例使用 IPv4 端口?
答案1
编辑
需要注意的一件重要事情(如评论中指出的那样)- 虽然它可能绑定到使用 IPv4 和 IPv6 的接口,但 IPv6 路由不适用于 Google Cloud(尚未内部支持)。
因此,事实证明,这是一个令人困惑的“功能”,与 Docker 的网络连接方式有关,它仍然应该允许 IPv4 连接以及 IPv6 连接。
看这个 StackOverflow 答案了解更多详情。为了方便后人参考,我在下面引用了答案:
...github.com/docker/docker/issues/2174是关于在 中仅显示与 IPv6 的绑定
netstat
,但这不是问题。正如 github 问题所述:设置代理时,Docker 请求回送地址“127.0.0.1”,Linux 意识到这是一个存在于 IPv6 中的地址(如 ::0)并在两者上打开(但它正式是一个 IPv6 套接字)。当您运行 netstat 时,它会看到这个地址并告诉您它是一个 IPv6 - 但它仍然在 IPv4 上监听。如果您对设置稍作调整,您可能已经禁用了 Linux 的这个技巧 - 通过设置 net.ipv6.bindv6only = 1。
换句话说,仅仅因为您将其视为仅 IPv6,它仍然能够在 IPv4 上通信,除非您使用 net.ipv6.bindv6only 设置将 IPv6 设置为仅绑定在 IPv6 上。为了清楚起见,net.ipv6.bindv6only 应该为 0 - 您可以运行
sysctl net.ipv6.bindv6only
以进行验证。