type
status
date
slug
summary
tags
category
icon
password
⚠️
迁移自旧站,原始文章发表于2021-05-15,信息可能已部分失效

缘起

最近碰巧看到某商家有国内的三线纯IPv6小鸡补货,便入手了一台玩玩。

家宽IPv6接入

如今三大运营商基本都提供IPv6接入,如果发现当前没有IPv6网络可能是光猫的配置还是纯IPv4的,可以参考这几篇文章修改光猫的配置[1][2]。设置妥当之后,在光猫或拨号路由器上就可以看到有IPv6的地址信息了,部分情况下网关的RA报文(Router Advertisement)会来得慢一些,获取地址信息可能会花上几分钟的时间。
现在的运营商(除了教育网)一般都在报文提供了Prefix delegation信息来为子网中的设备分配IPv6地址,这样客户端可以知道自己能够使用的子网范围,再自行“计算”出自己的网络接口ID,这个便是SLAAC(stateless address auto configuration)方式分配IPv6地址。还有一类是DHCPv6分配客户端地址的方式,其中又分为stateless和stateful两种,区别主要在于IPv6地址是否依然通过路由通告RA方式生成前者[3]

多级路由接入

如果设备将光猫作为路由器拨号接入,或通过桥接的方式在另一路由器上进行拨号再由设备接入,这样的方式客户端是可以正常获取IPv6地址的。但若在多级路由下的设备想要正常接入IPv6网络,与教育网中无PD信息的情况类似,需要额外做一些工作[4]

每一层划分子网

每一级的路由器下的网络,以运营商的提供的PD信息为基础再进行子网划分,同时需要上级交换机能对未知的IPv6地址发出NS报文[4]。这种方案虽然“最符合”IPv6规范,但每一层路由上都需要搞很多配置,比较费力。尝试使用padavan后台上的默认配置进行实验,没有成功,作罢。

NAT方式

在IPv6下还玩NAT,不免有些怪异,但胜在有成熟的方案,如NAT66。padavan中基于hanwckf维护的固件(比如Hiboy的)都有集成NAT66,设置也比较简单[5]
如果不关心内网穿透的问题,用NAT66来解决二级路由下的客户端接入IPv6是没啥问题的。但是在实践中发现,NAT66的方案在三级路由下的客户端便无法正常接入IPv6网络(二级和三级路由的LAN地址设置为不同前缀的私有IPv6地址)。猜测是地址转换上对目标地址是存在要求的,这里没有细究,作罢。

只允许IPv6包的WAN-LAN网桥

和NAT方案一样也是在内核空间进行数据包转发,配置也是相当简单。
ebtables -t broute -A BROUTING -i $WAN_DEV -p ! ipv6 -j DROP brctl addif $LAN_BR_DEV $WAN_DEV
 
再每一层的路由器上都搭建网桥,相当于把客户端直接暴露出去,如果路由器上有防火墙相关的设置,也是需要去掉的。
最后采用了这个方案,除了效率和安全上可能存在隐患,其他使用正常。还有一种是通过修改数据包的MAC地址进行中继的方案,但相关软件6relayd看分享存在不少断网和抖动的问题,没有尝试。

多线IPv6服务器

虚拟化之后的小鸡只有一块网卡(网络接口、interface),存在CT/CU/CM三条线路的接入和出口。

按目标地址选择出口线路

首先想当然地尝试了在IPv4网络中屡试不爽的单网卡、多虚拟接口(virtual interface)绑定不同IP,根据路由表控制不同目标IP走不同网关的方案。随即便发现linux对IPv6里头已经没有虚拟接口这样的实现了,而是在单个接口设备直接上绑定多个Global的IPv6地址。
不过也没关系,还是可以通过路由表控制出口线路的选择。

推测服务器上游交换机的路由策略

直接修改路由表中目标地址的Next Hop(gateway)信息为指定线路的网关(为CM线路),通过traceroute发现,中间的路由节点还是默认的另一条线路(为CU线路)。修改默认网关之后(为CT线路),发现还是走往CU线路,而单独只设置一个非CU的IPv6地址的情况下,则可以观察到走对应的线路出口。很明显此时虚拟机所在的网络拓扑和上游交换机的策略可能与我的想象不符。
When a program initiates an outbound connection it is normal for it to use the wildcard source address (0.0.0.0), indicating no preference as to which interface is used provided that the relevant destination address is reachable. This is not replaced by a specific source address until after the routing decision has been made. Traffic associated with such connections will not therefore match either of the above policy rules, and will not be directed to either of the newly-added routing tables. Assuming an otherwise normal configuration, it will instead fall through to the main routing table.[6]
如上所述,本地发出的数据包,应该是通过路由决策后确定往哪个接口发送后,才会将包的源地址(src address)修改为对应接口上的IP。现在只有一个接口,很显然数据包都会往这个唯一的接口上发送。但这个接口上有三个IPv6地址,究竟是选择哪一个作为改写的源地址呢?

单网卡多IP的源地址选择

ip -6 route get <DEST_IPV6_ADDR>
通过上述命令发现源地址地址总是网络接口上排在上面(最后添加)的IPv6地址,中间指定的网关地址虽然正确,但线路的选择似乎只和源地址相关。
ip -6 neigh
又查询本地的NS记录,发现三条线路的网关IPv6地址,对应的二层MAC地址均是相同的。

猜测&验证

至此可以猜测上游交换机/网关是通过数据包中的源地址IP来确定发送的出口线路的。
ip -6 route add <DEST_ADDR> via <NEXT_HOP> dev <DEV> src <SRC_ADDR>
添加路由后再次traceroute验证,果真如此。甚至是在系统标记某个IPv6地址为deprecated状态时,仍可以通过该IPv6地址对应的线路正常收发数据(这是什么鬼?)。

📎 参考文章

  1. 移动宽带如何获取IPV6地址
  1. 记一次中国移动家用宽带设置成支持IPv6网络的经历
  1. IPv6系列-彻底弄明白有状态与无状态配置IPv6地址
  1. 【进阶类教程】多种无PD的情况下给内网配置IPv6的方法
  1. scut_padavan使用指南
  1. Ensure symmetric routing on a server with multiple default gateways
 
llm事实/知识正确性论文整理Padavan插件开发笔记
hackaday
hackaday
一个普通的干饭人🍚
公告
type
status
date
slug
summary
tags
category
icon
password
🎉没有公告🎉
👏欢迎体验👏