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 |
|
效果等同于 curl ip.sb -6
1 |
|
如果你不想使用 IPv6 优先,可以在这个文件/etc/gai.conf(如果没有,可以手动创建它)中找到:
1 |
|
添加一行或取消注释,修改为:
1 |
|
作用解释:
::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 |
|
效果等同于 curl ip.sb -4
1 |
|
其他检验 Ipv4 是否生效的方法
- 使用 ping 测试
运行以下命令:
1 | ping ip.sb |
如果 /etc/gai.conf 的修改生效,ping 会优先解析 IPv4 地址。
如果未生效,ping 会解析 IPv6 地址。
- 使用
getent测试
运行以下命令:
1 | getent ahosts ip.sb |
getent ahosts会显示域名解析的结果。- 如果
/etc/gai.conf的修改生效,IPv4 地址会出现在解析结果的第一行,例如:1
2192.0.2.1 STREAM
2001:db8::2 STREAM - 如果未生效,IPv6 地址会出现在解析结果的第一行。
- 使用系统的 getaddrinfo 调研
运行一下 python 脚本来验证 getaddrinfo 的行为:
1 |
|
- 如果
/etc/gai.conf的修改生效,IPv4 地址会优先出现在结果中。 - 如果未生效,IPv6 地址会优先出现在结果中。
参考文档
Linux 上设置 IPv4 优先
https://pengtech.net/linux/linux-setup-ipv4-preferrence.html