Featured image of post 使用 NETMAP 获得稳定的 IPv6 地址并进行源地址控制

使用 NETMAP 获得稳定的 IPv6 地址并进行源地址控制

IPv6 确实不需要 NAT,但是前缀翻译并非毫无用处

运营商分配的 IPv6 地址通常都不固定:

1
2
3
4
5
[admin@shanghai-router] > /ipv6/dhcp-client/print
Columns: INTERFACE, STATUS, REQUEST, PREFIX
# INTERFACE          STATUS  REQUEST  PREFIX
0 pppoe-chinanet     bound   prefix   240e:388:6501:XX00::/56, 40m57s
1 pppoe-chinamobile  bound   prefix   2409:8a1e:6a64:2XX0::/60, 2d20h10m

虽然在 PPPoE 存活期间地址不会变更,但是通常运营商的 BRAS 都有定时中断触发重连的机制,导致我们的 IPv6 地址发生变更。比较新的 RouterOS 版本中,DHCPv6 拿到的前缀失效后会让设备更新地址 lifetime 为 0 从而删除旧地址,是一个比较不错的解决方案。

然而在 RouterOS 上利用 BGP 全表优化多线互联网访问这篇文章中提到:

因为没有 NAT,设备也不能智能的选择用哪个前缀的 IP 地址,IPv6 的分流依然存在问题

所以,光有一个稳定的前缀还不够用,我们需要让设备的防火墙“智能”地将出方向的 IPv6 源地址更新成我们想要他使用的源地址,才能让多 ISP 优化达到最佳效果。为了达成这个目的,我们可以使用 netfilter 提供的 NETMAP 目标。


假设我们的路由器拥有以下前缀:

  1. 来自中国电信的:240e:388:6501:ab00::/56
  2. 来自中国移动的:2409:8a1e:6a64:2XX0::/60
  3. 来自自己宣告的:2602:feda:de0:700::/56

我们选择固定的地址和最小的前缀作为翻译的范围,也就是 2602:feda:de0:700::/60

Notice

如果你没有自己的前缀,也可以用 IPv6 ULA 地址来配置 IPv6 SLAAC,例如 fd34:38a:f295:a00::/64

针对从 pppoe-chinanet 接口出去的,源地址为 2602:feda:de0:700::/60 的连接,使用防火墙将源地址映射到 240e:388:6501:ab00::/60 内(也就是中国电信的地址):

1
/ipv6/firewall/nat add chain=srcnat out-interface=pppoe-chinanet src-address=2602:feda:de0:700::/60 action=netmap to-address=240e:388:6501:ab00::/60

当然数据不能只管出不管进,否则外侧服务的响应回到路由器之后,路由器发现没有直接相邻且使用 240e:388:6501:ab00::/60 这个前缀的地址。使用如下规则来处理回程流量:

1
/ipv6/firewall/nat add chain=dstnat in-interface=pppoe-chinanet dst-address=240e:388:6501:ab00::/60 action=netmap to-address=2602:feda:de0:700::/60

同理可以编写如下规则用于移动的出口:

1
2
3
/ipv6/firewall/nat
add chain=srcnat out-interface=pppoe-chinamobile src-address=2602:feda:de0:700::/60 action=netmap to-address=2409:8a1e:6a64:2XX0::/60
add chain=dstnat in-interface=pppoe-chinamobile dst-address=2409:8a1e:6a64:2XX0::/60 action=netmap to-address=2602:feda:de0:700::/60

随后我们优化一下 BGP 全表的 v6 过滤器:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
if (dst-len > 0 && bgp-as-path [[:china_asn_list:]]$) {
    if (bgp-as-path 4134$|4812$) {
      set gw %pppoe-chinanet;
    } else {
      set gw %pppoe-chinamobile;
    }
  set distance -5;
  accept;
} else {
  reject;
}

最后我们还需要在对应的 DHCPv6 配置上增加一个更新脚本用于更新防火墙规则,以移动的为例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
:log info ("dhcpv6 up script started");

:local  [/ipv6/pool/get [find name="ipv6-chinamobile-pd"] prefix];
:log info "prefix assigned by China Mobile is: $china_mobile_prefix";
:local china_mobile_new_prefix [:pick "$china_mobile_prefix" 0 ([:len "$china_mobile_prefix"] - 3)]

/ipv6/firewall/nat/set dst-address="$china_mobile_new_prefix/60" [find chain=dstnat action=netmap in-interface="pppoe-chinamobile"];
/ipv6/firewall/nat/set to-address="$china_mobile_new_prefix/60" [find chain=srcnat action=netmap out-interface="pppoe-chinamobile"];

:log info "netmap update okay";

这样就完成了!


我们可以挑一个 IPv6 地址作为目标试一试 traceroute:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
ntzyz@nas-v2 ~ % curl ipv6.ip.sb
2406:4440:10:<redacted>
ntzyz@nas-v2 ~ % mtr 240e:f7:e01f:f1::30 --report -z
Start: 2023-08-18T13:58:52+0800
HOST: nas-v2                      Loss%   Snt   Last   Avg  Best  Wrst StDev
  1. AS142641 <redacted>           0.0%    10    0.3   0.4   0.3   0.4   0.0
  2. AS24400  2409:801e:f0:1::2fb 10.0%    10    4.3   4.9   3.9  10.5   2.1
  3. AS24400  2409:801e:f0:1::2fa  0.0%    10    4.2   4.3   3.9   5.2   0.4
  4. AS9808   2409:8080:0:2:206:2  0.0%    10    4.7   4.7   4.5   4.8   0.1
  5. AS9808   2409:8080:0:1:206:1  0.0%    10   21.8  16.4   7.9  25.4   6.6
  6. AS9808   2409:8080:0:1:1106: 70.0%    10   10.2  10.2  10.2  10.3   0.0
  7. AS9808   2409:8080:0:3:11e2:  0.0%    10   13.8  13.7  13.1  14.0   0.2
  8. AS4134   240e::c:b:5100:302   0.0%    10    8.5   8.5   8.1   8.7   0.2
  9. AS136190 240e:1c:b111:1fff:: 10.0%    10   12.2  15.3  11.1  43.4  10.5
 10. AS136190 240e:1c:b112:1122::  0.0%    10   11.9  11.9  11.8  12.0   0.1
 11. AS136190 240e:f7:e01f:ff::11  0.0%    10   13.0  14.7  12.6  27.2   4.5
 12. AS136190 240e:f7:e01f:f1::30  0.0%    10   10.6  11.5  10.6  11.8   0.3

可以看到,这台 NAS 访问 cloudflare 时使用的自己的前缀,访问国内的地址时实际上使用的是中国电信的前缀。

comments powered by Disqus
Except where otherwise noted, content on this blog is licensed under CC-BY 2.0.
Built with Hugo
主题 StackJimmy 设计