OpenWrt 开启 IPv6 中继

最近换了个路由器,不过只能刷 OpenWrt 固件。我之前用的都是 Padavan,几乎可以一键配置 IPv6,加上有 IPv6 公网,非常方便我在外使用远程桌面。不过换成 OpenWrt 后,前后折腾了一个多星期,才搞定了 OpenWrt IPv6 中继。

这里稍微介绍一些 IPv6 基础知识,同时记录一下 OpenWrt 开启 IPv6 中继实现过程。

IPv6 基础知识

IPv6 地址规范

IPv6 地址的长度为 128 bits(2128),由八组 16 位字段组成,相邻字段用冒号分隔,如:

1
fddd:f00d:cafe:0000:0000:0000:0000:0001

每组的前导零可以省略,上面的地址可以写成这样:

1
fddd:f00d:cafe:0:0:0:0:1

可以用双冒号“::”表示一组 0 或多组连续的 0,但只能出现一次:

1
fddd:f00d:cafe::1

IPv6 地址范围

范围 含义
::1/128 Loopback/本机回环地(就是localhost,类似 127.0.0.1)
fe80::/10 Link-Local/链路本地地址(同交换机下的地址,不能转发到其他局域网,类似 169.254.0.0/16)
fc00::/7 Unique-Local/唯一区域地址(大局域网地址,不能转发到公网,类似 192.168.0.0/16)
2000::/3 Global-Unicast/全球单播(互联网地址,就是公网 IP)

现实中 Link-Local/链路本地地址 fe80::/10 被使用的只有 fe80::/64 这一段,只要你启用了 IPv6,网口会自动根据 MAC 地址 自动生成 IPv6 地址,和 IPv4 的 169.254.0.0/16 只在没有 DHCP 时才会生成的情况不一样。

IPv6 Global 子网划分

IPv6 地址子网按下图分配:

  • 0—48 位:站点前缀定义从网络到路由器的公共拓扑。企业的站点前缀可以从 ISP 或区域 Internet 注册机构 (Regional Internet Registry, RIR) 获取。
  • 48—64 位:子网 ID 定义网络的管理子网,它的最大长度为 16 位。可以在配置 IPv6 网络的过程中指定子网 ID。
  • 64—128 位:接口 ID 用来标识特定节点的接口。接口 ID 必须在子网内唯一。IPv6 主机可以使用相邻节点搜索协议自动生成其自身的接口 ID。相邻节点搜索协议基于主机接口的 MAC 地址或 EUI-64 地址自动生成接口 ID。也可以手动指定接口 ID,建议对 IPv6 路由器和启用了 IPv6 的服务器采用这种方式。
  • 子网前缀通过指定已分配了子网的特定链路来定义路由器的站点拓扑。

比如电信运营商购买了一个 2048:DEAD:BEEF::/48 网段,则最多可以划分 2^16 = 65536 个子网,分配给 65536 个用户使用。如果用户分配到了类似 2048:DEAD:BEEF:00XX::/56 地址,则可以进一步划分子网(2^8 = 256 个);如果用户分配到的是 2048:DEAD:BEEF:XXXX::/64 ,尽管还有 64 位的空间(64—128 位)剩下,也不能继续往下划分子网了。因为接口 ID 是为了分配接入设备保留的。

IPv6 分发方式

IPv6 有三种分发方式:

  1. Static:与 IPv4 一样,手动输入 IPv6 地址固定。

  2. SLAAC:StateLess Address Auto Configuration,SLAAC 设备向路由器发送网络前缀的请求,设备使用前缀和自己的 MAC 地址创建 IP 地址,并检查是否与子网内已有的 IP 重复。

  • 设备启动:当一个 IPv6 设备连接到网络时,它会生成一个链路本地地址(Link-Local)。
  • 发送RS报文:设备发送 RS 报文,询问网络中的路由器是否存在。
  • 接收RA报文:网络中的路由器响应 RS 报文,发送 RA 报文。RA 报文包含网络前缀、默认网关等信息。
  • 生成IPv6地址:设备根据 RA 报文中的前缀和自身的 MAC 地址生成一个全局唯一的 IPv6 地址。这个过程通常使用 EUI-64 格式。
  • 地址验证:设备通过发送邻居请求(NS)报文来验证生成的 IPv6 地址是否唯一。
  • 配置完成:如果地址验证通过,设备就可以使用这个 IPv6 地址进行通信。
  1. DHCPv6:Dynamic Host Configuration Protocol,IPv6 地址可以使用 IPv6 版本的 DHCP(DHCPv6)进行分配。
  • 如果主机希望通过 DHCPv6 获取 IPv6 地址,它会从 UDP 端口 546 向 DHCP 多播地址的端口 547 发送 DHCP 请求。DHCP 服务器随后会从 UDP 端口 547 向客户端 UDP 端口 546 回复 DHCP 通告。这个握手过程可以通过客户端发送 DHCP 请求和服务器(ff02::1:2)回复 DHCP 应答来完成。

OpenWrt 开启 IPv6 中继

先介绍一下我的网络环境:

  • 光猫拨号,直接连接在光猫下的设备能够正常获取公网 IPv6;
  • OpenWrt 路由器 WAN 口连接在光猫 LAN,作为二级路由,我日常设备都连接在 OpenWrt 下;
  • OpenWrt 能够正常获取到公网 IPv6,连接在 OpenWrt 下的设备无法获取公网 IPv6。

如果你也是类似情况,可以参照一下步骤操作:

  1. 通过 SSH 登录路由器(假设路由器地址为 192.168.20.1 ):
1
ssh root@192.168.20.1
  1. 查看 OpenWrt 是否正常获取 IPv6:
1
ifconfig

正常情况下,在 wan 下能找到“2”开头的 IPv6 Global 地址,类似:

1
inet6 addr: 240e::1111:1111:1111:1111/64 Scope:Global
  1. 用 VIM 编辑器打开配置文件 /etc/config/dhcp
1
vim /etc/config/dhcp

注:按“i”进入编辑模式,完成修改后,按“ESC”键,输入“:wq”,按回车保存。

  1. config dhcp lanconfig dhcp wan6 部分修改或新增以下内容:
1
2
3
4
5
6
7
8
9
10
11
12
config dhcp lan
option dhcpv6 relay
option ra relay
option ndp relay
...
 
config dhcp wan6
option dhcpv6 relay
option ra relay
option ndp relay
option master 1
option interface wan6

完成设置后,保存文件。

  1. 使设置生效,运行以下命令提交设置:
1
uci commit dhcp
  1. 设备重新连接 OpenWrt 后,应该就能正常获取 IPv6。Windows 系统可以在终端中输入:
1
ipconfig

在输出中能够找到“2”开头的 IPv6 地址。

  1. 浏览器打开 IP查询(ipw.cn) 测试,通常来说,这个时候 IPv6 测试通过。

如果设备在 6 中有 IPv6 地址,但在 7 中有测试不通过,可以尝试在 OpenWrt 后台管理页面:

  1. 网络 —> 接口 —> 全局网络选项 —> IPv6 ULA 前缀:清空

  2. 网络 —> DHCP/DNS —> 高级设置:

  • 过滤 IPv6 AAAA 记录:不选
  • 过滤 IPv4 A 记录:不选

然后保存,重启路由器。

如果还不能获取 IPv6,可以尝试

  1. 系统 —> 软件包 —> 过滤器输入:owipcalc —> 安装

  2. 通过 SSH 登录路由器(假设路由器地址为 192.168.20.1 ):

1
ssh root@192.168.20.1
  1. 编辑
1
vim /etc/hotplug.d/iface/80-reset-route6

输入以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#!/bin/sh  

wan_dev="wan6"

[ "$HOTPLUG_TYPE" = "iface" ] || exit 0
[ "$INTERFACE" = "$wan_dev" ] || exit 0

RTMETRIC=127

. /lib/functions/network.sh

network_get_physdev lan_dev lan || exit 0

ifup_cb() {
local _lan_dev="$1"
local _metric="$2"

local wan_subnet
network_get_subnet6 wan_subnet "$wan_dev" || return
_wan_network=$(owipcalc "${wan_subnet}" network)

ip -6 route replace "$_wan_network" dev "$_lan_dev" metric "$_metric"
}

ifdown_cb() {
local _lan_dev="$1"
local _metric="$2"

ip -6 route flush dev "$_lan_dev" metric "$_metric"
}

case "$ACTION" in
ifup)
ifup_cb "$lan_dev" "$RTMETRIC"
;;
ifdown)
ifdown_cb "$lan_dev" "$RTMETRIC"
;;
ifupdate)
ifdown_cb "$lan_dev" "$RTMETRIC"
sleep 1
ifup_cb "$lan_dev" "$RTMETRIC"
;;
*)
;;
esac

exit 0
  1. 并赋予赋予执行权限:
1
chmod +X /etc/hotplug.d/iface/80-reset-route6
  1. 同时在防火墙放行:
  • 网络 —> 防火墙 —> 通信规则 —> 新建转发规则
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
规则已启用

名字:Allow-IPv6

限制地址:仅 IPv6 

协议:TCP+UDP

匹配 ICMP 类型:any

源区域:wan

源 MAC 地址:所有

源地址:所有

源端口:所有

目标区域:任意区域 (转发)

目标地址:所有

目标端口:所有

动作:接受

然后保存,重启路由器。

References

  1. IPv6 Cheat Sheets

  2. IPv6 原理及如何设置 OpenWrt

  3. IPv6 Subnetting

  4. OpenWRT 路由器IPv6实战配置长篇教程:纠正你的IPv4思维!

  5. OpenWrt 开启 IPv6 中继 公网访问全指南

  6. 修改配置文件,给OpenWRT开启IPv6中继

  7. OpenWrt Wiki: IPv6 configuration

  8. IPv6地址、单播、多播/组播介绍

  9. IPv6 Stateless Address Auto-configuration (SLAAC)

  10. odhcpd 中继模式原理、局限以及解决方案

  11. 上海电信IPV6光猫拨号ipv6中继方式,有ipv6地址,ping不通的临时解决方法