宵闇に まどろむ字句が いま起きる
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)session = requests.Session()#!/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"cp /tmp/upload/main.sh /root/main.sh# 每 2 分钟执行一次脚本
*/2 * * * * (sleep 10; bash /root/main.sh -u 123456 -p 'password')# eg. 每天凌晨 3:00 延时 60 秒后重启一次
* 3 * * * sleep 60 && touch /etc/banner && reboot
终于快放假了~总算有点时间复盘记录下最近折腾的一些东西。嘿嘿!是动手的快乐ヾ(≧▽≦*)o
博主在去年刚入学的时候在营业厅办了一张校园网卡(套餐 39 元含宽带),却没有在学校系统登记,也没有找到管理人员,于是大一一年里每个月都要再多交 20 元(哭),直到前段时间新生入学才完成了校园网的绑定
问了问室友,emm 好像就我一个办了卡。既然已经做了冤大头,那么,就共享给室友用吧,同时也可以让本不能登录校园网的 IoT 设备联网
校园网认证
博主学校使用的是武汉雨滴科技有限公司的认证计费系统,据说武汉很多高校都采用此方案。但不同厂商的认证逻辑都大同小异,因此本文对于大多数学校都适用
校园网的无线连接与有线连接一般都为无密码开放网络,在接入网络时,路由器会向设备分配内网 IP 地址并记录设备 MAC 地址。由于校园网内设备数量较多,因此一般使用的是 A 类保留地址 (10.0.0.0/8)
校园网登录采用的是强制认证门户 (Captive Portal) 技术,因此接入网络后并不能直接上网,部分操作系统会提示无互联网连接,点击按钮或在浏览器输入任意地址并访问即可跳转至登录页面
此时尝试使用 dig 命令进行 DNS 查询,发现 DNS 服务器可以正常返回域名的 IP 地址
可以判断认证页的跳转不是通过 DNS 劫持实现的,而是通过拦截 HTTP 请求至网关,网关丢弃原始数据包并返回重定向响应。我们可以使用 curl -i 验证
打开登录页,用浏览器开发人员工具记录网络请求,随后完成登录。不难看出,登录操作是通过一个 POST 请求来完成的。对该请求的请求头及表单数据进行分析得知,登录时除账号密码外还需要两个参数 nasId 和 csrf-token,其中 nasId 可以从重定向后的 URL 中获取,csrf-token 则是通过先前的请求得到的
那么理论上只需要拿到这两个参数并完成 POST 请求就可以实现校园网登录了,我们可以写一个简单的 Python 脚本来验证
这里的 http://www.msftconnecttest.com/redirect 是微软用于检测网络情况并生成重定向的地址,你也可以使用其他类似的地址
可以看到 nasId 和 csrf-token 均能正确获取,但为什么网关仍然会返回令牌不匹配的错误呢?
我们知道,访问某个网页时客户端与服务端会产生一个会话 (Session)。在先前的代码中,三次请求都是直接使用 requests 来发起请求,而直接调用 requests 会创建一个新的会话。也就是说,获取 csrf-token 和登录的两次请求会话不一致
方便的是,可以用 requests 的 requests.Session() 类来创建一个会话
随后将 requests.get / requests.post 方法用 session.get / session.post 替换即可
大功告成!如果不想使用 Python 的话,我们也可以使用 curl 对其进行改写以适配 Linux 系统
相关代码已开源至 GitHub,你也可以根据以上流程来适配自己学校的校园网认证系统。无法上网的时候只需运行脚本即可完成登录,是不是比打开浏览器输入账号密码要方便多啦!
设备数限制
在登录过程中,或许有细心的小伙伴发现,你的设备的 MAC 地址被记录了下来,这会被被用于无感知登录。当已经完成认证的设备再次连接时,由于该设备的 MAC 地址存在于记录中,网关会自动完成该设备的认证并与 IP 地址关联,放行该设备的流量
那么设备数限制的原理就很简单了,为每个账号限制可认证的 MAC 地址数量,超过限制数量后自动删除最早的记录,并将对应的设备下线
要想绕过限制也很容易,让小于限制数量的设备与校园网相连接,其他设备再与该设备连接。最简单的方法就是开热点
那有什么稳定又效果好的方案呢?让我们有请路由器登场
这是博主在宿舍使用的京东云赵云 (JDC-BE6500),也是为数不多支持刷机的 WiFi7 路由器之一,不过在这里谈刷机还为时尚早
路由器背后的网线接口一般分为 WAN 和 LAN 两种接口,广域网接口 (WAN) 用于连接运营商 (ISP) 网络或连接上级调制解调器、交换机等设备,局域网接口 (LAN) 用于连接局域网内的设备
如果你的校园网支持无感认证,并且路由器支持 MAC 地址克隆,那么你可以把路由器的 MAC 地址修改为电脑或手机的 MAC 地址,再用网线将 WAN 接口与校园网连接,路由器设置为 DHCP 模式,但请不要在 WAN 接口上提供 DHCP 服务,否则可能会因 IP 地址冲突造成全校断网。这样通过电脑或手机认证后,连上路由器,路由器便可以自动完成无感认证,这是最简单的一种方式,但不是博主采用的方案
部分学校的宽带可能是 PPPoE 协议拨号上网,这种宽带一般没有限制设备数量的问题,因此不在本文讨论范围内
当然你也可以先查看路由器的 MAC 地址,再将电脑的 MAC 地址修改为路由器的 MAC 地址,随后完成登录,这同样是利用校园网的无感认证来实现路由器的联网。修改电脑网卡的 MAC 地址不在本文讨论范围内
软路由
选择一款合适的路由器
并不是所有的路由器都可以刷机,所以在动手前先查查自己的路由器是否支持 OpenWrt
除此之外,你也应该注意路由器 SoC 的性能、内存大小、eMMC 的存储容量,不然即使成功刷入了系统,较差的扩展性也会让你失去刷机的乐趣
博主在 WiFi7、配置、价格等多方面因素考虑下选择了使用 ipq-53xx 方案,1G RAM 和 128G ROM 的京东云赵云 (JDC-BE6500),但可惜的是这款路由器并不支持免拆刷机
刷机
先找到对应的固件和刷机教程,博主参考的是恩山论坛 HugoYan 的这篇帖子
找好伙伴借齐工具,开干!
先焊好 TTL(这里多焊了 VCC)
没有镊子用来短接 eMMC,那就上万用表电流档吧,成功中断 U-Boot 进入命令行
随后刷入 U-Boot 和固件,重启后就可以在浏览器输入 192.168.1.1 进入管理页面了
路由器配置
博主使用的是 QWRT 固件,初始管理员密码为 root 和 password。首次登录时会出现引导式配置,你需要根据提示修改管理员密码,设置 SSID 和密码
与上文相同,用网线将 WAN 接口与校园网连接,路由器设置为 DHCP 模式,但不要在 WAN 接口上提供 DHCP 服务。不过这里就不需要修改路由器 MAC 地址了
(忘记截图了所以这里没有图图)
此时你的路由器如果你的配置正确,用 WiFi 或网线与路由器连接,用浏览器访问任意地址,会被重定向到校园网认证页面
自动认证
将你的登录脚本上传至路由器,如果使用 Web 页面提供的文件上传功能会保存至 /tmp/upload/ 目录,此时你需要打开终端,将你的脚本复制一份至 /tmp/ 以外的路径,例如 /root/
需要注意的是,如果你使用的是 Windows 系统,上传文件前需要先修改文件换行符,否则可能会出现报错
随后你可以在计划任务中使用 Cron 表达式配置脚本的定时运行
注意,如果你有定时重启的需求,一定要在 reboot 命令前添加 sleep 延时执行,由于 OpenWrt 系统时间在重启后且未与 NTP 服务器校时前仍是重启时的时间,不添加 sleep 命令会导致无限重启
到这里,你就可以拉上你的室友平摊网费,或是把各种 IoT 设备连上网,enjoy~