Rewrite as Windows Wi-Fi monitor service

This commit is contained in:
2026-04-24 10:44:28 -04:00
parent 955e636d5f
commit 18cc9b6bab
15 changed files with 2190 additions and 539 deletions

275
README.md
View File

@@ -1,60 +1,263 @@
# OSU Public Wi-Fi Auto Login
# OSU Public Wi-Fi Login
自动登录 OSUOhio State University公共 Wi-Fi 的脚本。通过 Selenium 驱动 Edge 浏览器,自动完成 Captive Portal 的条款确认和登录操作
适用于 Windows 11 的 OSU Wi-Fi 后台守护程序。它会持续监控无线网络状态,并按配置自动修复连接
## 工作原理
这个重写版本选择了 Python而不是 PowerShell 或 Rust原因是
1. 检测当前网络是否已连接(通过 HTTP 204 / connecttest 验证)
2. 若未连接,使用 headless Edge 浏览器访问 Captive Portal 触发 URL自动尝试多个备选地址
3. 自动勾选 "I accept the terms of use" 并点击 "Log In"
4. 登录后轮询验证网络是否真正连通,失败则自动重试(最多 3 次)
- `WiFi@OSU` Captive Portal 可以直接用 HTTP 表单提交流程处理,不依赖浏览器驱动
- 如果 portal 页面结构比较复杂,程序会自动回退到 Playwright 驱动已安装的 Microsoft Edge
- Windows 下调用 `netsh`、修改注册表、接 WinSW 都很直接
- 后续想打包成单文件 `exe` 也比较方便
## 功能
- 后台常驻运行,而不是一次性触发
- 可在 `WiFi@OSU``eduroam` 之间切换
- 支持 YAML 配置网络类型和检查/重试时间
- `WiFi@OSU` 模式下:
- 启动时如果 Wi-Fi 还没连上,会主动尝试连接目标网络
- 可选启用随机 MAC
- 可按周期刷新 MAC 并重连
- 自动打开 Captive Portal 并完成条款确认/登录
- `eduroam` 模式下:
- 启动时如果 Wi-Fi 还没连上,会主动尝试连接目标网络
- 使用系统已保存的凭据
- 可恢复为硬件 MAC
- 仅做断线检测和自动重连
- 支持 WinSW 包装为 Windows 服务
## 项目结构
```text
main.py CLI 入口
osu_wifi_login/config.py YAML 配置加载
osu_wifi_login/windows.py netsh / 注册表 / 连通性检测
osu_wifi_login/portal.py HTTP Portal 登录
osu_wifi_login/service.py 常驻监控与恢复逻辑
config.example.yaml 配置示例
winsw/ WinSW 服务模板
```
## 环境要求
- Python >= 3.14
- Microsoft Edge 浏览器
- [uv](https://docs.astral.sh/uv/) 包管理器
- Windows 11 x86-64
- Python 3.11+
- Microsoft Edge
- [uv](https://docs.astral.sh/uv/)
## 安装
```bash
```powershell
uv sync
```
## 使用
仓库已经附带默认的 `config.yaml`,直接编辑即可;如果想恢复模板,也可以参考 `config.example.yaml`
如果 `WiFi@OSU` portal 页面较复杂,运行时会使用 Playwright 调用本机已安装的 Edge所以第一次改完依赖后需要先完成一次 `uv sync`
```bash
uv run main.py
## 配置
默认配置文件是根目录下的 `config.yaml`
最常用的项如下:
```yaml
selected_network: wifi_osu
wifi_interface_name: Wi-Fi
allow_unsafe_mac_changes: false
randomize_mac_on_start: false
networks:
wifi_osu:
ssid: WiFi@OSU
profile_name: WiFi@OSU
requires_portal_login: true
randomize_mac: false
restore_hardware_mac: false
auto_create_open_profile: true
mac_refresh_hours: 6
eduroam:
ssid: eduroam
profile_name: eduroam
requires_portal_login: false
randomize_mac: false
restore_hardware_mac: true
auto_create_open_profile: false
connectivity_checks:
- url: http://example.com/
expected_status: 200
expected_text: Example Domain
require_final_url_match: true
allow_redirects: false
```
### 可选参数
说明:
| 参数 | 说明 |
|------|------|
| `--random-mac` | 登录前随机化 Wi-Fi 网卡的 MAC 地址(需要**管理员权限** |
- `selected_network` 设为 `wifi_osu``eduroam`
- `wifi_interface_name` 一般是 `Wi-Fi`,如果你的系统接口名不同,需要改成实际值
- `profile_name` 是 Windows 已保存的 WLAN 配置名,通常与 SSID 相同
- `auto_create_open_profile` 适合 `WiFi@OSU` 这类开放网络;如果本机还没有保存过 profile程序会先自动创建一个基础 profile 再连接
- `connectivity_checks` 默认使用像 `example.com` 这样的普通页面,不再使用 Windows/Apple/Firefox 的系统探针地址,避免被 portal 白名单误判成“已联网”
- `allow_unsafe_mac_changes` 默认关闭;关闭时不会写注册表改 `NetworkAddress`
- `randomize_mac``restore_hardware_mac` 都只有在 `allow_unsafe_mac_changes: true` 时才会生效
- 某些无线网卡驱动在修改 MAC 时会直接蓝屏,建议默认保持关闭
- `connect_retry_cooldown_seconds` 控制“Wi-Fi 完全没连上时”主动重连的频率
- `disconnect_grace_seconds` 表示断线多久后开始强制恢复
- `connection_timeout_seconds` 会用于登录后等待网络放行,默认给 captive portal 留 60 秒
- `mac_refresh_hours` 只对 `WiFi@OSU` 生效
示例:
## 运行
```bash
# 普通登录
uv run main.py
前台调试运行:
# 随机 MAC 地址后登录
uv run main.py --random-mac
```powershell
.\.venv\Scripts\python.exe main.py --config config.yaml
```
> **注意**`--random-mac` 会通过修改注册表并重启网卡来更改 MAC 地址,需要以管理员身份运行。
只跑一次检查:
## Windows 开机自启
1.`Win + R`,输入 `shell:startup` 打开启动文件夹
2.`run.bat` 的快捷方式放入该文件夹
3. 修改 `run.bat` 中的路径为你的实际项目路径
## 打包为可执行文件
```bash
uv run pyinstaller --onefile main.py
```powershell
.\.venv\Scripts\python.exe main.py --config config.yaml --once
```
生成的 `main.exe` 位于 `dist/` 目录下。
## 服务逻辑
程序每轮会做这些事:
1. 检查当前是否连在目标 SSID 上
2. 如果 Wi-Fi 完全没连上,先直接尝试连接目标网络
3. 如果是 `WiFi@OSU`,刚连上后会主动探测 captive portal检测到登录页就立刻登录
4. 检查是否真的能上网
5. 如果断线或异常持续超过阈值,则重启 Wi-Fi 网卡并重新连接
6. 如果你显式开启了高风险 MAC 改写,才会在启动时和刷新周期到达时改 MAC 并重连
## 管理员权限
以下操作需要管理员权限:
- 修改 `NetworkAddress` 注册表项
-`WiFi@OSU` 随机化 MAC
- 清除随机 MAC恢复硬件 MAC
- 重启无线网卡
其中 MAC 相关操作在部分驱动上可能导致蓝屏;现在默认关闭,只有在你明确打开 `allow_unsafe_mac_changes: true` 后才会执行。
## 编译发布
推荐使用 PyInstaller 的 `onedir` 模式发布。这个模式会生成一个完整目录,里面包含 `exe`、Python 运行时、第三方依赖和 Playwright 驱动文件;目标机器仍需要安装 Microsoft Edge但不需要安装 Python、uv 或项目依赖。
```powershell
uv sync
uv run pyinstaller --noconfirm --clean --onedir --name osu-wifi-login main.py
```
生成结果位于:
```text
dist\osu-wifi-login\osu-wifi-login.exe
```
`config.yaml` 放到同一个发布目录中:
```powershell
Copy-Item config.yaml dist\osu-wifi-login\config.yaml
```
发布目录最终至少应包含:
```text
dist\osu-wifi-login\
osu-wifi-login.exe
config.yaml
_internal\
```
前台验证:
```powershell
.\dist\osu-wifi-login\osu-wifi-login.exe --config .\dist\osu-wifi-login\config.yaml --once
```
也可以生成真正的单文件 `exe`
```powershell
uv run pyinstaller --noconfirm --clean --onefile --name osu-wifi-login main.py
```
不过不建议优先使用 `onefile`。Playwright 会在运行时解包和查找驱动文件,`onedir` 更稳定;`onefile` 虽然只有一个 `exe`但启动更慢也更容易遇到服务账户临时目录权限问题。无论使用哪种模式Microsoft Edge 仍需要由系统提供,因为程序使用的是已安装 Edge 渠道。
## WinSW 服务
仓库中已经提供:
- [winsw/osu-wifi-login.xml](/C:/Users/yuanzhe/src/OSU-Public-Wi-Fi-Login/winsw/osu-wifi-login.xml)
- [winsw/README.md](/C:/Users/yuanzhe/src/OSU-Public-Wi-Fi-Login/winsw/README.md)
### 使用编译后的 exe
1. 下载 WinSW x64 可执行文件
2. 将 WinSW 重命名为 `osu-wifi-login-service.exe`
3.`osu-wifi-login-service.exe` 放入 `dist\osu-wifi-login\`
4. 在同一目录创建 `osu-wifi-login-service.xml`
`dist\osu-wifi-login\osu-wifi-login-service.xml` 示例:
```xml
<service>
<id>osu-wifi-login</id>
<name>OSU Wi-Fi Login Service</name>
<description>Keeps WiFi@OSU or eduroam connected and logs into the captive portal when needed.</description>
<executable>%BASE%\osu-wifi-login.exe</executable>
<arguments>--config "%BASE%\config.yaml"</arguments>
<workingdirectory>%BASE%</workingdirectory>
<log mode="roll-by-size">
<sizeThreshold>1048576</sizeThreshold>
<keepFiles>8</keepFiles>
</log>
<onfailure action="restart" delay="10 sec" />
<stoptimeout>30 sec</stoptimeout>
</service>
```
以管理员 PowerShell 安装并启动:
```powershell
Set-Location .\dist\osu-wifi-login
.\osu-wifi-login-service.exe install
.\osu-wifi-login-service.exe start
```
查看状态、停止、卸载:
```powershell
.\osu-wifi-login-service.exe status
.\osu-wifi-login-service.exe stop
.\osu-wifi-login-service.exe uninstall
```
### 服务账户建议
默认不写 `<serviceaccount>`WinSW 通常使用 `LocalSystem`。这个程序需要能访问 WLAN profile、启动 Edge 自动化并执行 `netsh`,更推荐使用你自己的 Windows 用户运行服务。
如果要指定服务账户,在 XML 中加入:
```xml
<serviceaccount>
<domain>.</domain>
<user>YOUR_WINDOWS_ACCOUNT</user>
<password>YOUR_PASSWORD</password>
<allowservicelogon>true</allowservicelogon>
</serviceaccount>
```
如果你保持 `allow_unsafe_mac_changes: false`,通常不需要管理员权限来修改 MAC但重启网卡和某些 `netsh` 操作仍可能需要提升权限。若服务日志提示权限不足,再改用管理员账户运行服务。
## 当前注意事项
- `WiFi@OSU` 的 Captive Portal 表单字段仍然基于当前已知页面结构;如果学校改版,可能需要微调 YAML 或代码
- 现在默认不依赖 `msedgedriver`;复杂页面会自动回退到 Playwright + 已安装 Edge