Skip to main content

Linux 在 IPv6+IPv4 双栈下优先使用 IPv4

最近服务器引入了 IPv6 ,但是就出现了一个问题:

如果访问的域名同时拥有 A 和 AAAA 解析,那么 Linux 系统会优先使用 AAAA 解析,也就是 IPv6 地址,同时网络出口的优先级都会比 IPv4 高。

而且还有更牛的,IPv6+IPv4 双栈下,DNS查询会同时发送 AAAA 和 A 解析,无论访问域名有没有 AAAA 解析都会浪费一定时间去查询。

但是现在 IPv6 网络还不理想

举一个栗子

wget https://papermc.io/api/v1/paper/1.15.2/385/download
--2020-08-14 00:21:05--  https://papermc.io/api/v1/paper/1.15.2/385/download
正在解析主机 papermc.io (papermc.io)... 2606:4700:20::ac43:4580, 2606:4700:20::681a:202, 2606:4700:20::681a:302, ...
正在连接 papermc.io (papermc.io)|2606:4700:20::ac43:4580|:443... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:44783881 (43M) [application/java-archive]
正在保存至: “download”

 2% [=>                                                                             ] 1,317,487   9.59KB/s 剩余 35m 23s
wget https://papermc.io/api/v1/paper/1.15.2/385/download
--2020-08-14 00:26:40--  https://papermc.io/api/v1/paper/1.15.2/385/download
正在解析主机 papermc.io (papermc.io)... 172.67.69.128, 104.26.3.2, 104.26.2.2, ...
正在连接 papermc.io (papermc.io)|172.67.69.128|:443... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:44783881 (43M) [application/java-archive]
正在保存至: “download”

 1% [                                                                               ] 466,050      105KB/s 剩余 6m 51s

 

结果很 amazing 啊 ,这 IPv4 不知道快到那里去了。

 

好,说正事

优先 IPV4 非常简单

只要在 /etc/gai.conf 文件里面添加一行(这个文件默认不存在,手动生成吧)

precedence  ::ffff:0:0/96  100

保存就立即生效了

 

那么这行代码意味着什么呢

/etc/gai.conf 是干嘛的?   
Man 的说明:系统调用 getaddrinfo(3) 函数时可能返回会多个答案。根据 RFC 3484 ,系统必须对这些答案进行排序,来让成功率最高的地址优先级最高。RFC 还要求系统管理员可以动态修改优先级,这就是修改优先级的文件。
人话:系统解析域名获取 IP 地址的时候可能会获取到多个地址,这个文件允许你修改使用优先级。

 

/etc/gai.conf 这个文件默认里面写了 (我知道你的是刚创建的,但里面什么都没写也等于写了下面的内容)

label  ::1/128       0
label  ::/0          1
label  2002::/16     2
label ::/96          3
label ::ffff:0:0/96  4
precedence  ::1/128       50
precedence  ::/0          40
precedence  2002::/16     30
precedence ::/96          20
precedence ::ffff:0:0/96  10

这些是什么地址?看下表:

IPv6 默认地址选择

前缀 优先级 标签 用途/描述
::1/128 50 0 本地主机
::/0 40 1 默认单播
::ffff:0:0/96 35 4 IPv4 映射的 IPv6 地址(用 IPv6 地址代表的所有 IPv4 地址)
2002::/16 30 2 用于 6to4 隧道的地址 (现已废弃)
2001::/32 5 5 隧道地址
fc00::/7 3 13 唯一的本地地址
::/96 1 3 兼容 IPv4 的地址(已废弃)
fec0::/10 1 11 站点本地地址(已废弃)
3ffe::/16 1 12 6bone网络(returned)

因此 precedence ::ffff:0:0/96 100 意味着把所有 IPv4 地址的优先级调为 100

 

别说我优先级 100 是乱改熬,这是 RFC3484 说的:https://www.ietf.org/rfc/rfc3484.txt

10.3. Configuring Preference for IPv6 or IPv4

   The default policy table gives IPv6 addresses higher precedence than
   IPv4 addresses.  This means that applications will use IPv6 in
   preference to IPv4 when the two are equally suitable.  An
   administrator can change the policy table to prefer IPv4 addresses by
   giving the ::ffff:0.0.0.0/96 prefix a higher precedence:

      Prefix        Precedence Label
      ::1/128               50     0
      ::/0                  40     1
      2002::/16             30     2
      ::/96                 20     3
      ::ffff:0:0/96        100     4

   This change to the default policy table produces the following
   behavior:

   Candidate Source Addresses: 2001::2 or fe80::1 or 169.254.13.78
   Destination Address List: 2001::1 or 131.107.65.121
   Unchanged Result: 2001::1 (src 2001::2) then 131.107.65.121 (src
   169.254.13.78) (prefer matching scope)

   Candidate Source Addresses: fe80::1 or 131.107.65.117
   Destination Address List: 2001::1 or 131.107.65.121
   Unchanged Result: 131.107.65.121 (src 131.107.65.117) then 2001::1
   (src fe80::1) (prefer matching scope)



Draves                      Standards Track                    [Page 18]

RFC 3484           Default Address Selection for IPv6      February 2003


   Candidate Source Addresses: 2001::2 or fe80::1 or 10.1.2.4
   Destination Address List: 2001::1 or 10.1.2.3
   New Result: 10.1.2.3 (src 10.1.2.4) then 2001::1 (src 2001::2)
   (prefer higher precedence)