基于 OpenWrt 软路由实现校园网自动认证与绕过设备数限制

  • ~5.68K 字
  • 次阅读
  • 条评论
  1. 1. 校园网认证
  2. 2. 设备数限制
  3. 3. 软路由
    1. 3.1. 选择一款合适的路由器
    2. 3.2. 刷机
    3. 3.3. 路由器配置
    4. 3.4. 自动认证

终于快放假了~总算有点时间复盘记录下最近折腾的一些东西。嘿嘿!是动手的快乐ヾ(≧▽≦*)o

博主在去年刚入学的时候在营业厅办了一张校园网卡(套餐 39 元含宽带),却没有在学校系统登记,也没有找到管理人员,于是大一一年里每个月都要再多交 20 元(哭),直到前段时间新生入学才完成了校园网的绑定

问了问室友,emm 好像就我一个办了卡。既然已经做了冤大头,那么,就共享给室友用吧,同时也可以让本不能登录校园网的 IoT 设备联网

校园网认证

博主学校使用的是武汉雨滴科技有限公司的认证计费系统,据说武汉很多高校都采用此方案。但不同厂商的认证逻辑都大同小异,因此本文对于大多数学校都适用

校园网的无线连接与有线连接一般都为无密码开放网络,在接入网络时,路由器会向设备分配内网 IP 地址并记录设备 MAC 地址。由于校园网内设备数量较多,因此一般使用的是 A 类保留地址 (10.0.0.0/8)

路由器分配的 IP 地址

校园网登录采用的是强制认证门户 (Captive Portal) 技术,因此接入网络后并不能直接上网,部分操作系统会提示无互联网连接,点击按钮或在浏览器输入任意地址并访问即可跳转至登录页面

需要登录

此时尝试使用 dig 命令进行 DNS 查询,发现 DNS 服务器可以正常返回域名的 IP 地址

DIG

可以判断认证页的跳转不是通过 DNS 劫持实现的,而是通过拦截 HTTP 请求至网关,网关丢弃原始数据包并返回重定向响应。我们可以使用 curl -i 验证

重定向

打开登录页,用浏览器开发人员工具记录网络请求,随后完成登录。不难看出,登录操作是通过一个 POST 请求来完成的。对该请求的请求头及表单数据进行分析得知,登录时除账号密码外还需要两个参数 nasIdcsrf-token,其中 nasId 可以从重定向后的 URL 中获取,csrf-token 则是通过先前的请求得到的

表单数据

请求头

那么理论上只需要拿到这两个参数并完成 POST 请求就可以实现校园网登录了,我们可以写一个简单的 Python 脚本来验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import requests
from urllib.parse import urlparse, parse_qs

username = ""
password = ""

# 从重定向 URL 获取 nasId
resp = requests.get("http://www.msftconnecttest.com/redirect", allow_redirects=True)
parsed_url = urlparse(resp.url)
nasid = ""
nasid_list = parse_qs(parsed_url.query).get("nasId")
if nasid_list:
nasid = nasid_list[0]
print(nasid)

# 获取 csrf-token
resp = requests.get("http://172.30.21.100/api/csrf-token")
csrf = resp.json().get("csrf_token")
print(csrf)

# 登录
headers = {
"content-type": "application/x-www-form-urlencoded",
"x-csrf-token": csrf,
}
data = (
f"username={username}&password={password}"
f"&switchip=&nasId={nasid}&userIpv4=&userMac=&captcha=&captchaId="
)
resp = requests.post(
"http://172.30.21.100/api/account/login",
headers=headers,
data=data
)
print(resp.text)

这里的 http://www.msftconnecttest.com/redirect 是微软用于检测网络情况并生成重定向的地址,你也可以使用其他类似的地址

测试脚本

可以看到 nasIdcsrf-token 均能正确获取,但为什么网关仍然会返回令牌不匹配的错误呢?

我们知道,访问某个网页时客户端与服务端会产生一个会话 (Session)。在先前的代码中,三次请求都是直接使用 requests 来发起请求,而直接调用 requests 会创建一个新的会话。也就是说,获取 csrf-token 和登录的两次请求会话不一致

方便的是,可以用 requestsrequests.Session() 类来创建一个会话

1
session = requests.Session()

随后将 requests.get / requests.post 方法用 session.get / session.post 替换即可

测试脚本

大功告成!如果不想使用 Python 的话,我们也可以使用 curl 对其进行改写以适配 Linux 系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash

USERNAME=""
PASSWORD=""

SESSION=$(mktemp)

LOGIN_URL=$(curl -Ls -c "$SESSION" -b "$SESSION" -o /dev/null -w "%{url_effective}" "http://www.msftconnecttest.com/redirect")
NASID=$(printf '%s\n' "$LOGIN_URL" | sed -n 's/.*[?&]nasId=\([^&]*\).*/\1/p')

CSRF_TOKEN=$(curl -s -c "$SESSION" -b "$SESSION" "http://172.30.21.100/api/csrf-token" | sed -n 's/.*"csrf_token"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')

RESPONSE=$(curl -s -X POST "http://172.30.21.100/api/account/login" \
-c "$SESSION" -b "$SESSION" \
-H "content-type: application/x-www-form-urlencoded" \
-H "x-csrf-token: $CSRF_TOKEN" \
--data "username=$USERNAME&password=$PASSWORD&switchip=&nasId=$NASID&userIpv4=&userMac=&captcha=&captchaId=")

echo "$RESPONSE"

rm -f "$SESSION"

相关代码已开源至 Github,你也可以根据以上流程来适配自己学校的校园网认证系统。无法上网的时候只需运行脚本即可完成登录,是不是比打开浏览器输入账号密码要方便多啦!

设备数限制

在登录过程中,或许有细心的小伙伴发现,你的设备的 MAC 地址被记录了下来,这会被被用于无感知登录。当已经完成认证的设备再次连接时,由于该设备的 MAC 地址存在于记录中,网关会自动完成该设备的认证并与 IP 地址关联,放行该设备的流量

那么设备数限制的原理就很简单了,为每个账号限制可认证的 MAC 地址数量,超过限制数量后自动删除最早的记录,并将对应的设备下线

记录的 MAC 地址

要想绕过限制也很容易,让小于限制数量的设备与校园网相连接,其他设备再与该设备连接。最简单的方法就是开热点

那有什么稳定又效果好的方案呢?让我们有请路由器登场

路由器

这是博主在宿舍使用的京东云赵云 (JDC-BE6500),也是为数不多支持刷机的 WiFi7 路由器之一,不过在这里谈刷机还为时尚早

路由器背后的网线接口一般分为 WAN 和 LAN 两种接口,广域网接口 (WAN) 用于连接运营商 (ISP) 网络或连接上级调制解调器、交换机等设备,局域网接口 (LAN) 用于连接局域网内的设备

如果你的校园网支持无感认证,并且路由器支持 MAC 地址克隆,那么你可以把路由器的 MAC 地址修改为电脑或手机的 MAC 地址,再用网线将 WAN 接口与校园网连接,路由器设置为 DHCP 模式,但请不要在 WAN 接口上提供 DHCP 服务,否则可能会因 IP 地址冲突造成全校断网。这样通过电脑或手机认证后,连上路由器,路由器便可以自动完成无感认证,这是最简单的一种方式,但不是博主采用的方案

部分学校的宽带可能是 PPPoE 协议拨号上网,这种宽带一般没有限制设备数量的问题,因此不在本文讨论范围内

重设 MAC 地址

WAN 设置

当然你也可以先查看路由器的 MAC 地址,再将电脑的 MAC 地址修改为路由器的 MAC 地址,随后完成登录,这同样是利用校园网的无感认证来实现路由器的联网。修改电脑网卡的 MAC 地址不在本文讨论范围内

路由器 MAC 地址

软路由

选择一款合适的路由器

并不是所有的路由器都可以刷机,所以在动手前先查查自己的路由器是否支持 OpenWrt

除此之外,你也应该注意路由器 SoC 的性能、内存大小、eMMC 的存储容量,不然即使成功刷入了系统,较差的扩展性也会让你失去刷机的乐趣

博主在 WiFi7、配置、价格等多方面因素考虑下选择了使用 ipq-53xx 方案,1G RAM 和 128G ROM 的京东云赵云 (JDC-BE6500),但可惜的是这款路由器并不支持免拆刷机

刷机

先找到对应的固件和刷机教程,博主参考的是恩山论坛 HugoYan 的这篇帖子

找好伙伴借齐工具,开干!

摇人

先焊好 TTL(这里多焊了 VCC)

TTL

没有镊子用来短接 eMMC,那就上万用表电流档吧,成功中断 U-Boot 进入命令行

短接 eMMC

随后刷入 U-Boot 和固件,重启后就可以在浏览器输入 192.168.1.1 进入管理页面了

博主在刷入固件时遇到了无限重启的问题,在网上搜集了很多资料都没有成功解决,一度怀疑是刷坏了分区表,没想到恢复分区表的时候真把分区表扬掉了quq。于是 9008 救砖,又找外援远程操作,也不能解决重启的问题。最终偶然拔下 TTL 模块发现成功启动了,如果有大佬知道这是什么原理欢迎在评论区讲讲orz

路由器配置

博主使用的是 QWRT 固件,初始管理员密码为 rootpassword。首次登录时会出现引导式配置,你需要根据提示修改管理员密码,设置 SSID 和密码

与上文相同,用网线将 WAN 接口与校园网连接,路由器设置为 DHCP 模式,但不要在 WAN 接口上提供 DHCP 服务。不过这里就不需要修改路由器 MAC 地址了

(忘记截图了所以这里没有图图)

此时你的路由器如果你的配置正确,用 WiFi 或网线与路由器连接,用浏览器访问任意地址,会被重定向到校园网认证页面

自动认证

将你的登录脚本上传至路由器,如果使用 Web 页面提供的文件上传功能会保存至 /tmp/upload/ 目录,此时你需要打开终端,将你的脚本复制一份至 /tmp/ 以外的路径,例如 /root/

1
cp /tmp/upload/main.sh /root/main.sh

需要注意的是,如果你使用的是 Windows 系统,上传文件前需要先修改文件换行符,否则可能会出现报错

换行符

随后你可以在计划任务中使用 Cron 表达式配置脚本的定时运行

1
2
# 每 2 分钟执行一次脚本
*/2 * * * * (sleep 10; bash /root/main.sh -u 123456 -p 'password')

计划任务

注意,如果你有定时重启的需求,一定要在 reboot 命令前添加 sleep 延时执行,由于 OpenWrt 系统时间在重启后且未与 NTP 服务器校时前仍是重启时的时间,不添加 sleep 命令会导致无限重启

1
2
# eg. 每天凌晨 3:00 延时 60 秒后重启一次
* 3 * * * sleep 60 && touch /etc/banner && reboot

到这里,你就可以拉上你的室友平摊网费,或是把各种 IoT 设备连上网,enjoy~

赞助喵
非常感谢您的喜欢!
赞助喵
分享这一刻
让朋友们也来瞅瞅!