[esp32] Captive Portal
ESP32 Captive Portal 自动弹出原理
1. 功能概述
手机连接 ESP32 的 SoftAP 后,Android 或 iOS 会自动弹出配网页面。
这个页面并不是 ESP32 主动命令手机打开的,而是手机操作系统检测到当前 Wi-Fi 存在 Captive Portal 后,主动打开系统配网窗口。
当前实现结合了以下三种机制:
- DHCP Option 114 声明配网页面地址。
- DNS 劫持将所有域名解析到 ESP32。
- HTTP Server 将未知路径重定向到配网页面。
2. 手机连接 Wi-Fi 后的行为
手机连接 Wi-Fi 后,通过 DHCP 获取以下网络参数:
- IP 地址
- 子网掩码
- 默认网关
- DNS Server
- Captive Portal 地址
ESP32 SoftAP 通常分配:
手机地址:192.168.4.2
网关地址:192.168.4.1
DNS 地址:192.168.4.1
ESP32 还通过 DHCP Option 114 告诉手机:
Captive Portal URL = http://192.168.4.1/
支持 DHCP Option 114 的操作系统可以直接知道配网页面的地址。
3. 操作系统联网检测
手机连接 Wi-Fi 后,会主动访问操作系统预设的 HTTP 地址,判断当前网络是否能够访问互联网。
常见检测地址如下:
Android:
http://connectivitycheck.gstatic.com/generate_204
iOS:
http://captive.apple.com/hotspot-detect.html
Windows:
http://www.msftconnecttest.com/connecttest.txt
操作系统期望收到特定响应:
| 系统 | 预期响应 |
|---|---|
| Android | HTTP 204 No Content |
| iOS | 包含固定 Success 内容的页面 |
| Windows | 固定的文本内容 |
如果收到预期响应,系统认为网络可以正常访问互联网。
如果收到重定向、配网页面或其他内容,系统会认为当前网络需要进行网页登录认证。
4. DNS 劫持
ESP32 在 UDP 53 端口运行 DNS Server。
DNS Server 会将客户端发来的所有 IPv4 A 记录查询都解析为 SoftAP 地址:
任意域名 -> 192.168.4.1
例如手机查询:
connectivitycheck.gstatic.com
ESP32 返回:
connectivitycheck.gstatic.com -> 192.168.4.1
因此手机原本发往互联网的联网检测请求,最终会发送到 ESP32 的 HTTP Server。
5. HTTP 重定向
手机可能访问以下路径:
/generate_204
/hotspot-detect.html
/connecttest.txt
ESP32 当前只提供根路径:
/
当 HTTP Server 收到未注册的路径时,返回:
HTTP/1.1 303 See Other
Location: /
手机随后访问:
http://192.168.4.1/
ESP32 返回完整的配网页面。
6. 完整流程
手机连接 ESP32 SoftAP
|
v
通过 DHCP 获取 IP、网关和 DNS
|
v
DHCP Option 114 声明配网页面地址
|
v
手机发起系统联网检测
|
v
查询 connectivitycheck.gstatic.com 等域名
|
v
ESP32 DNS 返回 192.168.4.1
|
v
联网检测请求到达 ESP32 HTTP Server
|
v
未知路径返回 HTTP 303
|
v
重定向到根路径 /
|
v
ESP32 返回配网页面
|
v
系统判断当前 Wi-Fi 存在 Captive Portal
|
v
Android/iOS 自动弹出系统配网窗口
7. 各模块职责
DHCP Server
负责向客户端分配网络参数,并通过 Option 114 声明配网页面:
http://192.168.4.1/
Captive DNS Server
监听 UDP 53 端口,将所有 A 记录查询解析为:
192.168.4.1
HTTP Server
负责:
- 返回配网页面。
- 处理手机的联网检测请求。
- 将未知路径重定向到
/。
Android/iOS
负责:
- 主动检测网络连通性。
- 判断是否存在 Captive Portal。
- 打开系统配网窗口。
- 配网完成后重新检查互联网连接。
8. 为什么使用 HTTP 而不是 HTTPS
Captive Portal 主要依赖 HTTP 联网检测。
如果手机访问:
https://example.com
浏览器要求服务器提供与 example.com 匹配的 TLS 证书。
ESP32 无法提供任意网站的合法证书,因此 HTTPS 请求会产生证书错误,不能透明重定向到配网页面。
因此可以认为:
普通 HTTP 请求可以被引导到配网页面。
HTTPS 请求不能可靠劫持和重定向。
9. 配网页面不一定始终自动弹出
是否自动弹出最终由手机操作系统决定,以下情况可能影响弹窗:
- 手机启用了 Private DNS、DoH 或 DoT。
- 手机缓存了之前的 DNS 结果。
- 手机自动切换到蜂窝网络。
- 操作系统厂商修改了联网检测机制。
- 手机已经记住了该 Wi-Fi 的检测结果。
- 浏览器访问的是 HTTPS 或启用了 HSTS 的网站。
即使系统没有自动弹窗,用户仍然可以手动访问:
http://192.168.4.1/
进入配网页面。
10. 当前实现总结
当前 ESP32 Captive Portal 使用:
SoftAP
+ DHCP Option 114
+ 通配 DNS 解析
+ HTTP 303 重定向
+ HTML 配网页面
其本质是:
ESP32 将手机的联网检测请求引导到本地 HTTP Server,操作系统发现响应不符合互联网连通性检测要求,因此判定该 Wi-Fi 需要认证,并自动打开配网页面。