AI:BJUT校园网场景下的路由器IPV6调试过程

北工大校园网 QWRT/OpenWrt IPv6 配置实录:无 DHCPv6-PD 下的 IPv6 Relay、校园认证与 OpenClash 共存

这次折腾的目标并不是简单地“让路由器拿到 IPv6”,而是让接入北工大校园网的 QWRT 路由器能够正常完成校园网认证,并把学校分配在 WAN 侧的 IPv6 /64 网络通过 IPv6 Relay 延伸到 LAN,使电脑等终端获得真实校园网 IPv6 地址。同时还要兼容 OpenClash,实现 IPv4 继续按原有方式使用 OpenClash,而 IPv6 可以直接通过校园网访问公网。

整个过程中实际上遇到了三个相互独立的问题:校园网 IPv6 认证、没有 DHCPv6-PD 时的 LAN IPv6 Relay,以及 OpenClash 对 AAAA DNS 记录的抑制。最开始这三个问题叠在一起,很容易误判成“学校 IPv6 不通”或者“路由器不支持 IPv6”。

下面按照实际排障过程,从头到尾整理。


一、网络环境和最初的问题

使用的路由器是京东云雅典娜 AX6600,刷入 QWRT。WAN 物理接口是 eth4,IPv4 通过 DHCP 获取,IPv6 通过 DHCPv6/RA 获取。

最初查看 WAN6 后发现,路由器本身其实已经获得了学校提供的公网 IPv6:

2001:da8:216:210d:ded8:7cff:fe56:225c/64

同时存在默认路由:

default from 2001:da8:216:210d::/64
via fe80::76ea:cbff:fe5b:d91b
dev eth4

这说明至少从二层和 IPv6 RA 的角度,路由器已经成功加入学校 IPv6 网络。

但 LAN 端当时只有:

fda5:724f:9eec::/64

这样的 ULA 私有 IPv6 地址,Windows 没有获得 2001:da8:216:210d::/64 的公网地址。

这里逐渐确认了一个很关键的事实:

学校给的是 WAN 所在链路上的一个 /64,没有下发 DHCPv6 Prefix Delegation,也就是没有额外给路由器一个可以自由分配给 LAN 的 IPv6 前缀。

因此普通 OpenWrt 家宽环境中常见的:

WAN 获得 /56 或 /60
→ 路由器拆一个 /64 给 LAN

在这里行不通。

只能采用:

WAN /64
    ↓
RA Relay
DHCPv6 Relay
NDP Relay
    ↓
LAN 继续使用同一个 /64

也就是说,需要把校园网这一条 IPv6 链路“延伸”到 LAN。


二、先确认校园网 IPv6 门户本身是否可达

校园网认证相关域名经过学校 DNS 可以解析。

例如:

lgn6.bjut.edu.cn

可以得到 IPv6 地址:

2001:da8:216:30c9::a
2001:da8:216:30c9::2

直接从路由器访问:

curl -6 \
  -H 'Host: lgn6.bjut.edu.cn' \
  'http://[2001:da8:216:30c9::a]/'

可以收到 Dr.COM 门户响应。

因此,路由器到校园认证系统的 IPv6 链路没有问题。

同时还发现学校提供两个很有用的接口。

IPv4 映射:

curl -4 \
  'http://lgn.bjut.edu.cn/drcom/getipv4?callback=x'

会返回类似:

x({"result":1,"ip":"172.21.13.69"})

IPv6 地址:

curl -6 \
  -H 'Host: lgn6.bjut.edu.cn' \
  'http://[2001:da8:216:30c9::a]/drcom/getipv6?callback=x'

返回:

x({"result":1,"ip":"2001:da8:216:210d:...."})

这两个接口后来对认证过程非常有帮助。


三、分析校园网 Portal 的认证逻辑

最开始直接按照传统 Dr.COM 的参数去请求登录接口,会遇到:

认证操作非本机终端

或者请求并不能正确完成认证。

后来对门户页面加载的 JavaScript,特别是 a41.js 和相关逻辑进行了分析。

Portal 当前使用:

/eportal/portal/login

同时配置中可以看到:

page_data_encrypt = 1
encryption_type = 1
secret_key = test

关键问题就在这里。

网页并不是把登录参数直接明文发送到 /eportal/portal/login,而是先进行一个非常简单的编码。

相关 JavaScript 的逻辑本质上是:

每个字符 ASCII 值
    XOR 22
    ↓
转成两位十六进制

例如:

'1'
ASCII = 49
49 XOR 22 = 39
39 = 0x27

所以:

enc("1") = "27"

在 QWRT 中由于系统没有完整 GNU 工具,最后使用 BusyBox hexdump 实现:

enc() {
  printf '%s' "$1" |
  hexdump -v -e '1/1 "%02x\n"' |
  while read h; do
    [ -n "$h" ] && printf '%02x' "$((0x$h ^ 22))"
  done
}

这里还有一个很容易搞错的地方。

/drcom/chkstatus、/drcom/getipv6 等 Dr.COM 接口本身不需要进行这种参数编码;但:

/eportal/portal/login

需要。

之前一直失败的重要原因之一,就是把这两套接口的参数处理方式混在了一起。


四、确定认证参数和 MAC 行为

Portal 前端初始化终端参数时,会从:

ss4
olmac

获取 MAC。

实际 /drcom/chkstatus 返回的是:

ss4 = 000000000000

后面在线状态中:

olmac = 000000000000

所以本次 IPv6 Portal 场景中,网页实际上并没有使用路由器物理 MAC:

dc:d8:7c:56:22:5c

而是使用:

000000000000

这也是为什么之前直接把路由器真实 MAC 塞进去,反而会得到:

认证操作非本机终端

前端还会给普通 PC 账号添加:

,0,

前缀,因此实际 user_account 类似:

,0,用户名

同时门户支持:

login_ip_type = 0

表示 IPv4 + IPv6 统一认证,

以及:

login_ip_type = 2

表示 IPv6 认证。

经过参数编码后,从 QWRT 发起请求,终于得到:

Portal协议认证成功!

随后访问:

/drcom/chkstatus

返回:

"result":1

并显示当前 IPv6 地址。

这就证明路由器 WAN IPv6 已经真正进入在线状态。


五、为什么认证成功以后 ping6 还是全部超时

这里出现了整个过程中一个比较容易误导判断的现象。

认证成功后:

ping6 2400:3200::1

仍然:

100% packet loss

对 Cloudflare:

2606:4700:4700::1111

同样没有 Echo Reply。

一开始很容易认为:

“认证虽然显示成功,但公网 IPv6 还是没通。”

后来改用真正的应用层协议测试。

首先直接用公网 IPv6 DNS:

nslookup www.cloudflare.com 2400:3200::1

成功获得结果。

这已经证明:

IPv6 UDP/53

可以访问公网。

然后绕过 DNS,直接指定 Cloudflare 的真实 AAAA:

curl -6 -I \
  --resolve 'www.cloudflare.com:443:[2606:4700::6810:7c60]' \
  https://www.cloudflare.com/

返回:

HTTP/2 200

至此可以确定:

QWRT 路由器本身的公网 IPv6 完全正常。

所以这次排障得到一个重要经验:

ping6 不通 ≠ IPv6 不通

校园网或中间设备完全可能过滤 ICMPv6 Echo Request/Reply,但 TCP、UDP 仍正常工作。


六、配置 IPv6 Relay

确认路由器 WAN IPv6 正常后,开始处理 LAN。

修改前首先备份:

TS="$(date +%Y%m%d-%H%M%S)"

cp /etc/config/network "/etc/config/network.bak.$TS"
cp /etc/config/dhcp "/etc/config/dhcp.bak.$TS"
cp /etc/config/firewall "/etc/config/firewall.bak.$TS"

然后配置 WAN6 为 Relay Master:

uci -q delete dhcp.wan6

uci set dhcp.wan6='dhcp'
uci set dhcp.wan6.interface='wan6'

uci set dhcp.wan6.ra='relay'
uci set dhcp.wan6.dhcpv6='relay'
uci set dhcp.wan6.ndp='relay'
uci set dhcp.wan6.master='1'

LAN 同样使用 Relay:

uci set dhcp.lan.ra='relay'
uci set dhcp.lan.dhcpv6='relay'
uci set dhcp.lan.ndp='relay'

由于不再使用 OpenWrt 自己分配 IPv6 子网,因此去掉:

uci -q delete network.lan.ip6assign

保存:

uci commit dhcp
uci commit network

重启:

/etc/init.d/odhcpd restart

最开始还执行了一次:

/etc/init.d/network reload

结果 QWRT 的 Qualcomm/QSDK 网络脚本输出了大量:

unknown operand
Permission denied

以及 Wi-Fi 重新初始化日志。

不过后面证明这些主要是 QWRT/QSDK 脚本本身比较混乱,与 IPv6 Relay 的核心功能无关。

后面的调试中就不再频繁 reload 整个 network,而是只重启:

/etc/init.d/odhcpd restart

七、Windows 成功获得校园公网 IPv6

Relay 生效后,Windows 的 ipconfig 中终于出现:

2001:da8:216:210d:940d:a7b4:f526:6566

以及临时地址:

2001:da8:216:210d:c06e:3c23:bd4a:4435

默认网关为 QWRT:

fe80::ded8:7bff:fe56:225b

IPv6 路由表也出现:

::/0
    → fe80::ded8:7bff:fe56:225b

2001:da8:216:210d::/64
    → On-link

因此 RA Relay 已经成功。

这里虽然:

ipconfig /renew6

会出现:

信号灯超时时间已到

但这并不代表 IPv6 获取失败。

因为公网 IPv6 地址主要已经通过 RA/SLAAC 获得,而不是必须依赖 DHCPv6 Stateful Address。


八、LAN 客户端为什么仍然不能访问公网 IPv6

Windows 虽然已经获得真实公网 IPv6,但最开始:

curl.exe -6 ...

仍然超时。

于是开始检查 NDP。

当时:

ip -6 route get Windows_IPv6

错误地显示:

dev eth4

也就是说内核认为 Windows 的 IPv6 地址就在 WAN 上。

而:

ip -6 neigh show proxy dev eth4

也没有 Windows 的公网 IPv6。

因此进行了临时验证:

ip -6 route replace "$WIN6/128" dev br-lan
ip -6 neigh replace proxy "$WIN6" dev eth4

此后:

ip -6 route get "$WIN6"

变成:

dev br-lan

Proxy NDP 中也能看到该地址。

这一步证明 NDP Relay 的方向判断是正确的。

但即使这样,Windows 访问公网仍然失败。

说明还有另一层问题。


九、发现校园网认证是按客户端 IPv6 地址进行的

接下来直接从 Windows 访问:

http://[2001:da8:216:30c9::a]/drcom/chkstatus

返回:

"result":0

并且 myv6ip 正是 Windows 自己当前使用的:

2001:da8:216:210d:c06e:3c23:bd4a:4435

这时问题彻底明确:

IPv6 Relay 已经把 Windows 接入校园 IPv6 网络,但学校 Portal 认为这个新的 IPv6 地址是另外一个未认证终端。

当时校园网官网在线终端中只有路由器 WAN IPv6:

2001:da8:216:210d:ded8:7cff:fe56:225c

而没有 Windows 的临时 IPv6。

因此不是 Relay 转发失败,而是:

Windows IPv6 → 校园网络可达
Windows IPv6 → 尚未通过 Portal 公网认证

十、Windows IPv6 完成校园认证

Windows 通过自己的 IPv6 地址访问 Portal。

期间曾经手动构造 /eportal/portal/login 请求,服务端返回了一个 ThinkPHP:

Fatal error:
Call to a member function toArray() on null

这个页面甚至包含了请求调试信息。

需要注意,这种错误页中的认证字段虽然不是明文密码,但其编码只是前面提到的简单 XOR,因此不应该把完整错误页面上传到公开论坛、GitHub 或公开日志中。

更重要的是,之后再次检查:

/drcom/chkstatus

发现:

"result":1

而:

v6ip

已经变成 Windows 当前 IPv6:

2001:da8:216:210d:c06e:3c23:bd4a:4435

说明 Windows IPv6 会话已经建立。

再次测试:

curl.exe -6 -I `
  --resolve "www.cloudflare.com:443:[2606:4700::6810:7c60]" `
  https://www.cloudflare.com/

终于得到:

HTTP/1.1 200 OK

至此 LAN 客户端的公网 IPv6 数据面也完全打通。


十一、最后一个问题:OpenClash 把 AAAA 记录屏蔽了

虽然指定 IPv6 地址访问成功,但普通执行:

curl.exe -6 https://www.cloudflare.com/

却得到:

Could not resolve host

检查 DNS:

nslookup www.cloudflare.com 192.168.100.1

只返回:

198.18.x.x

这是典型的 OpenClash Fake-IP。

进一步查看 OpenClash:

uci show openclash | grep -Ei 'ipv6|dns'

发现:

openclash.config.ipv6_enable='0'
openclash.config.ipv6_dns='0'

Clash YAML 中也是:

dns:
  ipv6: false
  enhanced-mode: fake-ip

所以问题不是 Windows IPv6,而是:

OpenClash DNS 主动把 AAAA 查询结果屏蔽了。


十二、调整 OpenClash:IPv4 使用代理,IPv6 保持直连

最终目标是:

IPv4 → OpenClash

IPv6 → 校园网直连

DNS → 同时返回 A 和 AAAA

因此不需要开启 OpenClash 的 IPv6 流量接管,只需要允许 DNS 返回 IPv6。

先设置:

uci set openclash.config.ipv6_dns='1'
uci commit openclash

随后又将增强模式由:

fake-ip

改成:

redir-host

最终配置:

uci set openclash.config.en_mode='redir-host'
uci set openclash.config.ipv6_enable='0'
uci set openclash.config.ipv6_dns='1'

uci commit openclash

重启:

/etc/init.d/openclash restart

然后:

/etc/init.d/dnsmasq restart

最终 UCI:

en_mode = redir-host
ipv6_enable = 0
ipv6_dns = 1

Windows 清空 DNS:

ipconfig /flushdns

重新查询:

nslookup www.cloudflare.com 192.168.100.1

此时已经能同时得到真实 IPv4:

104.16.124.96
104.16.123.96

以及真实 IPv6:

2606:4700::6810:7b60
2606:4700::6810:7c60

再查询:

Resolve-DnsName www.cloudflare.com `
  -Type AAAA `
  -Server 192.168.100.1

也能正常返回 AAAA。

最终:

curl.exe -6 -I https://www.cloudflare.com/

直接:

HTTP/1.1 200 OK

到这里,DNS 问题也解决。


十三、验证 NDP Relay 是否真的可以动态工作

前面为了诊断曾经手工添加过:

ip -6 route replace "$WIN6/128" dev br-lan

ip -6 neigh replace proxy "$WIN6" dev eth4

这些命令不能作为最终方案。

因为 Windows 使用 IPv6 Privacy Extension 后,临时 IPv6 地址会变化。

如果每换一个 IPv6 都要手动加 /128,显然没有意义。

因此最后专门测试 odhcpd 是否能够自动学习。

先删除针对 Windows 当前地址的手工规则:

ip -6 route del "$WIN6/128" dev br-lan

ip -6 neigh del proxy "$WIN6" dev eth4

然后把 odhcpd 日志提高到 Debug:

uci set dhcp.odhcpd.loglevel='7'
uci commit dhcp

/etc/init.d/odhcpd restart

重启后再次查看,发现 /128 路由已经自动出现:

2001:da8:216:210d:c06e:3c23:bd4a:4435
dev br-lan
proto static

Proxy NDP 也自动出现:

2001:da8:216:210d:c06e:3c23:bd4a:4435 proxy

更关键的是日志明确显示:

Netlink newneigh ... on lan

Added proxy neighbour entry ... on wan6

Learning about proxy routing for ... on lan

还可以看到:

Got a RA on wan6
Forward a RA on lan

以及:

Got a DHCPv6-request on lan
Sending a DHCPv6-relay-forward on wan6

这说明三部分全部正常:

RA Relay
DHCPv6 Relay
NDP Relay

随后 Windows 再次强制使用这个 IPv6:

curl.exe -6 -v `
  --interface "2001:da8:216:210d:c06e:3c23:bd4a:4435" `
  --resolve "www.cloudflare.com:443:[2606:4700::6810:7c60]" `
  https://www.cloudflare.com/

成功:

Established connection
HTTP/1.1 200 OK

因此可以确认:

最终工作状态完全依赖 odhcpd 的动态 NDP Relay,而不是我们之前临时添加的静态 /128。

测试完成后恢复正常日志等级:

uci set dhcp.odhcpd.loglevel='4'
uci commit dhcp

/etc/init.d/odhcpd restart

十四、最终配置

最终 odhcpd 为:

dhcp.wan6.interface='wan6'

dhcp.wan6.ra='relay'
dhcp.wan6.dhcpv6='relay'
dhcp.wan6.ndp='relay'
dhcp.wan6.master='1'

dhcp.lan.ra='relay'
dhcp.lan.dhcpv6='relay'
dhcp.lan.ndp='relay'

最终 OpenClash:

en_mode='redir-host'

ipv6_enable='0'
ipv6_dns='1'

整个网络现在的逻辑变成:

                  ┌── IPv4 ── OpenClash
Windows ─ QWRT ───┤
                  └── IPv6 ── BJUT IPv6 ── Internet

IPv6 这一侧进一步展开就是:

Windows
   │
   │ 2001:da8:216:210d::/64
   ↓
br-lan
   │
   │ RA / DHCPv6 / NDP Relay
   ↓
QWRT odhcpd
   │
   ↓
eth4 / wan6
   │
   ↓
北工大校园 IPv6
   │
   ↓
Internet

十五、几个最容易误判的地方

这次最大的几个坑其实都非常典型。

首先是没有 DHCPv6-PD。WAN 拿到 /64 并不意味着 LAN 能直接通过 ip6assign 获得一个公网子网。这种情况下需要的是 Relay,而不是继续尝试 Prefix Delegation。

其次是 ping6。这次无论路由器还是 Windows,都出现过:

ping6 100% 丢包

但 HTTPS、UDP DNS 全部正常。因此实际网络诊断应该至少使用:

DNS
TCP
HTTPS

而不能只依赖 ICMP Echo。

第三是 OpenClash。最初 IPv6 数据面已经通了,但由于:

dns.ipv6 = false

导致应用根本得不到 AAAA,所以表面现象仍然是“IPv6 上不了网”。

第四是 Fake-IP。Fake-IP 对纯 IPv4 代理环境很方便,但在这次:

IPv4 代理
IPv6 直连

的混合环境里,redir-host + AAAA 更容易保持真实 IPv6 地址解析。

第五是校园认证。Relay 解决的是网络连通问题,并不会自动让 LAN 中新出现的 IPv6 地址继承另一个 IPv6 地址的认证状态。实际测试说明校园 Portal 会识别客户端 IPv6,因此客户端地址变化以后可能需要按校园网正常流程重新认证。


十六、最终验证方法

以后如果怀疑配置失效,不需要重新走整套排查。

先在 Windows 看:

ipconfig

应该存在:

2001:da8:216:210d:xxxx:xxxx:xxxx:xxxx

然后:

Resolve-DnsName www.cloudflare.com `
  -Type AAAA `
  -Server 192.168.100.1

应该得到真实:

2606:4700::...

最后:

curl.exe -6 -I https://www.cloudflare.com/

出现:

HTTP/1.1 200

即可说明:

IPv6 地址获取正常
DNS AAAA 正常
NDP Relay 正常
公网 IPv6 正常

如果突然只能访问校园门户,公网 IPv6 不通,则优先检查:

/drcom/chkstatus

中的:

result

是否仍为:

1

如果变成 0,很可能只是终端换了新的临时 IPv6,需要重新完成正常校园网认证,而不是路由器 Relay 配置坏了。


结论

这次最终解决方案的本质并不是“给 OpenWrt 开个 IPv6 开关”,而是把三个层面分别处理:

第一层:校园 IPv6 认证
        ↓
确认 WAN IPv6 真正拥有公网访问权限

第二层:IPv6 Relay
        ↓
利用 odhcpd 将学校同一个 /64
通过 RA / DHCPv6 / NDP Relay 延伸至 LAN

第三层:OpenClash DNS
        ↓
允许 AAAA 返回
同时保持 IPv6 不由 OpenClash 接管

最终不需要 NAT66,也不需要给每台电脑写死 IPv6 /128 路由,更不需要长期维护静态 Proxy NDP。

正常情况下 odhcpd 会根据 LAN 邻居自动创建对应的客户端 /128 路由和 WAN Proxy NDP。

现在的最终状态就是:

路由器 WAN IPv6:正常
校园 IPv6 认证:正常
LAN 公网 IPv6:正常
RA Relay:正常
DHCPv6 Relay:正常
NDP Relay:正常
OpenClash IPv4:正常
AAAA DNS:正常
Windows IPv6 HTTPS:正常

 

 

文章由AI生成

#
By YORU NO
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇