本文解决的问题是:如何在不改变现有网络拓扑的情况下,让位于多个不同vlan内网的客户机都用上IPv6,也就是网关设备需要获取ipv6 地址并通过前缀委派的方式获取一组ipv6子网,并将获取到的ipv6地址通过三层交换机的多个vlan接口,分别下发到内网每个vlan的每个设备上。
DHCPv6 Prefix Delegation ,简写为 PD,在本文中翻译为前缀委派,也有翻译为前缀委托、前缀授权等。
本文针对传统企业的常见网络架构模型:企业内部是由三层交换机统治的多个vlan组成的 多个ipv4 子网的内网,出口通过一台或者若干台网关设备(随手搜的图中EG),NAT模式转换为公网ipv4 地址,通过固定ip或 PPPoE接入线路连接因特网。
一般传统企业的常见网络架构工作模式可以用下述场景描述:
传统的一条固定ip或 PPPoE接入线路只给eth、vlan、dialer0、ppp0 或者 tun0等等设备与ISP直接对接的设备接口提供了ipv4 地址,即使大多网关设备已经有能力支持获取ipv6 地址,也无法将ipv6 地址传播到内网中去。
本文参考了前人的技术文档,相关链接如下:
在PPPoE拨号宽带上实现基于前缀委派(PD)的IPv6(Cisco路由器)
在PPPoE拨号环境下实现基于前缀委派(PD)的IPv6(H3C设备)
上文是在没有三层交换机的环境下,仅用一台路由器实现让内网的客户机也用上IPv6。
该实现的缺陷是,对稍大型的、带有三层交换机的企业网络需要改变网络拓扑,造成ipv6是在路由器内直通isp的,从而破环原有的安全防护通道(如防火墙、三层交换机acl等过滤手段),我们希望不改变网络拓扑,保留原网络的安全防护措施,于是有了本文的创作思路。
ISP一般提供了一个光猫,当前几乎所有的运营商光猫(电信、联通、移动)默认都是路由模式的,这里需要联系运营商更改为桥接模式,电信可以直接打10000更改,同时需要从ISP获得PPPoE账号和密码。
出口网关设备此处使用了FreeBSD路由器,这也是很多软路由的实现平台。具体用啥系统都可以,此处也可以用开源Linux 如Ubuntu,案例主要是解决工作原理,具体实现可以多样。
FreeBSD 路由器在此有三大功能:
利用FreeBSD路由器实现最基础的出口 ipv4 pppoe 网关不是很复杂,处理 IPv4 的 NAT技术也很老了,所以1、2、3就不多赘述。
需要详细描述的是FreeBSD 路由器上的 IPv6 前缀委派,该技术在FreeBSD平台成型于2004年,但那时国内互联网都还在启动阶段,大家都在研究如何赚钱,没人关注基础技术研发。直到如今我才了解到,原来别人家的操作系统上的ipv6实现在20年前就已经成型了。
uname -a
FreeBSD 13.1-RELEASE-p6 FreeBSD 13.1-RELEASE-p6 GENERIC amd64
pkg info | grep dhcp6
dhcp6-20080615.2_3 KAME DHCP6 client, server, and relay
为实现上述三大功能,FreeBSD 路由器必须具有两个或以上千兆网口。但其实并不严格要求,如对接入带宽无感,仅验证技术的话,也可以用单臂路由配置多个vlan接口实现。
本文实验环境使用vmware esxi 虚拟机,单臂路由配置多个vlan接口实现。
本文实验环境实测点在浙江,三家(电信、联通、移动)都测试成功获取了/60前缀。
示例中的网络接口名称由/etc/rc.conf 创建,约定如下:
vlan1072 是wan接口,对接ISP提供的光猫。此处配了192.168.1.227 是为了进光猫的web设置。
lagg0.36是 lan 接口,对接内部网络的三层交换机192.168.36.227是与三层交换机互联地址。
tun0 是pppoe 拨号虚接口,由/etc/rc.conf 创建,由/etc/ppp/ppp.conf 指定对接vlan1072。
/etc/rc.conf 添加如下配置(ipv4相关设置省略):
ifconfig_vmx0="up"
cloned_interfaces="lagg0 vlan1072 tun0"
ifconfig_lagg0="laggproto failover laggport vmx0 laggport em0"
vlans_lagg0="36"
#ifconfig_lagg0_36="192.168.36.227/24"
ifconfig_vlan1072="inet 192.168.1.227/24 vlan 1072 vlandev lagg0"
ppp_enable="YES"
ppp_mode="ddial"
ppp_profile="cuc"
ipv6_cpe_wanif="tun0"
ipv6_activate_all_interfaces="YES"
ipv6_gateway_enable="YES"
rtadvd_enable="YES"
rtadvd_interfaces="lagg0.36"
ifconfig_tun0_ipv6="inet6 accept_rtadv up"
ifconfig_lagg0.36_ipv6="inet6 -accept_rtadv up"
dhcp6c_enable="YES"
dhcp6c_interfaces="tun0"
编辑/etc/ppp/ppp.conf:
#CUC_1G_Down_100M_Up_PPPoE_0571012345678_123456
cuc:
set device PPPoE:vlan1072 # replace xl1 with your Ethernet device
set authname 0571012345678
set authkey 123456
set dial
set login
add default HISADDR
请自行修改上面的device PPPoE:vlan1072、authname 0571012345678、authkey 123456。
cuc: 与/etc/rc.conf 中的ppp_profile="cuc"对应。
重要:必备步骤。
dhcp6c 是向 ISP 请求前缀委派所必需的。
注意dhcp6c 不在 wan 接口上设置ipv6 地址,wan 口上ipv6 地址由pppoe 设置。
与路由器的 IPv6 通信是通过链路本地地址linklocal完成的。
使用 pkg 安装 KAME dhcp6c 客户端(或从ports 中的net/dhcp6 ):
pkg install -y dhcp6
修改 /usr/local/etc/dhcp6c.conf:
interface tun0 {
#从ISP WAN 接口 向 ISP 申请前缀委派
send ia-pd 0;
request domain-name-servers;
};
id-assoc pd 0 {
prefix-interface lagg0.36 {
#申请到的前缀绑定到lan口= langg0.36
sla-len 0;
#sla-len 申请到的前缀删除位数。
#如果ISP默认会将/60委派给我,如果我想获得/64,就从中删除4位。如 sla-len 4(声明删除的位数)。
#如果ISP默认会将/56委派给我,如果我想获得/64,就从中删除8位。如 sla-len 8(声明删除的位数)。
#先用0测试ISP默认委派的位数。实际使用需要计算到/64,实测国内三家运营商在浙江都用4
sla-id 1;
#测试阶段sla-len 0;时,sla-id 1;
#实际使用阶段,sla-len 4;时,sla-id 0;
};
};
如果一切正常,FreeBSD 将获得对应接口的ipv6地址,输入命令
ifconfig tun0
ifconfig lagg0.36 以检测对应的ip获取情况。
并且默认会自动将sysctl net.inet6.ip6.rfc6204w3更改为1,输入命令
net.inet6.ip6.rfc6204w3 确认对应的sysctl 变量情况。
[root@CUC227_PPPoE_1G_100M_up] ~# ifconfig tun0
tun0: flags=8051 metric 0 mtu 1492
options=80000
inet6 fe80::250:569f:33ac:7385%tun0 prefixlen 64 scopeid 0x6
inet6 2408:8240:5201:76e:250:569f:33ac:7385 prefixlen 64 autoconf
inet 172.19.200.223 --> 172.19.200.1 netmask 0xffffffff
groups: tun
nd6 options=3
Opened by PID 1025
[root@CUC227_PPPoE_1G_100M_up] ~# ifconfig lagg0.36
lagg0.36: flags=8843 metric 0 mtu 1500
options=4000002
ether 00:50:56:ac:73:85
inet6 2408:8240:5210:af70:250:56ff:feac:7385 prefixlen 60
groups: vlan
vlan: 36 vlanproto: 802.1q vlanpcp: 0 parent interface: lagg0
media: Ethernet autoselect
status: active
nd6 options=41
[root@CUC227_PPPoE_1G_100M_up] ~# sysctl net.inet6.ip6.rfc6204w3
net.inet6.ip6.rfc6204w3: 1
从上图可见,ISP给我方委派授权的ip地址已经绑定到lagg0.36,
其ip为2408:8240:5210:af70:250:56ff:feac:7385
前缀为:2408:8240:5210:af70 prefixlen 是/60,所以切分后,我方共有16个/64的ipv6 前缀可供分配,具体为2408:8240:5210:af70-2408:8240:5210:af7e,因为0已经被lagg0.36用掉,所以还有15个/64ipv6 前缀可供分配给其他vlan,就是2408:8240:5210:af70 ,因为是16进制数,最后一位可以是1-e/64。
此处案例为一台华为S5720 三层交换机。参考链接:
FAQ-S5700 IPV6 DHCP SERVER配置- 华为
下面案例我选定了16进制数的最后一位e ,2408:8240:5210:af7e 这个/64前缀分配给vlan15,
将华为交换机的vlan 15,vlan 36 的三层接口ipv6 地址配置为每个段的第一个地址(将会自动充当ipv6路由接口);
dhcp6 server 分配时排除前10个地址避免冲突。
配置如下:
#
ipv6
#
dhcp enable
#
dhcpv6 pool vlan15
address prefix 2408:8240:5210:AF7E::/64
excluded-address 2408:8240:5210:AF7E::1 to 2408:8240:5210:AF7E::10
dns-server 2408:8888::8
dns-server 2408:8899::8
dns-domain-name mycompany.com
#
dhcpv6 pool vlan36
address prefix 2408:8240:5210:AF70::/64
excluded-address 2408:8240:5210:AF70::1 to 2408:8240:5210:AF70::10
dns-server 2408:8888::8
dns-server 2408:8899::8
dns-domain-name mycompany.local
#
interface Vlanif15
ipv6 enable
ipv6 address 2408:8240:5210:AF7E::1/64
ipv6 mtu 1432
undo ipv6 nd ra halt
ipv6 nd autoconfig managed-address-flag
ipv6 nd autoconfig other-flag
dhcpv6 server vlan15
#
interface Vlanif36
ipv6 enable
ipv6 address 2408:8240:5210:AF70::1/64
ipv6 address auto link-local
ipv6 mtu 1432
undo ipv6 nd ra halt
ipv6 nd autoconfig managed-address-flag
ipv6 nd autoconfig other-flag
dhcpv6 server vlan36
#
上面vlan36 是互联接口,所以我们还需要:
在华为交换机上添加默认互联接口的ip为ipv6 默认出口网关:
ipv6 route-static :: 0 2408:8240:5210:AF70:250:56FF:FEAC:7385
在FreeBSD 上对应添加对应的ipv6子网为回程路由(指向华为交换机的vlan 36 的三层接口ipv6 地址 2408:8240:5210:af70::1)
route add -6 2408:8240:5210:af70::1/60 2408:8240:5210:af70::1
【huawei]]ping ipv6 -a 2408:8240:5210:AF70::1 2408:8240:5210:AF70:250:56FF:FEAC:7385
PING 2408:8240:5210:AF70:250:56FF:FEAC:7385 : 56 data bytes, press CTRL_C to break
Reply from 2408:8240:5210:AF70:250:56FF:FEAC:7385
bytes=56 Sequence=1 hop limit=64 time = 1 ms
Reply from 2408:8240:5210:AF70:250:56FF:FEAC:7385
bytes=56 Sequence=2 hop limit=64 time = 2 ms
Reply from 2408:8240:5210:AF70:250:56FF:FEAC:7385
bytes=56 Sequence=3 hop limit=64 time = 1 ms
Reply from 2408:8240:5210:AF70:250:56FF:FEAC:7385
bytes=56 Sequence=4 hop limit=64 time = 1 ms
Reply from 2408:8240:5210:AF70:250:56FF:FEAC:7385
bytes=56 Sequence=5 hop limit=64 time = 2 ms
--- 2408:8240:5210:AF70:250:56FF:FEAC:7385 ping statistics ---
5 packet(s) transmitted
5 packet(s) received
0.00% packet loss
round-trip min/avg/max = 1/1/2 ms
【Huawei】ping ipv6 -a 2408:8240:5210:AF70::1 2408:8888::8
PING 2408:8888::8 : 56 data bytes, press CTRL_C to break
Reply from 2408:8888::8
bytes=56 Sequence=1 hop limit=60 time = 5 ms
Reply from 2408:8888::8
bytes=56 Sequence=2 hop limit=60 time = 5 ms
Reply from 2408:8888::8
bytes=56 Sequence=3 hop limit=60 time = 4 ms
Reply from 2408:8888::8
bytes=56 Sequence=4 hop limit=60 time = 5 ms
Reply from 2408:8888::8
bytes=56 Sequence=5 hop limit=60 time = 5 ms
--- 2408:8888::8 ping statistics ---
5 packet(s) transmitted
5 packet(s) received
0.00% packet loss
round-trip min/avg/max = 4/4/5 ms
【huawei】ping ipv6 -a 2408:8240:5210:AF7e::1 2408:8888::8
PING 2408:8888::8 : 56 data bytes, press CTRL_C to break
Reply from 2408:8888::8
bytes=56 Sequence=1 hop limit=60 time = 6 ms
Reply from 2408:8888::8
bytes=56 Sequence=2 hop limit=60 time = 7 ms
Reply from 2408:8888::8
bytes=56 Sequence=3 hop limit=60 time = 11 ms
Reply from 2408:8888::8
bytes=56 Sequence=4 hop limit=60 time = 7 ms
Reply from 2408:8888::8
bytes=56 Sequence=5 hop limit=60 time = 7 ms
--- 2408:8888::8 ping statistics ---
5 packet(s) transmitted
5 packet(s) received
0.00% packet loss
round-trip min/avg/max = 6/7/11 ms
【CTC_PPPoE】 /usr/local/etc# ping 2408:8240:5210:AF7E::1
PING6(56=40+8+8 bytes) 240e:390:5272:e40a:250:56ff:feac:1375 --> 2408:8240:5210:af7e::1
16 bytes from 2408:8240:5210:af7e::1, icmp_seq=0 hlim=55 time=11.027 ms
16 bytes from 2408:8240:5210:af7e::1, icmp_seq=1 hlim=55 time=11.004 ms
16 bytes from 2408:8240:5210:af7e::1, icmp_seq=2 hlim=55 time=11.283 ms
16 bytes from 2408:8240:5210:af7e::1, icmp_seq=3 hlim=55 time=10.867 ms
16 bytes from 2408:8240:5210:af7e::1, icmp_seq=4 hlim=55 time=11.027 ms
16 bytes from 2408:8240:5210:af7e::1, icmp_seq=5 hlim=55 time=10.922 ms
16 bytes from 2408:8240:5210:af7e::1, icmp_seq=6 hlim=55 time=11.325 ms
^C
--- 2408:8240:5210:AF7E::1 ping6 statistics ---
7 packets transmitted, 7 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 10.867/11.065/11.325/0.161 ms
C:\Windows\system32>ipconfig /renew6
Windows IP 配置
以太网适配器 Ethernet0:
连接特定的 DNS 后缀 . . . . . . . : mycompany.com
IPv6 地址 . . . . . . . . . . . . : 2408:8240:5210:af7e::11
IPv6 地址 . . . . . . . . . . . . : 2408:8240:5210:af7e:4c2:47ab:757e:cd59
临时 IPv6 地址. . . . . . . . . . : 2408:8240:5210:af7e:61f1:4f8a:e2b6:16cf
本地链接 IPv6 地址. . . . . . . . : fe80::4c2:47ab:757e:cd59%4
自动配置 IPv4 地址 . . . . . . . : 169.254.205.89
子网掩码 . . . . . . . . . . . . : 255.255.0.0
默认网关. . . . . . . . . . . . . : fe80::3abc:1ff:feb2:4d48%4
C:\Windows\system32>ping 2408:8899::8
正在 Ping 2408:8899::8 具有 32 字节的数据:
来自 2408:8899::8 的回复: 时间=8ms
来自 2408:8899::8 的回复: 时间=8ms
来自 2408:8899::8 的回复: 时间=8ms
来自 2408:8899::8 的回复: 时间=8ms
2408:8899::8 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 8ms,最长 = 8ms,平均 = 8ms
# ping 2408:8240:5210:AF7E::11
PING6(56=40+8+8 bytes) 240e:390:1272:e40a:250:56ff:feac:1375 --> 2408:8240:5210:af7e::11
16 bytes from 2408:8240:5210:af7e::11, icmp_seq=0 hlim=54 time=13.525 ms
16 bytes from 2408:8240:5210:af7e::11, icmp_seq=1 hlim=54 time=13.502 ms
16 bytes from 2408:8240:5210:af7e::11, icmp_seq=2 hlim=54 time=13.849 ms
16 bytes from 2408:8240:5210:af7e::11, icmp_seq=3 hlim=54 time=13.555 ms
16 bytes from 2408:8240:5210:af7e::11, icmp_seq=4 hlim=54 time=13.679 ms
--- 2408:8240:5210:AF7E::11 ping6 statistics ---
5 packets transmitted, 5 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 13.439/13.636/13.903/0.167 ms
国内运营商都只给/60的委派授权,最多只能拆成16个/64的子网,去除互联的一个,实际只能供15个vlan分配地址。生产环境最好能申请更大委派授权,比如/56
因为是PPPoE动态地址,每次断电、重启、PPPoE超时重拨号(每家运营商都会在一定周期断开重拨,一般是24小时的整数倍)都会导致三层交换机配置的ipv6地址失效。我目前的想法是检测到ipv6地址变化时,自行撰写bash expect脚本命令行登录交换机,使用命令行盲交互的方式自动修改对应的ipv6设置。生产环境最好能申请固定ipv6子网委派授权。
三层交换机默认的ipv6地址租约是3天,对动态地址的情况不友好,建议改短,并人为将PPPoE 重拨时间优化到午夜,以便各PC、移动终端在第二天获取到新的、具有较长有效期(不会在使用时突然因ipv6地址变更而中断)的ipv6地址。
ipv6 dns 优先级会比ipv4 dns 优先级高,如果企业内部有ipv4 dns server,为降低内网应用响应时间不影响业务,也需要创建一个具有ipv6 aaaa 记录的内部 ipv6 dns server 替换掉案例中的2408:8888::8
注:本文范例的所有ipv6 地址均已修改以掩藏真实地址。
附:全国运营商DNS服务器IPv4&IPv6地址记录
附:IPV6 DHCPv6-PD 前缀子网拆解