本站在允许 JavaScript 运行的环境下浏览效果更佳


通过指令过滤出正确的公网 ipv6 地址(记一次折腾 IPV6 DDNS)

117

现象

主机有多个ipv6地址,ddnsgo无法正确获取

研究过程

  1. 选择通过接口获取太慢,且不能每次都确保可用
  2. 选择通过网卡获取,不能保证每次获取的都是对的(笔者一开始发现固定第二个是有效的,所以使用的是这项,但是重启光猫之后就不能使用了,具体原因请看下文)
  3. 通过指令获取,官方给的指令无效

如何创建一个正确的指令

ddnsgo项目提供的指令为

ip -6 addr | grep inet6 | awk -F '[ \t]+|/' '$3 == "::1" { next;} $3 ~ /^fe80::/ { next;} /inet6/ {print $3}'

我们可以在上面进行改动

第一步使用ip -6 addr查看自己的网卡的ipv6地址
笔者使用的是有线网,且笔者服务器仅有一个网卡,也仅有eth0获取到了24开头的ipv6地址,所以eth0就是笔者网卡
其他情况可能有wlan0(无线网),eth0.1 等

展开查看 笔者服务器的输出(敏感信息已做处理)
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 state UNKNOWN qlen 1000
    inet6 ::1/128 scope host noprefixroute
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
    inet6 2409:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xx/128 scope global deprecated dynamic noprefixroute
       valid_lft 2001sec preferred_lft 0sec
    inet6 fd02:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:c3a2/64 scope global deprecated dynamic noprefixroute
       valid_lft 5998sec preferred_lft 0sec
    inet6 2409:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/64 scope global dynamic noprefixroute
       valid_lft 7014sec preferred_lft 3414sec
    inet6 fe80::xxxx:xxxx:xxxx:xxxx/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
4: br-ad31df22f4b7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP
    inet6 fe80::42:c7ff:fe31:1b62/64 scope link
       valid_lft forever preferred_lft forever
7: vethc082c67@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP
    inet6 fe80::b4d5:49ff:fe4f:b4d9/64 scope link
       valid_lft forever preferred_lft forever
11: vethdc78e38@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP
    inet6 fe80::6034:10ff:fe26:4f0f/64 scope link
       valid_lft forever preferred_lft forever
13: vethc4b1ba9@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP
    inet6 fe80::44c4:81ff:fef2:acca/64 scope link
       valid_lft forever preferred_lft forever
15: vethdec5b90@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP
    inet6 fe80::7493:5cff:fe52:e624/64 scope link
       valid_lft forever preferred_lft forever
19: veth91efc43@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP
    inet6 fe80::dcc8:3ff:fea6:38a4/64 scope link
       valid_lft forever preferred_lft forever

所以第一段指令就可以改成ip -6 addr show eth0

接着笔者尝试了ip -6 addr show eth0 | grep inet6

展开查看 笔者服务器的输出(敏感信息已做处理)
inet6 24xx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xx/128 scope global dynamic noprefixroute
inet6 fd02:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/64 scope global deprecated dynamic noprefixroute
inet6 24xx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/64 scope global dynamic noprefixroute
inet6 fe80::xxxx:xxxx:xxxx:xxxx/64 scope link noprefixroute

众所周知,deprecated可以表示弃用的,过期的,所以deprecated的地址必然不是我们需要的地址
此时我们打开在线ping工具,或者使用笔记本连接手机热点,确保路由器,光猫,服务器都没有阻拦网络的设置(如防火墙),检测上面的地址是否可以连通。
经过测试也可以确定有deprecated标记的地址不可连通
经过几次重启服务器反复测试,笔者发现/128的那个地址可能是deprecated的,也可能不是deprecated的,但不论如何,必定是不可连通的,所以笔者将第二段grep inet6改成了grep 'inet6 240[a-f:A-F 0-9]*/64'

服务正常运行了一周,直到网络欠费,充值后笔者重新让路由器拨号,服务变得无法访问了
笔者多次让路由器重新拨号,以及让光猫重启后
登录服务器ssh,尝试了ip -6 addr show eth0 | grep inet6输出以下信息

展开查看 笔者服务器的输出(敏感信息已做处理)
inet6 24xx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xx/128 scope global dynamic noprefixroute
inet6 24xx:xxxx:xxxx:xxxx:xxxx:xxxx:xxx:xxxx/64 scope global deprecated dynamic noprefixroute
inet6 fd02:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/64 scope global deprecated dynamic noprefixroute
inet6 24xx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/64 scope global deprecated dynamic noprefixroute
inet6 24xx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/64 scope global deprecated dynamic noprefixroute
inet6 24xx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/64 scope global deprecated dynamic noprefixroute
inet6 24xx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/64 scope global deprecated dynamic noprefixroute
inet6 24xx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/64 scope global dynamic noprefixroute
inet6 fe80::xxxx:xxxx:xxxx:xxxx/64 scope link noprefixroute

可以看到大量prefixlen 64但是deprecated的地址
(这就是为什么,ddnsgo内设置通过网卡获取如果固定第二个地址,第一次获取的是有效的,之后只能获取到的地址都无效了)
所以笔者在第二条和第三条指令间加了一条指令grep -v 'deprecated'用于排除带deprecated的地址,最后终于可以成功运行了

2024.2.25补充: github有人反馈,定期换宽带,上面的指令依然会匹配到两个,而第二个新的才是有用的,所以最后再加上一条tail -1指令选择最后一条

最终指令(如果要使用,请把第一段eth0改成你的网卡,或者直接去掉show eth0,只留下ip -6 addr

ip -6 addr show enp1s0 | grep 'inet6 240[a-f:A-F 0-9]*/64' | grep -v 'deprecated' | awk -F '[ \t]+|/' '$3 == "::1" { next;} $3 ~ /^fe80::/ { next;} /inet6/ {print $3}' | tail -1