针对常见的单 IPv4 地址加 IPv6 /64 子网的场景,组建 IPv4 内网,手动配置端口映射,与 Docker 的方案类似。而 IPv6 单独分配到每个虚拟机,便于某些需要独立 IP 的场景。

主机配置

假设以下配置是在单独安装 Linux 系统时的:

  1. IPv4:123.45.67.89/24,网关:123.45.67.1
  2. IPv6:240e:ab:cd:ef::/64,网关:fe80::1

而安装了 Proxmox VE 后有这样两个网络接口:

  1. 物理网口:ens6
  2. Linux 网桥: vmbr0

开启转发和代理

接下来直接在 PVE 的 Shell 中操作,修改 /etc/sysctl.conf

net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
net.ipv6.conf.ens6.proxy_ndp=1

第一条和第二条分别开启 IPv4 和 IPv6 转发,第三条开启 IPv6 的 NDP 代理,注意将 ens6 修改为你自己接口的名字。

配置网络接口

修改 /etc/network/interfaces

auto lo
iface lo inet loopback

auto ens6
iface ens6 inet static
        address 123.45.67.89/24
        gateway 123.45.67.1

iface ens6 inet6 static
        address 240e:ab:cd:ef::1/128
        gateway fe80::1

iface vmbr0 inet static
        address 10.0.0.1/24
        bridge-ports none
        bridge-stp off
        bridge-fd 0

iface vmbr0 inet6 static
        address 240e:ab:cd:ef::2/64

        post-up   iptables -t nat -A POSTROUTING -s '10.0.0.0/24' -o ens6 -j MASQUERADE
        post-down iptables -t nat -D POSTROUTING -s '10.0.0.0/24' -o ens6 -j MASQUERADE
        post-up   iptables -t raw -I PREROUTING -i fwbr+ -j CT --zone 1
        post-down iptables -t raw -D PREROUTING -i fwbr+ -j CT --zone 1

注意将所有 ens6 改为你自己的接口名。到这一步已经完成了 IPv4 NAT,但是 IPv6 还需要一点配置,见下文。

创建虚拟机

创建时将虚拟机的网口桥接到 vmbr0,同时需要手动配置静态 IPv4:

  • IPv4/CIDR:10.0.0.2/24
  • 网关(IPv4):10.0.0.1

IPv4/CIDR 不同虚拟机保持与网关和其他虚拟机不同,可以是 10.0.0.2-10.0.0.254。同样,需要手动配置静态 IPv6:

  • IPv6/CIDR:240e:ab:cd:ef::3/64
  • 网关(IPv6):240e:ab:cd:ef::2

与 IPv4 的要求相同,不要与网关和其他虚拟机相同。另外,IPv6 还需要另外一点工作。

NDP 处理

邻居发现协议(Neighbor Discovery Protocol),简称 NDP,类似与 IPv4 中的 ARP 协议。由于我们的 ens6 物理接口仅使用了 240e:ab:cd:ef::1/128 这一个地址,因此其只会对上级路由器响应这一个地址的 NDP 包。这样上级路由就仅有这一个地址的路由,对于 /64 子网中的地址并不会默认路由到我们的主机。

为此需要让 ens6 响应我们虚拟机 240e:ab:cd:ef::3/128 地址的 NDP 包,这就需要用到 NDP 代理。之前我们仅仅开启了内核的支持,还需要另外配置配置,有两种方案。

手动增加 NDP 代理

这个方案的好处是不需要额外安装其他软件,利用系统自带的 ip 即可,我们在 /etc/network/interfaces 末尾加入:

post-up   ip neigh add proxy 240e:ab:cd:ef::3 dev ens6
pre-down  ip neigh del proxy 240e:ab:cd:ef::3 dev ens6

每一个虚拟机都要添加两条,对应虚拟机的 IPv6 地址。让 ens6 接口代理响应 NDP 包。

使用 NDPPD

每个虚拟机添加一次,对于少量虚拟机还好,对于大量的虚拟机可以使用 NDPPD 软件,安装:

apt install ndppd

修改配置文件 /etc/ndppd.conf

proxy ens6 {
  rule 240e:ab:cd:ef::/64 {
    static
  }
}

保存重启后生效,这样 NDPPD 会自动代理整个 /64 子网,因此也就不需要每个虚拟机手动添加了。

IPv4 端口转发

最后是端口转发,假设要将虚拟机 10.0.0.2 的 80 端口映射到 123.45.67.89 的 80 端口,/etc/network/interfaces 末尾加入:

post-up   iptables -t nat -I PREROUTING -p tcp -i ens6 --dport 80 -j DNAT --to 10.0.0.2:80
post-down iptables -t nat -D PREROUTING -p tcp -i ens6 --dport 80 -j DNAT --to 10.0.0.2:80

如果是范围端口 8000-9000,末尾加入:

post-up   iptables -t nat -I PREROUTING -p tcp -i ens6 --dport 8000:9000 -j DNAT --to 10.0.0.2:8000-9000
post-down iptables -t nat -D PREROUTING -p tcp -i ens6 --dport 8000:9000 -j DNAT --to 10.0.0.2:8000-9000

注意将 ens6 接口换成你自己的。