我有一个使用内核选项启动的 Linux (Ubuntu Groovy) 服务器,ipv6.disable=1
因此 IPv6 不可用。
我还有一些双栈软件,宣称它适用于仅 IPv4 的计算机,而且我无法更改。该软件现在想要绑定到::
,这当然失败了。我可以以某种方式配置操作系统以使该服务器绑定0.0.0.0
并使用 IPv4 吗?
编辑:或者,这可以在绑定之前、名称解析期间完成吗?该软件尝试解析::
,如果它将获得 IPv4 地址127.0.0.1
作为响应,我认为它将使用 IPv4。
答案1
即使有可能,您所要求的也不会起作用。如果软件绑定到::,那么它可以假设地址将以 IPv6 格式呈现给它。接受的套接字将是 IPv6,并且 IPv4 地址将被封装。
所以 192.168.1.1 变成 ::FFFF:192.168.1.1
换句话说,即使您可以以某种方式绑定到不同的 IP,您也会将其设置为 IPv4 套接字,而软件不会编译为处理该套接字。该软件需要它是一个 IPv6 套接字,但它不能,因为 IPv6 已被禁用。
禁用 IPv6 时没有兼容性代码。最重要的是您禁用了 IPv6,而您使用的软件要求启用它。
这里唯一的选择是启用 IPv6(从你的问题中不清楚为什么需要禁用它)或自己从源代码重新编译 IPv6 软件,可能会修补源代码以“修复”问题。
答案2
您可以做的就是妥协:启用 IPv6,但不允许它在任何地方有效使用。
启动时启用 IPv6,但通过使用sysctl -w ...
以下参数或在/etc/sysctl.conf
/中添加这些参数,在未来和当前的接口上禁用它/etc/sysctl.d
:
net.ipv6.conf.default.disable_ipv6=1
net.ipv6.conf.all.disable_ipv6=1
这样,IPv6 的使用就被有效禁用,而 IPv6 套接字 API 仍保持启用状态。因此,应用程序仍然可以在双堆栈模式下绑定::
并获取也与其关联的 IPv4(这是默认情况下,根据RFC 3493)。
您可以考虑关于 ::1 的异常和问题罗接口,具体取决于配置和应用程序行为。多项选择中:
/etc/hosts
从如下所示的条目中删除:::1 localhost ip6-localhost ip6-loopback
或者不要禁用 IPv6罗(在之前的设置之后)得到 ::1 :
net.ipv6.conf.lo.disable_ipv6=0
如果选择保留 中的条目
/etc/hosts
,请考虑使 127.0.0.1 优先于 ::1,或者通过添加以下内容来简单地使 IPv4 优于 IPv6/etc/gai.conf
:precedence ::ffff:127.0.0.1/128 100
或者:
precedence ::ffff:0:0/96 100
注意:某些网络配置工具(例如 NetworkManager)会将切换重置disable_ipv6
为其自己的设置,因此必须显式配置为在配置的接口上禁用 IPv6。
替代方法:如果这太麻烦而无法接受,这里有一个禁用 IPv6 的替代方法(在带有 的内核上CONFIG_IP_ADVANCED_ROUTER
,所有主要发行版内核都这样做)。
通过替换来防止 IPv6 路由规则使用路由表偏好 0规则与黑洞导致任何 IPv6 路由查找失败的规则(可以删除所有规则,包括首选项 32766,以获取Network is unreachable
而不是Invalid argument
):
ip -6 rule delete preference 0
ip -6 rule add preference 0 blackhole
即使在任何界面上没有任何其他设置:
$ ping ::1
ping: connect: Invalid argument
ping ff05::2
ping: connect: Invalid argument
虽然监听 IPv6 仍然成功(并且根据 RFC 默认为双堆栈):
$ socat tcp6-listen:4242 /dev/null &
[1] 430541
$ ss -tnle sport == 4242
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 5 *:4242 *:* uid:1000 ino:5971821 sk:1106 v6only:0 <->
由于 IPv4 路由不受阻碍,它仍然可以在双堆栈模式下接收 IPv4 流量。