一个基于 ESP-IDF 开发的 ESP32 WiFi Captive Portal(强制门户)演示项目。该项目创建一个 WiFi 热点,当设备连接后会自动弹出 Web 页面。
- WiFi 热点(SoftAP): 自动生成唯一 SSID,支持多设备连接
- DNS 劫持: 将所有 DNS 查询重定向到 ESP32 IP 地址
- Captive Portal: 设备连接后自动弹出 Web 页面
- 嵌入式 Web 页面: HTML 文件嵌入固件,无需外部存储
- C++ 实现: 主程序使用 C++ 编写
- ESP32 开发板(如 ESP32-DevKitC、ESP-WROVER-KIT 等)
- USB 数据线
- ESP-IDF v5.0 或更高版本
- Python 3.8+
- CMake 3.16+
如果你没有 ESP-IDF 开发环境,可以直接使用预编译的二进制文件通过在线工具烧录。
从项目的 release/merged-binary.bin 下载预编译的二进制文件。
- 打开 ESP Launchpad 在线烧录工具
- 选择对应的 ESP32 芯片型号
- 点击"Connect"连接设备(需要浏览器支持 Web Serial)
- 选择下载的
merged-binary.bin文件,设置烧录地址为0x0 - 点击"Program"开始烧录
注意:
- 需要使用支持 Web Serial 的浏览器(推荐 Chrome、Edge)
- 预编译的二进制文件是按照默认配置编译的,如需自定义配置,请使用方式二从源码构建
git clone https://github.com/shenjingnan/esp32-wifi-demo.git
cd esp32-wifi-demo# 如果已安装 ESP-IDF,激活环境
. $HOME/esp/esp-idf/export.sh
# 或使用别名(如果已配置)
get_idfidf.py build# 连接 ESP32 开发板,然后执行
idf.py -p PORT flash
# 例如:
# idf.py -p /dev/ttyUSB0 flash # Linux
# idf.py -p COM3 flash # Windows
# idf.py -p /dev/tty.usbserial-110 flash # macOSidf.py -p PORT monitor
# 也可以一步完成构建、烧录和监控
idf.py -p PORT flash monitor- 烧录完成后,ESP32 会创建一个 WiFi 热点
- 使用手机或电脑搜索 WiFi,SSID 格式为
ESP32_WIFI_XXXXXX(后缀为 MAC 地址后3字节) - 连接该 WiFi(无需密码)
- 大多数设备会自动弹出 Web 页面;如果没有,打开浏览器访问任意网站即可跳转
esp32-wifi-demo/
├── CMakeLists.txt # 根目录 CMake 配置
├── sdkconfig.defaults # SDK 默认配置
├── README.md # 项目说明文档
├── release/
│ └── merged-binary.bin # 预编译的二进制文件
├── main/
│ ├── CMakeLists.txt # main 组件 CMake 配置
│ ├── main.cc # 主程序源代码(C++)
│ └── index.html # 嵌入的 Web 页面
└── components/
└── dns_server/ # 自定义 DNS 服务器组件
├── CMakeLists.txt
├── dns_server.c
└── include/
└── dns_server.h
┌─────────────────────────────────────────────────────────────────┐
│ ESP32 设备 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ WiFi AP │ │ DNS Server │ │ HTTP Server │ │
│ │ (SoftAP) │ │ (Port 53) │ │ (Port 80) │ │
│ │ │ │ │ │ │ │
│ │ SSID: │ │ 拦截所有 │ │ ┌───────────────┐ │ │
│ │ ESP32_WIFI_ │───▶│ DNS 查询 │───▶│ │ GET / │ │ │
│ │ XXXXXX │ │ 返回本地 IP │ │ │ → index.html │ │ │
│ │ │ │ │ │ ├───────────────┤ │ │
│ │ IP: │ │ │ │ │ 404 Handler │ │ │
│ │ 192.168.4.1 │ │ │ │ │ → 302 → / │ │ │
│ └─────────────┘ └─────────────┘ │ └───────────────┘ │ │
│ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
sequenceDiagram
participant 用户设备
participant WiFi AP
participant DNS Server
participant HTTP Server
用户设备->>WiFi AP: 1. 连接 WiFi
用户设备->>DNS Server: 2. DNS 查询(检测网络)
DNS Server-->>用户设备: 3. 返回 192.168.4.1
用户设备->>HTTP Server: 4. HTTP GET(检测 URL)
HTTP Server-->>用户设备: 5. 302 重定向 → /
用户设备->>HTTP Server: 6. GET /
HTTP Server-->>用户设备: 7. 返回 HTML 页面
| 组件 | 功能 |
|---|---|
| WiFi AP | 创建开放热点,SSID 基于 MAC 地址生成 |
| DNS Server | 将所有 A 记录查询重定向到 ESP32 IP |
| HTTP Server | 提供 Web 页面,404 重定向实现 Portal |
| 参数 | 值 | 说明 |
|---|---|---|
| WiFi 模式 | WIFI_MODE_AP |
接入点模式 |
| SSID 格式 | ESP32_WIFI_XXXXXX |
MAC 地址后3字节 |
| 认证方式 | WIFI_AUTH_OPEN |
开放,无密码 |
| 最大连接数 | 4 | 同时最多4个设备 |
| 默认 IP | 192.168.4.1 |
ESP-IDF 默认 AP IP |
| DNS 端口 | 53 | 标准 DNS 端口 |
| HTTP 端口 | 80 | 标准 HTTP 端口 |
编辑 main/index.html 文件,修改后重新构建烧录即可。
在 main/main.cc 中修改相关参数:
wifi_config_t wifi_config = {};
strcpy(reinterpret_cast<char *>(wifi_config.ap.ssid), "你的SSID");
wifi_config.ap.ssid_len = strlen("你的SSID");
wifi_config.ap.max_connection = 8; // 最大连接数
wifi_config.ap.authmode = WIFI_AUTH_WPA2_PSK; // 使用密码
strcpy(reinterpret_cast<char *>(wifi_config.ap.password), "你的密码");在 main/main.cc 中修改 DNS 服务器配置:
dns_server_config_t config = DNS_SERVER_CONFIG_SINGLE("*", "WIFI_AP_DEF");
// "*" 表示匹配所有域名
// 可以指定特定域名,如 "example.com"- 部分设备需要手动打开浏览器访问任意网站
- iOS 设备可能需要等待几秒钟
- Android 设备可能需要点击"登录"或"连接"按钮
- 确认 ESP32 已正确烧录
- 检查日志输出确认 WiFi AP 是否正常启动
- 尝试重启 ESP32
- 确认 ESP-IDF 版本 >= 5.0
- 执行
idf.py fullclean后重新构建 - 检查 Python 依赖是否完整安装
本项目采用 MIT 许可证,详见 LICENSE 文件。