0%

使用ESP32C3开发板实现一个强制门户(Captive Portal)

开发板如上图所示,这本是LUATOS的开发板,但可惜我不会那一套工作链(虽然确实要简单一些),使用的还是IDF那一套。

强制门户是在授予新连接至Wi-Fi的用户更广的网络访问权限之前在其网页浏览器呈现中的网页,其常用于呈现可能需要认证或接受最终用户许可协议/可接受使用策略的着陆页或登录页。类似校园网的认证。

原理

终端设备在连接到WiFi之后,需要确定该WiFi是否能连接到互联网。厂商们的解决办法也很简单,就是向某个网址发起HTTP请求,如果能获得正确的数据,则证明这个WiFi能正常连接互联网。如果不行,则证明这个WiFi不能连接互联网。

比如苹果的设备会向http://captive.apple.com/hotspot-detect.html发送请求,直接打开会看到Success的字样。

这个过程的具体原理是这样的:

在这里面我们有机会下手的就是DNS Server,让终端设备获得错误的服务器IP,进而使得终端设备发送HTTP请求到错误的网站(即我们的HTML)。这种做法通常被称为DNS拦截,一般的设备在检测到DNS拦截后,都会自动弹出发送HTTP请求后返回的页面(通常情况下的认证页面)。

实现

建立DNS Server

终端设备连接到ESP32的WiFi后,默认的DNS IP就是ESP32的内网IP(一般为192.168.4.1)。

因此我们可以在ESP32上建立一个DNS Server,响应终端设备发起的DNS请求,并将所有的域名都解析到模块自己的IP上。

这样做的结果就是无论终端设备访问哪个域名来获取连通信息,都将被解析到ESP32自己。

例如,访问http://captive.apple.com/hotspot-detect.html会被拦截成http://192.168.4.1/hotspot-detect.html

建立HTTP Server

而当终端设备向ESP32发起HTTP请求后,捕获到的HTTP请求还需要做出相应的相应,才能让终端设备弹出网页。

因此我们还需要在ESP32上建立一个HTTP Server,响应终端设备发起的HTTP请求。

HTTP的底层协议是TCP,默认端口是80,所以我们只需要建立一个TCP服务器,监听80端口,收到请求后做出相应的回复。

代码实现

代码主要分为四部分,分别是:

  • main.c - 初始化ESP32;
  • dns_server - DNS服务器;
  • web_server - TCP服务器;
  • index.html - 返回的网页。

项目地址:Direct5dom/ESP32CaptivePortal: 可以用在ESP32上的强制门户。 (github.com)