双栈操作系统中 :: 和 0.0.0.0 的语义

Ale*_*x J 11 linux windows ip ipv6 netstat

回到仅使用 IPv4 的时代,显示netstat为侦听的 LISTEN 连接0.0.0.0将响应系统中任何 IPv4 接口上的连接。

据我了解,新的 IPv6 习惯用法::侦听所有可用的 IPv6IPv4 接口。对于所有操作系统(Unix、Windows、Mac),这是否正确?是否有只听 IPv6 接口的习惯用法?

Jer*_*ser 18

不幸的是,这取决于您使用的操作系统。

在 Microsoft Windows 上,将套接字绑定到::仅绑定到 IPv6 端口。因此,要侦听 IPv4 和 IPv6 上的所有地址,您需要绑定到0.0.0.0以及::。以下摘录来自 Vista 盒子:

C:\>netstat -an | find "445"
  TCP    0.0.0.0:445            0.0.0.0:0              LISTENING
  TCP    [::]:445               [::]:0                 LISTENING
Run Code Online (Sandbox Code Playgroud)

我给出的例子是端口 445,当不使用 NetBIOS 时用于 SMB 流量。如您所见,它绑定到0.0.0.0::分别使 IPv4 和 IPv6 客户端工作。

在 Linux 上,::包括与 IPv4 兼容的地址,正如您正确猜测的那样,因此绑定到0.0.0.0as 是不必要的。我写了一个简单的Python程序,只有结合到AF_INET6插座上::。即使我也没有绑定到AF_INET(IPv4) 套接字,它仍然接受来自 IPv4 客户端的连接。例如,如果10.1.1.3连接到它,它将显示为从 连接::ffff:10.1.1.3

除了它变得毛茸茸的。如果/proc/sys/net/ipv6/bindv6only设置为1,则上述内容不适用于 Linux ,在这种情况下,行为与 Windows 完全相同——绑定到::将仅侦听 IPv6 请求。如果您还想侦听 IPv4 请求,则还需要创建一个AF_INET套接字并侦听0.0.0.0。幸运的是,默认bindv6only0,所以有你永远不得不面对这样的机会非常渺茫(除非你使用Debian,这实际上默认bindv6only = 1)。

在检查服务是否支持 IPv6 以及是否支持 IPv4 时,了解所有这些都很方便。这是我的 SSH 服务器:

$ netstat -64ln | grep 22
tcp6    0    0 :::22    :::*    LISTEN
Run Code Online (Sandbox Code Playgroud)

如您所见,SSH 仅侦听::端口 22。但是,它不仅侦听 IPv6 客户端——它在 IPv4 客户端上也能正常工作,因为 IPv4 兼容绑定。为了证明这一点,如果你看看这个:

$ cat /proc/sys/net/ipv6/bindv6only 
0
Run Code Online (Sandbox Code Playgroud)

bindv6only被禁用(默认)。如果将其设置为1,那么我将不得不鼓励 SSH0.0.0.0也(或改为)进行侦听。

抱歉没有关于 Mac OS X 方面的信息。以前用过,但是比较喜欢GNOME的美观,所以很久没用了。但是,我猜想该行为与 Linux 的行为相同。

希望这可以帮助。