最近这段时间一直在折腾 10G 内网,先是买了 HPE 的 MicroServer Gen10 Plus 来做 NAS,之后又买了威联通的交换机 QSW-M2108R-2C。路由器则选用的是 Mikrotik 的 hEX S (RB760iGS),而之前作为主力使用的 AX88U 变成了专职 AP。

把它们堆在一起就是下面这个样子:

网络设备们

废话不多说,直接进入正题。

配置 DHCPv6-PD 客户端

启用 DHCPv6 客户端

登入 RouterOS 终端,输入以下命令启用 DHCPv6 客户端:

# 接受来自 ISP 的路由器通告 (RA),以通过 SLAAC 获取 IPv6 WAN 地址
/ipv6 settings set accept-router-advertisements=yes
# DHCPv6 客户端配置:
# - 添加默认路由: yes
# - WAN 端口: ether1
# - IPv6 地址池名称: delegation(可以随意起名,之后的命令里对应修改)
# - IPv6 地址池前缀长度:60(这是关键,下文会解释)
# - IPv6 前缀提示: 56(和 ISP 挂钩,根据实际情况修改)
# - IPv6 请求:WAN 地址和 LAN 前缀
/ipv6 dhcp-client add add-default-route=yes interface=ether1   \
  pool-name=delegation pool-prefix-length=60 prefix-hint=::/56 \
  request=address,prefix

IPv6 前缀提示取决于你的 ISP,以我的 ISP 为例,Charter Spectrum 提供 /56 的前缀,所以这里我使用的是 ::/56

要使 SLAAC(或者说无状态 DHCPv6)正常工作,你需要从 ISP 那拿到至少 /63 的前缀(这种情况下可以划分两个 /64 的子网)。如果 ISP 最多只给分配 /64 的前缀,那就和前缀代理无缘了 —— 能用的方案只有 NAT66NDPv6 代理

这条命令中的关键是 pool-prefix-length 参数:它决定了下文中 DHCPv6 服务器下发前缀的长度(或者说二级路由器拿到的前缀的长度)。

这里我设置的是 60,在 ISP 分配给我 /56 前缀的前提下,hEX S 可以划分出 16 个 /60 的前缀给二级路由器使用,二级路由器则可以提供另外 16 个 /64 的前缀给它们的设备使用。

运行 /ipv6 dhcp-client print/ipv6 pool print 来查看 ISP 分配的前缀:

[admin@MikroTik] > /ipv6 dhcp-client print
Flags: D - dynamic, X - disabled, I - invalid
 #    INTERFACE STATUS  REQUEST   PREFIX
 0    ether1    bound   address   2600:6c51:fake:n00b::/56, 4d22h24m10s
                        prefix
[admin@MikroTik] > /ipv6 pool print
Flags: D - dynamic 
 #   NAME       PREFIX                   PREFIX-LENGTH EXPIRES-AFTER
 0 D delegation 2600:6c51:fake:n00b::/56            60 4d22h23m52s

添加必要的 IPv6 防火墙规则

如果上面命令的 STATUS 一栏一直显示的是 searching,那么有可能是 IPv6 防火墙阻止了 UDP 端口 546 的连接入站。

运行下面的命令添加允许 UDP 546 入站的规则:

# 允许 DHCPv6 客户端尝试前缀代理
/ipv6 firewall filter add action=accept chain=input \
  comment="Accept DHCPv6 client prefix delegation"  \ 
  dst-port=546 protocol=udp src-address=fe80::/10

为 LAN 端口分配 IPv6 地址

最后一步是从 IPv6 地址池中为默认网桥分配 IPv6 地址:

# RouterOS 默认启用了 RA,这样下级设备才能通过 SLAAC 自动配置 IPv6 地址。
# (原因是 RouterOS 的 DHCPv6 目前暂不支持有状态 IPv6 地址分配)
# 如果有单独运行的有状态 DHCPv6 服务器,则应该在后面加上 `advertise=no`。
/ipv6 address add address=::1 from-pool=delegation interface=bridge

如果有多个网桥或端口,则需要对每个网桥和端口单独运行上面的命令。运行 /ipv6 address print 来查看分配到 LAN 端口的地址:

[admin@MikroTik] > /ipv6 address print
Flags: X - disabled, I - invalid, D - dynamic, G - global, L - link-local 
 #    ADDRESS                                 FROM-POOL  INTERFACE ADVERTISE
 0  G 2600:6c51:fake:n00b::1/64               delegation bridge    yes
 1 DL fe80::a55:31ff:fe00:fake/64                        bridge    no
 2 DL fe80::a55:31ff:fe00:fake/64                        ether1    no
 3 DG 2600:6c51:some:fake:addr:why:so:long/64            ether1    no

配置 DHCPv6-PD 服务器

注意 1:要使用 DHCPv6-PD 服务器,你需要从 ISP 那拿到至少 /63 的 IPv6 前缀。

注意 2: 为了能让二级路由器通过 DHCPv6-PD 拿到前缀,上一节 DHCPv6 客户端中的 pool-prefix-length 参数必须正确设置。

开始之前,先重申一下 Mikrotik 文档中的说明:

Note: RouterOS DHCPv6 server can only delegate IPv6 prefixes, not addresses.

Mikrotik Documentation — Manual:IPv6/DHCP Server

换句话说,RouterOS 的 DHCPv6 服务器目前只支持 SLAAC(无状态 DHCPv6)。

启用 DHCPv6 服务器

下面的命令用于创建 DHCPv6 服务器:

# 从地址池 `delegation` 中代理 IPv6 地址
# 租约有效期为 1 天
/ipv6 dhcp-server add address-pool=delegation \
  interface=bridge lease-time=1d name=default

如果有多个网桥或端口,则需要对每个网桥和端口单独运行上面的命令。

现在就可以运行 /ipv6 dhcp-server binding print 来检查二级路由器有没有拿到前缀:

[admin@MikroTik] > /ipv6 dhcp-server binding print
Flags: I - invalid, X - disabled, R - radius, D - dynamic 
 #    ADDRESS                   DUID            SERVER   STATUS
 0  D 2600:6c51:fake:n01b::/60  0xa85e45fakeid  default  bound  

如果看到类似上面的输出,那就说明 DHCPv6 服务器已经正常工作了。

配置 DHCPv6 选项

如果想通过 DHCPv6 下发诸如 DNS (Option 23) 和域搜索列表 (Option 24) 等选项,则需要先在 IPv6 ND 中启用 Other Configuration

/ipv6 nd set [ find default=yes ] other-configuration=yes

然后就可以设置 DHCPv6 选项了,这里我创建了 DNS 和域搜索列表两个选项:

/ipv6 dhcp-server option
# Option 23 (DNS): fd00::1
add code=23 name=dns value=0xfd000000000000000000000000000001
# Option 24 (域搜索列表): example.local
add code=24 name=domain-search value="0x07'example'0x05'local'0x00"

DNS (Option 23) 需要打上完整的 64 位十六进制 IPv6 地址,域搜索列表 (Option 24) 则可以使用这个工具生成:https://jjjordan.github.io/dhcp119/

我这里的 DNS 设置的是 fd00::1,这样不需要额外的脚本就能让 hEX S 作为内网的默认 DNS (否则的话需要使用脚本来获取公网 IPv6 地址)。

这个方法来源于 dksoft。不过对于我的应用场景而言,只需要一条命令:

# 为 `bridge` 分配 `fd00::1`,不启用 RA
/ipv6 address add address=fd00::1 advertise=no interface=bridge

这里没有启用 RA,因为不想也没必要让设备拿到 fd00::1/8 前缀的地址。

最后一步就是把这些选项添加到 DHCPv6 服务器上:

# 根据你的设置对应修改服务器名称和选项名称
/ipv6 dhcp-server set default dhcp-options=dns,domain-search

总结

RouterOS 的学习曲线还是有些陡峭的,但是一旦搞明白怎么回事,属实比在 AX88U 上做相同的事来的轻松的多(感觉在讲废话,毕竟 AX88U 是针对消费市场的)。

无论如何,相对于 AX88U 这种多合一的设备,确实是发现还是专事专做比较好,尤其是有那种特殊或者专业需求的时候。