Linux 上设置 IPv4 优先

今天遇到一个情况,在访问下游服务的时候,下游服务的授权是根据 ip 进行授权的。

而我一台服务器上既有 ipv4 地址又有 ipv6 地址,如果为两个 ip 都授权,那么服务费就 double 了,这显然有些浪费,所以我只授权了 ipv4 地址。

这样就出现了下游服务不稳定的情况,如果服务器访问下游服务的时候以 ipv6 作为出口就会失败,反之以 ipv4 就能成功。

服务商建议是关闭 ipv6, 但是这显然是没有考虑到整个系统的健壮性和完备性, 我的整个服务双协议栈肯定是要支持的, 这是一种不可逆的趋势。最后折中的办法是在服务器上设置为 ipv4 优先,虽然这种办法不是很完美,但是在目前的情况下勉强够用了。情况就是这样的情况,如果你有更好的方法,请在评论区留言, 让更多人知道。

下面直接进入正题。

如何设置 IPv4 优先

在 Debian、Redhat 等 Linux 系统下,有一个 /etc/gai.conf 文件,用于系统的 getaddrinfo 调用,默认情况下,它会使用 IPv6 优先,如果您安装了 curl 并且本地支持 IPv6,那么可以使用 curl ip.sb 测试:

1
2
3
4

root@server ~ # curl ip.sb
2001:db8::2

效果等同于 curl ip.sb -6

1
2
3
4

root@server ~ # curl ip.sb -6
2001:db8::2

如果你不想使用 IPv6 优先,可以在这个文件/etc/gai.conf(如果没有,可以手动创建它)中找到:

1
2
3

#precedence ::ffff:0:0/96 100

添加一行或取消注释,修改为:

1
2
3

precedence ::ffff:0:0/96 100

作用解释:

::ffff:0:0/96 是 IPv6 的一个特殊地址范围,称为 IPv4-mapped IPv6 addresses。它用于表示 IPv4 地址在 IPv6 中的映射。
precedence ::ffff:0:0/96 100 的意思是:
为 IPv4 映射的 IPv6 地址(::ffff:0:0/96)设置优先级为 100。
这个优先级值高于其他 IPv6 地址的默认优先级,因此系统会优先选择 IPv4 地址。

此时再使用 curl ip.sb 测试

1
2
3
4

root@server ~ # curl ip.sb
192.0.2.2

效果等同于 curl ip.sb -4

1
2
3
4

root@server ~ # curl ip.sb -4
192.0.2.2

其他检验 Ipv4 是否生效的方法

  1. 使用 ping 测试

运行以下命令:

1
ping ip.sb

如果 /etc/gai.conf 的修改生效,ping 会优先解析 IPv4 地址。
如果未生效,ping 会解析 IPv6 地址。

  1. 使用 getent 测试

运行以下命令:

1
getent ahosts ip.sb
  • getent ahosts 会显示域名解析的结果。
  • 如果 /etc/gai.conf 的修改生效,IPv4 地址会出现在解析结果的第一行,例如:
    1
    2
    192.0.2.1 STREAM
    2001:db8::2 STREAM
  • 如果未生效,IPv6 地址会出现在解析结果的第一行。
  1. 使用系统的 getaddrinfo 调研

运行一下 python 脚本来验证 getaddrinfo 的行为:

1
2
3
4

import socket
print(socket.getaddrinfo('ip.sb', None))

  • 如果 /etc/gai.conf 的修改生效,IPv4 地址会优先出现在结果中。
  • 如果未生效,IPv6 地址会优先出现在结果中。

参考文档

linux 双网卡 ipv4 ipv6 双栈,linux ipv4 ipv6 双栈

作者

鹏叔

发布于

2025-07-22

更新于

2025-07-22

许可协议

评论