Proxmox 默认配置中无法动态获取 IPv6 问题的原因分析和解决方案

此文章是对 PVE 主机及 LXC 容器开启 DHCPv6 客户端教程 的补充,本篇单独讲有状态 DHCPv6 的配置

在 Proxmox 系列系统(除了 Proxmox VE,还包括 Backup Server 和 Mail Gateway)的默认配置中,通常按照上方蓝字教程的方法配置好 sysctl 规则后,LXC 就能正常的、同时通过无状态和有状态两种方式获取 IPv6 地址。而宿主机可能会存在只有无状态地址,没有有状态地址的问题。

不想看原因分析,可以直接点击这里看解决方案。

有状态地址

在 IPv6 配置中,无状态(SLAAC)一般指的是路由器下放一个前缀,后缀由机器(客户端)配置;而有状态则是地址全部由路由器配置。大多数路由器同时开启有状态和无状态,客户端可以获得下面几个地址:

  • 2400:1234:5678:abcd:1145:14ff:fe19:1981
  • 2400:1234:5678:abcd::114
    其中 2400:1234:5678:abcd:: 是前缀,长度是 64 个二进制位(16 个十六进制位),前缀后面的部分则称为后缀。
    一般长得上面这样的,比较长的地址,都是通过 SLAAC 获取的,后缀一般会使用 MAC 生成(EUI-64 算法)或者完全随机,而下面这个短的,一般通过有状态 DHCPv6 获取。
    (当前,这只是大多数情况,SLAAC 的后缀完全由客户端决定,通过 SLAAC 获取的地址也可能很短;而有状态获取的后缀完全由路由器决定,通过有状态获取的地址也可能很长)

如果你的 PVE 只有类似上面那样比较长的地址,而 LXC 和其他设备均能获取两种不同的地址,那一般就是说明宿主机没有获取到有状态的 IPv6 地址。

明明其他设备都能正常获取,只有 PVE 宿主机(或者和几个少数 LXC)获取不到,为什么会这样呢?

ifupdown2

要想解释清楚这个问题,必须要扯几句 ifupdown2

ifupdown2 是 PVE 7.0 以来的默认网络管理器,主流发行版中只有 Proxmox 系默认使用。普通的 Debian 系统以及 PVE 老版本采用的是 ifupdown

ifupdown2 普遍被认为是更现代的网络管理器,由 NVIDIA 开发,使用 Python 语言编写,加入了热重载接口等高级功能,支持更多配置选项,并且兼容传统的 ifupdown 配置。

优点讲完了,就要讲它的缺点了。

ifupdown2 目前有三个大问题:

  • 不支持同一个接口混合静态地址和 DHCP 配置
  • 如果一个接口 DHCP 没有响应,会一直等待,阻塞继续开机
  • DHCPv6 租约会在关机或重启后自动移除

可以说是完全没认真去适配 DHCP 的网络环境。

Proxmox 系统无法获取有状态地址,一般就是由于上面提到的第一个问题————不支持同一个接口混合静态地址和 DHCP 配置

什么是“同一个接口混合静态地址和 DHCP 配置”?答:IPv4 使用静态地址,IPv6 使用自动获取。反过来也一样。

Proxmox 系统的 IPv4 地址默认就是静态配置的,此时如果你配置了 DHCPv6:这段配置是完全无效的,会被忽略,而且不产生任何报错信息。

1
2
3
4
iface vmbr0 inet manual
address 172.20.2.1/22
gateway 172.20.0.20
iface vmbr0 inet6 dhcp

对于 ifupdown2这是无效的配置!如果你按照上面的方法配置,最后只会获得静态的 IPv4 地址,IPv6 不可用。

1
2
3
4
iface vmbr0 inet6 dhcp
iface vmbr0 inet manual
address 172.20.2.1/22
gateway 172.20.0.20

这也是无效的配置,如果你按照这个方法配置,最后只会获得 DHCP 得到的 IPv6 地址,IPv4 不可用。

而如果你使用 ifupdown,上面两个配置都是有效的,而且作用相同。这算是个 ifupdown2 的大 Bug,而且开发者貌似目前完全不打算修复这个(技术上重写很麻烦,但是开发者接受 PR)。

软件有问题,就只能由用户处理了。这里提供两种解,推荐选择第一种。

post-up hooks

这是第一种解法:添加 post-up hooks。

1
2
3
4
iface vmbr0 inet manual
address 172.20.2.1/22
gateway 172.20.0.20
post-up dhclient -6 -v -pf /run/dhclient6.$IFACE.pid -lf /var/lib/dhclient6/$IFACE.leases -I $IFACE

照抄 post-up 这一行

ifupdown

这是第二种解法:切换到 ifupdown

不推荐。仅当完全不需要 ifupdown2 的功能时才使用此方法。安装 ifupdown 会自动卸载 ifupdown2

1
apt install ifupdown