家宽IPv6基础介绍, 以及一种批量DDNS的方法

1,046 阅读8分钟

这个帖子主要是介绍普通宽带IPv6的一些机制, 在此基础上提供一种思路, 利用IPv6区别于IPv4的分配机制, 达到对内网机器进行批量DDNS绑定的效果 不提供具体的实现代码和工具, 欢迎自行实现

Pasted image 20230414233247.png

ISP地址分配

IPv4

无论是动态拨号还是静态分配, 从运营商处获得的IPv4地址总是一个, 有些是公网IP, 有些是内网IP, 这个地址会被绑定到WAN口, 而路由器LAN口连接的内网主机则统一用一个专用网段或者说内网网段来分配, 常用的比如10.0.0.0/24或者192.168.1.0/24等., 内外网通过NAT转换. 由于外网可见的设备其实只有路由器(的WAN口), 内部主机要对外开放就需要路由器做端口转发或DMZ. 如果ISP分配的已经是一个内网地址, 那通过互联网甚至没法访问路由器, 除非做内网穿透. 这就是为什么很多人都想申请公网IP, 并且从猫拨号改为路由器拨号, 光猫只做桥接的原因.

IPv6

IPv6则有不同, 运营商分配给路由器的除了一个IPv6地址(同样绑定到WAN口), 还有一个IPv6网段, 形如AAAA:AAAA:AAAA:AAAA::0/64(实际域范围不会是/64,这里只以路由器常见的默认值/64为例), 供路由器LAN内的主机使用, 这个网段中每一个地址都是公网IP地址, 可以从外网直接访问.

IPv6地址的结构

举例LAN内某个主机地址为AAAA:AAAA:AAAA:AAAA:1111:1111:1111:1111, 我们把前面的64位称为前缀, 后64位称为后缀(实际后缀叫主机地址更准确, 为方便理解所以叫后缀), 按照我们前面的内容可以知道, 前缀总是从ISP取得且会经常变化, 就跟IPv4公网IP一样, 而后缀则是LAN内部按一定的原则生成, 具体生成方式包括DHCPv6/静态分配/SLAAC

LAN地址分配

IPv4的LAN地址要么使用DHCP分配要么使用手动配置 DHCP即主机广播请求, DHCP服务器从LAN地址池中(比如TP-Link默认为192.168.1.100~192.168.1.199)选择一个可用地址并返回. 通常这个DHCP服务器由路由器兼任, 并且一个网段内只能有一个DHCP服务器, 至于分配的地址, 按我的经验, TP-Link都是使用顺序分配, 如192.168.100->192.168.1.101, 而Openwrt系普遍是随机分配. 静态地址分配则是用户自己填写.
对于IPv6, 除了同样支持DHCPv6和手动填写静态之外, 还有一种独特方式, 主机会根据网段内其他主机地址, 自动生成自己的地址, 这种方式叫无状态地址自动配置SLAAC. ipv6ddns-03.png

SLAAC

SLAAC与DHCPv6一样, 前缀均来自ISP, 但两者区别在于,DHCPv6方式的后缀由路由器分配, 而SLAAC方式只从周围机器获取前缀, 后缀需要主机自行生成. 根据系统不同, SLAAC后缀有多种生成算法, 简单分成EUI-64和非EUI-64就行

EUI-64算法

EUI-64算法的介绍网上有很多, 而且我们其实也不需要自己手动算, 所以我简单介绍:

  • 将MAC地址的6个字节(48bit)从中间拆开, 塞进去2个字节(FFFE)
  • 高位的第七个bit位置1
  • 得到的这个64bit的值即为主机地址后缀.

详细的介绍可以自行搜索. Pasted image 20230417113959.png

单接口多IP

当你用ipconfig/ifconfig/ip addr等命令查看ip地址的时候, 你可能会看到你机器上有好几个IPv6地址. 一方面, 因为IPv6同样有环回地址/本地地址的概念; 另一方面, IPv6可以同一个Interface绑定多个地址, 也就是说 DHCPv6/SLAAC等方式获得的地址会同时有效, 另外如果启用临时地址的功能, 还会有永久地址和临时地址的概念.

示例

从前面可以看出, 相比IPv4简单的机制, IPv6的内网地址分配要复杂得多, 其生成的地址多且难以理解. 这里我用我一台典型的Ubuntu虚拟机做例子, 这台机器所属的路由器也是一台常见的支持IPv6的家用路由器(红米AC2100), 默认开启了DHCPv6. ipv6ddns-02.png 蓝色字体部分是4个IPv6地址, 红色字体部分是一些值得注意的额外属性, 这几个地址的含义如下:

  • [::1]
    • 表示IPv6的环回地址, 相当于IPv4的127.0.0.1
    • scope host表示这个地址的作用域仅限本机范围
  • [fe80::20c:29ff:fec0:8f48]
    • [fe80::]前缀说明是链路本地地址, 类似IPv4的192.168.x.x这种局域网网段
    • 后缀[20c:29ff:fec0:8f48]是EUI-64算法根据MAC地址得到的
    • scope link属性同样都说明了作用域只限本地范围(二层地址)
    • 结论: 内网地址, 前缀固定, 后缀SLAAC获取
  • [2408:8aaa:aaaa:aaaa::e18]
    • 前缀是[2408:8aaa:aaaa:aaaa], 以2408:8xxx这种开头的是联通的网络
    • 后缀是[::e18]这种DHCPv6常用的短地址, 判断是从路由器DHCPv6得到
    • scope global属性同样说明了作用域是全局范围(三层地址)
    • 结论: 公网地址, 前缀来自ISP, 后缀来自DHCPv6
  • [2408:8aaa:aaaa:aaaa:20c:29ff:fec0:8f34]
    • 前缀同上
    • 后缀[20c:29ff:fec0:8f48]是EUI-64算法根据MAC地址得到的
    • scope global属性同样说明了作用域是全局范围(三层地址)
    • 结论: 公网地址, 前缀来自ISP, 后缀来自SLAAC

总的来说, 大致的判断方式是:

  • fe80:开头的地址是局域网地址, 以240x:开头的是公网地址, 更详细地说, 如果是240e:开头说明是中国电信, 2409:开头说明是中国移动, 2408:开头说明是中国联通, 更详细的列表可见[[comeround.cn/article/ipv…]]
  • 后缀部分如果中间位置有ff:fe这种数值, 可以判断是EUI-64算法得到
  • 后缀部分如果没有ff:fe且数值很短, 一般是DHCPv6得到

DDNS方案

示例地址中我们只需要关注最后一个地址[2408:8aaa:aaaa:aaaa:20c:29ff:fec0:8f34]

  • 这个地址是公网地址
  • 它的前缀来自ISP, 并且与局域网内其他机器以及路由器都相同
  • 它的后缀来自SLAAC和EUI-64算法, 只要MAC地址不变这个后缀就永远固定, 且可以简单算出来

这些特点意味着只需要知道前缀, 我们总能直接知道它的IPv6公网地址, 甚至在它还没有开机的时候. 而前缀可以从其他机器上获取, 包括路由器上. 如果是内网内有多台主机, 那我们从路由器或者任何一台主机上都可以批量获取这些主机的IPv6地址, 并一次性给这些主机分配域名.

前置条件

要实现这种一次性获取主机地址+批量DDNS+外网可访问, 需要这些条件:

  • 网络提供IPv6功能, 由于政策原因, 现在的绝大部分家宽默认都支持
  • 路由器拨号而非光猫拨号, 这是因为需要配置防火墙功能, 光猫基本无法配置
  • 路由器支持IPv6(较新的路由器基本都支持)
  • 路由器支持IPv6防火墙的开关功能, 或者可以对防火墙配置
  • 内网主机支持IPv6, 且支持SLAAC分配+EUI-64主机地址算法
    • Linux系的都支持且默认使用, 我测试过的包括但不限于主板BMC/ESXi/Ubuntu等linux发行版/TrueNAS scale/群晖/Openwrt及衍生的ikuai之类的各种软路由
    • Windows默认使用随机算法, 可通过命令改用EUI-64, [[sid-500.com/2018/02/07/…

虽然看起来条件很多, 但使用软路由的情况下绝大部分用户都满足这些条件, 非软路由的情况也很多都支持(比如我未刷机的红米AC2100开启了SSH之后).

软件方案

与IPv4的DDNS方案思路其实是一样的: 最典型方案是利用路由器脚本, 定时查询自身IP变动, 如果运营商前缀发生变动, 则将准备好的主机列表与对应的域名进行更新 由于红米AC2100不带ssl库, 而我用的cloudflare api强制要求HTTPS, 所以我并没有使用纯路由器进行处理, 而是使用了一个VPS中转的方案, 这个方案并不适合绝大多数人. 所以我无法提供代码, 请自行实现

其他

  • 关闭防火墙的危险性必然存在, 但是具体到IPv6的危险性有多高, 我见过很多讨论, 很难拿出一个定论, 请自行斟酌
  • 路由器LAN口的后缀固定是::1, 同样可以绑定域名
  • 如果路由器支持DHCPv6的MAC绑定功能(一般需要软路由), 同样可以利用DHCPv6获得的地址去绑定