文章

OpenWrt 开启 IPv6 公网访问全指南

阅读本文要求具有基础网络知识,例如知道什么是网络掩码、路由、DHCP 等。

当前环境:

  • 江苏电信,光猫为桥接模式。
  • x86 软路由,安装 iStoreOS

基础概念

什么是 IPv6

IPv6 与 v4 不同。v4 时代运营商一般只给用户分配最多 1 个公网 ip,然后用户自己的路由器通过 NAT 再给局域网设备分配内网 IP,也就是 192.168.x.x 这种。这种情况下内网设备没有独立的公网 IP,要想从公网访问必须配置路由器端口转发。随着 v4 资源枯竭,现在运营商默认已经不再分配公网 IP 了。要想正常从外部访问,必须做内网穿透。

IPv6 有无数个地址可供分配,“可以给地球上的每一粒沙子都分配一个 IP 地址”。因此运营商分配的策略也会变化。v4 分配的是一个地址,而 v6 分配的是一个前缀,也就是所谓的 pd,相当于是一整个网段,我们可以自己继续往下分配,从而使得每一个局域网设备都能获得公网 IP 地址,甚至可以划分自己的多层子网。

典型的 IPv6 地址由 8 组十六进制数字表示,一共有 128 bits (16B)。

|----- 网络号 ------| 子网号|--------- 主机号 ---------| 前缀长度|
0123 : 4567 : 89ab : cdef : 0123 : 4567 : 89ab : cdef /64

通常习惯上只有子网号是我们可以自行往下划分的部分,即前缀长度应该在 49~64 范围内。

IPv6 每组的前缀 0 可以省略,多组连续的 0 也可以省略,但要用 :: 表示,例如下面两种写法等价:

204e:0000:0000:0000:0000:0000:0000:1
204e::1

Scope

与 v4 不同,一个接口可以同时具有多个 v6 的 IP 地址,并且多数情况下都会超过一个。因为 v6 地址分为不同的 Scope,也就是说有效范围不同,常见的(不是全部)包括:

  • Global:全局地址,全局可路由,相当于「公网 IP」。
  • Unique Local:只在网关内部使用,相当于 192.168.x.x 之类的局域网地址。多个子网可以通过此类地址互相访问(通过路由器)。
  • Link Local:每个接口自动生成的链路地址,永远不被路由。只在本地链路(冲突域)中使用。

其中只有「Link Local」在 IPv4 中没有明确对应,因为它的存在主要为了解决 IPv6 特有的一个问题:一个接口有多个地址,那么建立路由时很可能学习到重复的下一跳,所以需要一个唯一标识来区分设备,这就是 Link Local 地址。

拨号获取 IPv6

进入 OpenWrt 后台「网络-接口」,编辑 wan 接口(通常都是这个名字),修改这些选项:

  • 获取 IPv6 地址:自动
  • 委托 IPv6 前缀:勾选

wan 口的「DHCP 服务器 - IPv6 设置」:

  • 指定的主接口:不勾选
  • RA 服务:禁用
  • DHCPv6 服务:禁用
  • NDP 代理:禁用

保存应用后通常会多出一个名为 wan_6 的虚拟动态接口,因为大部分营运商是通过 DHCPv6 下发地址的,而我们之前选择了「自动」,OpenWrt 识别到之后就会新建一个客户端。若运营商支持现在应该就能看到获取的前缀了(PD):

获取的 PD

注意,若只有 fe80:: 开头的地址则说明未获取到 IPv6,这个只是自动生成的链路地址而已。

分配 IPv6

路由器获得了一个网段,下面要做的就是给每一个设备都分配一个公网地址。有两种方案,可以单独选择也可以同时使用,分别是 SLAAC 与 DHCPv6。

SLAAC

SLAAC 是无状态地址自动配置协议,顾名思义,它不再需要 DHCP 服务器来维护状态,而是各个客户端自行生成、协商、通告地址。SLAAC 是唯一全平台支持的协议Android 明确不会支持有状态 DHCPv6,谷歌认为有状态协议对于终端用户没有明显优点,还会造成隐私问题,属于 IPv4 时代的陋习。

SLAAC 的一个重要数据是路由器定期发送的 RA(路由通告),其包含前缀信息,以及是否应该尝试通告 DHCPv6 请求地址。

要配置纯 SLAAC,需要进入 「lan 口的设置 - 高级设置」:

  • 委托 IPv6 前缀:自选,决定到下级设备能否获得前缀(不影响 IPv6 地址本身的分配)。不懂可以勾上。
  • IPv6 分配长度:启用委托前缀时决定分配下去的前缀长度,划分多个子网时需要,不懂可以填 64 或保持默认。
  • IPv6 分配提示:保持默认就行,划分子网是可选用的。
  • IPv6 后缀:设置当前接口的 IPv6 地址后缀,可以填写 ::1,那么此接口的地址就类似 240e:aaaa:bbbb:cccc::1

另外还要配置「lan 口的设置 - DHCP 服务器 - IPv6 设置」:

  • 指定的主接口:不勾选
  • RA 服务:服务器模式
  • DHCPv6 服务:禁用
  • 本地 IPV6 DNS 服务器:勾选
  • NDP 代理:禁用

对应地,修改 「IPv6 RA 设置」:

  • 默认路由器:自动
  • 启用 SLAAC:勾选
  • RA 标记:无,因为我们根本没有 DHCPv6 服务器。

这样保存应用之后,应该所有的下属设备都可以生成公网 IPv6 地址了。

DHCPv6

Android 明确不会支持有状态 DHCPv6

DHCPv6 本身也分为有状态和无状态两种:

  • 有状态:通过 DHCPv6 分配 IP。
  • 无状态:IP 依然采用 SLAAC 生成(通过 RA),但其他参数,例如 DNS,网关地址等则通过 DHCPv6 获取。

要启用 DHCPv6,「lan 口的设置 - 高级设置」与上文 SLAAC 配置一致,「lan 口的设置 - DHCP 服务器 - IPv6 设置」如下:

  • RA 服务:服务器模式
  • DHCPv6 服务:服务器模式
  • 本地 IPV6 DNS 服务器:勾选
  • NDP 代理:禁用,用于多级路由器之间转发邻居发现协议的流量。

对应地, 「IPv6 RA 设置」应为:

  • 启用 SLAAC:禁用
  • RA 标记:M + O,表示通过 DHCPv6 获取 IP 与其他配置参数。

若希望配置为无状态 DHCPv6,则需要启用 SLAAC,并把 RA 标记设置为 O。即通过 SLAAC 生成 IP 但通过 DHCPv6 获取参数。

防火墙放行

现在我们的每一个设备都有公网地址了,但要想被外部访问,需要防火墙放行才行。这里只说 OpenWrt 的防火墙,至于设备自己的(群晖 NAS,Windows 等)自行设置。

进入「网络 - 防火墙 - 通信规则」点击下面的添加按钮:

【常规设置】

  • 协议:按需选择,注意 ping 使用的是 ICMP 协议,不是 TCP/UDP。
  • 源区域:wan
  • 目标区域:lan(如果要访问路由器自己则选择「设备」)
  • 目标端口:自行设置
  • 操作:接受

【高级设置】

  • 地址族限制:仅 IPv6

保存一下就好。

注意,这样配置防火墙实际上是允许以 IPv6 访问任意子网设备的指定端口。

如果希望只放行特定的目标设备,可以指定 IP 后缀。因为运营商分配给我们的前缀是动态变化的,所以不能直接指定 IP,而后缀无论是使用 DHCPv6 还是 SLAAC(使用 eui64),经过配置都可以确保不变。然后添加防火墙规则时填写「目标地址」为 ::aaaa:bbbb:cccc:dddd/-64,其中 -64 的意思是匹配从右往左的 64 位。若部分系统不支持这种缩写,可以回退到 IPv4 的掩码表示形式:::aaaa:bbbb:cccc:dddd/::ffff:ffff:ffff:ffff

匹配地址后缀

附录

常见前缀

  • 240e::/20: 中国电信
  • 2409:8000::/20: 中国移动
  • 2408:8000::/20: 中国联通
  • 2000::/3: 全局单播地址。也就是全球可路由的公网地址。上述三个都属于这个。
  • FE80::/10: 链路本地地址。
  • 2002::/16: 仅供 6to4 隧道使用

特殊地址

  • :: - 相当于 0.0.0.0
  • ::1/128 - 本地回环地址,相当于 127.0.0.1/32

在线小工具