搭配OpenWRT路由器使用运营商IPv6进行家庭自建Debian服务器的网络配置指北

Intro

一般家庭宽带运营商不会(或默认不会)提供可路由的非NAT后的v4地址;若有,但v4解决方案单一(路由器上必做NAT,然后搭配一个DHCP static lease以及DMZ、端口转发二选一),没有过多可讨论的部分。

但是如今v6入户越来越普及了,且这个v6一般都是全球可路由的真v6,所以本着正确且合理进行推广v6的原则,撰写此文。

本文不涉及OpenWRT的路由器选购、安装和基本配置。OpenWRT默认已采用v22.03以上的官方stable版本。本文选择debian作为自建服务器使用的操作系统,同时也是推荐配置。

Additionally,本文假定运营商提供的IPv6地址具有PD能力(成都电信可以PD一个/60的段)。对于校园网下那种依赖ipv6 relay的方案是否适用,有待考证。

宽带入户概况

现行宽带方案基本上以运营商提供的光猫为终端家庭的网络接入点,较新的安装服务还会顺带送一个合作厂商的无线路由器,比如22年七月份安装宽带送了一台H3C的RC3000。当然一般这些送的路由器都是不推荐使用的,因为基本都是运营商定制版本,且一般也不会支持OpenWRT。

光猫这边,建议配置成“桥接模式”。使用桥接模式的目的是将PPPOE拨号过程放到自己的路由器上,从而获得完全的wan口控制,有利于调试部署。改桥接一般需要获得光猫的“超管帐号”,且里边的选项因光猫型号而异,选项描述也比较迷惑。成都电信1000号支持让客服远程帮忙改成桥接,如果想省事的话可以咨询一下自己的运营商,可能会支持相关服务。

通用的solution一般就是通过技术手段破解光猫,拿到超管密码或者其它形式成功登录。这取决于光猫型号与个人的信息检索能力,以及相关技术素养。

还有一条路可以尝试,小黄鱼或者tb可能会有相关地区相关ISP的运营商内鬼,几块钱就可以让他查到自己光猫的超管密码。

顺带,改了桥接只是part1,为了利用起桥接的接口,还需要获得自己宽带帐号PPPOE的用户名和密码。对于获得了超管帐号的情况,可以尝试进光猫管理页查看已经存储的帐号信息。运营商内鬼也能够查询这俩信息。

局部地区有的运营商是可以给出公网可路由的IPv4的,只不过默认没有给。比较推荐尝试去和运营商battle一下,或许会有惊喜。否则就只能拿到一个10.或者100.或者其它什么打头的NAT后的地址。但是这个地址一般并没有使用Symmetric NAT,所以是可能在自己路由器上做好补丁,让自己v4子网下的其它设备UDP获得NAT1支持。本文不讨论v4相关以及NAT打洞。

关于UPnP:这是一个愿意阅读本文的人所不需要的技术。出于如下几个原因:

  1. 推广IPv6可以消除家用NAT的需求,从而消除对与当前用例下的UPnP & NAT-PMP的需求
  2. IPv4下UPnP想要发挥作用,自己的路由器wan口需要拥有可路由的公网IP,或运营商也支持UPnP,二者都不容易满足

OpenWRT对接光猫桥接配置

宽带入户场景下,假定已在光猫侧完成桥接配置,那么路由器侧只需要将选定的WAN口网线连接至光猫配置桥接的网口即可。

首先配置基本的PPPOE实现拨号上网。OpenWRT的Interfaces列表中如果有预置的WAN或者WAN6接口,请删除后再进行配置。

首先创建对应的PPPOE接口:

注意正确选择Device。在接下来的选项中,先填入PAP/CHAP usernamePAP/CHAP password两项,即为PPPOE的用户名和密码。

然后切换至Firewall Settings,将该WAN口的防火墙区域选择至wan

注:这里的lanwan是OpenWRT默认配置时已经建立好的。如果列表中没有这两项,请重置路由器,或自行探索如何配置。

完成上述配置后点击Save以及Apply,等待PPPOE开始工作。如果配置正确,此时OpenWRT已成功取代光猫的拨号,通过桥接模式正常入网了。此时LAN下的设备也将获得互联网连接。观察一下运营商分配下来的IPv4地址:

说明自己并没有默认拿到公网v4(最终也没能向运营商要到)

OpenWRT IPv6上游配置

新建一个新的Interface,选择DHCPv6 client协议,起名为WAN6注意这里的Device需要选择为Alias Interface。具体原因可以参考下方Reference。

image

剩余两项保持默认即可。然后切换到Firewall Settings,将该接口加入至wan区域即可。保存并应用,等待v6生效。

检查是否正确获得IPv6地址,以及IPv6-PD(Prefix Delegation)。如若未能获取到上述两项,则可能是运营商策略不同,需要进一步分析,或选取其它IPv6接入方案。本方案配置仅适用于拥有IPv6-PD的环境。

如图,运营商给终端用户分配了一个/60的池子,意味着用户可以利用SLAAC起16个独立的IPv6子网(实际一般家用场景只需要一个,也就是只要有PD,/64就够用)(没有PD的场景比如校园网,则需要借助其它手段,不能参考本文)

OpenWRT IPv6下游配置

这里是整篇文章的核心内容之一。

需要配置的目标Interface只有LAN一个。点击蓝按钮的Edit,先点开Advanced

第一行和第二行是默认开着的,不要动。

第三行的Use custom DNS servers,我不确定它影响的是什么配置,因为另有一处更加像是需要进行配置的地方。总之先填上。不建议使用8.8.8.81.1.1.1,这里我使用的是阿里和DNSPOD的公共DNS。

千万不要使用运营商下发的DNS服务器,否则后续的各种BUG都要怪罪到这里来。

然后是Delegate IPv6 prefixes,这个可以开着也可以关了,因为我这里拿到的是/60因此我可以子网套子网弄出16个来(暂时没有什么用)。以及下面的IPv6 assignment length,选择到/64就行。这俩以及下面的选项不会影响LAN里的其它机器,只对路由器在LAN里的那个接口产生影响。如果想要修改路由器在LAN下的v6地址,可以去调整IPv6 suffix选项,默认是::1,类似于v4的192.168.1.1,但是对于v6来说,192.168.1.*里的前几项是由ISP分配的可路由地址,而非NAT后的地址。

接下来点开标签页DHCP Server。直接点开IPv6 Setttings子标签页。

如图进行配置。由于拥有PD,因此可以创建出比较Native的IPv6子网来。即:使用SLAAC进行地址分配;辅以无状态DHCPv6下发DNS等配置信息。因而RA-ServiceDHCPv6-Service都配置为server mode,而非校园网下常见的relay方案。

个人推荐不要让子网下的设备去直接使用公共DNS服务器,这样可以实现一些feature,并减少配置量。路由器可以缓存DNS信息(能有多好的效果就不知道了)。所以启用Local IPv6 DNS Server

NDP-Proxy也需要关掉。原本它是为了实现IPv6路由而采取的workaround,但是因为有了PD,整个网段已经默认会发给路由器WAN口了,所以不需要进行这种hack。还有Designated master也需要关掉,因为没有用到其功能。

注:208+的路由器上是一套标准的Proxy接入配置,与家庭宽带是完全不同的。理论来说采用代理转发方式会加重路由器负担,并且不能scale well。

再切换到IPv6 RA Settings子标签页。

图上即为推荐配置。灰色的为默认选项,不建议修改。

该页控制由路由器发送到LAN侧的RA报文。主要有两点:启用SLAAC;告诉子网设备仅使用DHCPv6获取DNS等配置,而非直接获取地址。

直接通过DHCPv6在这里获取地址也是可行的,但不是推荐配置。建议不要同时启用SLAAC与有状态DHCP(RA-Flags里选择managed config),避免分配两个IP地址。

完成上述设置后,子网已经获得了比较native的IPv6支持。将新的设备接入子网后,将会SLAAC自动配置得到全球可路由的IPv6地址,并完成DNS配置。

自建服务器的静态IPv6配置

以Debian 11系统作为示例。

IPv6下可用的地址分配手段概览:

  • 采用有状态DHCPv6,为设备划定static lease:v4风格简单暴力,但是完全依赖路由器
  • 设备上进行纯手工static ipv6 address:不实际,因为v6前缀也会同时写死,明显不能用作家用部署时的配置方案
  • 设备上啥都不配置且不使用有状态DHCPv6(即inet6 auto):如今会获得个隐私地址,会变,不利于路由器侧进行防火墙配置(胆子大的话试试全部放行)
  • 设备上使用Stable Private Address:一个只要前缀不变,后缀就不变的方案,但很明显前缀会变,所以还是个动态地址,不利于路由器侧防火墙配置
  • token address:本文采用的方案,兼顾隐私(没有隐私就是最好的隐私)与静态地址,但代价是地址可能会撞,配置时需小心。

在debian上配置token address需要一些小技巧,因为它不是开箱即用的。

首先,需要一个if-up.d的脚本。我的自建服务器上,由于一些原因(开了虚拟机),使用了一个桥接接口来当作网络接口,所以只能使用if-up.d。如果没有使用桥接接口,那么推荐直接使用if-pre-up.d。参阅下方Reference: IPv6_Static_Addresses_using_Tokens

首先建立文件:/etc/network/if-up.d/ipv6-token-iid

内容为:

#!/usr/bin/env sh


if [ "$PHASE" != "post-up" ]; then
    exit 0
fi

if [ -z "$IF_TOKEN_IID" ]; then
    exit 0
fi

ip -6 addr flush scope global dev "$IFACE"
ip token set "$IF_TOKEN_IID" dev "$IFACE"

exit 0

该脚本会在网络接口启用后被调用,然后检查IF_TOKEN_IID变量是否被配置,如果被配置了,则删除已经分配的全球可路由地址,然后重新配置网口的token为变量内容。如果是在if-pre-up.d里,请参考下方Reference里的脚本方案。

然后使其可执行:sudo chmod +x /etc/network/if-up.d/ipv6-token-iid

接下来修改/etc/network/interfaces

auto br0
iface br0 inet dhcp
    bridge_ports enp4s0 enp3s0 enp2s0
iface br0 inet6 auto
    token_iid ::2

由于我使用了桥接接口所以长这样。重点只有最下面两行。还是使用inet6 auto,但是下面多了一行,将token_iid变量配置成了::2。这个变量将会在前面的脚本里被读取到。

生效后则会成功固定地址。(蓝色圈出)

注意,虽然这里成功获得了“静态地址”,但是静态的部分只有受子网控制的suffix部分。IPv6 Prefix部分是运营商下发的,仍可能会变,因而依旧需要DDNS支持。做这一章节的配置主要目的是为下一章节的配置服务。

OpenWRT路由器侧防火墙放行

防火墙是必要的。在当前社会背景下,防火墙承担着重要的防内鬼任务。[bgcolor=#fff]内鬼是谁?可以自行搜索“中国 BAT”[/bgcolor]

OpenWRT在采用上述配置时,默认阻断了IPv6的传入连接(没有允许防火墙wan区域向lan区域的forward),只放行了ICMPv6的Ping。这个ICMPv6的Ping是显式放行的,在防火墙 Traffic Rules 里:

如果想要把子网下的设备暴露到公网,那么就需要允许传入连接。如果没有进行上一步的“静态地址分配”,那么在这里就会面临很麻烦的处境,因为IPv6前缀不一定是固定的,没有办法去做L3的管理。为了不至于为了一台设备而放开整个子网的防火墙,所以需要在此处新增规则,针对设备和应用进行区别控制。

我将我的服务器IPv6整个暴露到了公网环境下。(只是这一台机器的话自认为还是管理的过来的,但如果连带上windows安卓那一票生活设备的话真没那个勇气)

新建规则,首先点进 Advanced Settings里:

限制仅应用于IPv6。然后点回 General Settings里:

起一个名字,选择TCP+UDP(当然直接放行any也不是不行?不放行any的话,nmap就必须带-Pn才能扫描)。防火墙区域源为wan,目标为lan,然后目标地址,使用一种特殊的写法,通过后缀进行匹配(普通v4掩码是前缀匹配)。Action选择accept。

这里的目标地址将会匹配到所有后64位地址为::2的包。实际上就只有前面手动配置了token address的那一台会被匹配到。采用这种匹配方法,就能够不受可变的前缀影响。注意,还有需要确定的一点:我这里运营商PD下来是个/60的段,意味着可能有16个独立的v6地址的后64位都是::2。暂时没去研究解决办法。

完成后就会多出这一条规则来。此时该机器上开的端口已经可以公网直接访问了。

如果不想要整个放开,那也可以在上述页面具体配置,只放行特定端口。此时的配置已经非常灵活了。

References

2 个赞

修订:

该问题依旧可用后缀掩码匹配进行解决,只不过地址需要精确到/-68,即涵盖住/60下的所有IP即可。示例:

电信家宽的/60一共可以提供8个/64子网,每个子网下的::2/-64可以通过类似于这种的0:0:0:0::2/-68, 0:0:0:1::2/-68, …, 0:0:0:7::2/-68互相区分。