使用 ESP8266 连接到强制门户 wifi
Connect to captive portal wifi using ESP8266
我想在受强制门户保护的 wifi 网络上连接基于 ESP8266 的传感器(我别无选择,也不能要求减损)。
我有一个 login/password 可以连接。
在一台普通计算机上,当我连接到网络并发出 Internet 请求时(例如,我在 google 上搜索 "bl"),我得到如下页面: https://url:1003/fgtauth?12291a0aff04200a
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
...
</style>
<body>
<div class="oc">
<div class="ic">
<form action="/" method="post">
<input type="hidden" name="4Tredir" value= "https://www.google.com/search?q=test&ie=utf-8&oe=utf-8">
<input type="hidden" name="magic" value="12291a0aff04200a">
<input type="hidden" name="answer" value="0">
<h1 class="logo">
GENERAL CONDITIONS
</h1>
<p>
I. OBJET <br /> <br />
Some blabla..
</p>
<h2>
Do you agree to the above terms?
</h2>
<div class="fec">
<input type="submit" value= "Yes, I agree" onclick="sb('1')">
<input type="submit" value= "No, I decline" onclick="sb('0')">
</div>
</form>
</div>
</div>
<script>
function sb(val) {
document.forms[0].answer.value = val;
document.forms[0].submit();
}
</script>
</body>
</html>
因此,我们在此页面中看到我们得到一个 "magic value",它实际上是会话的 ID。当我点击同意按钮时,我得到这个页面 https://url:1003/ :
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
...
</style>
<title>
Firewall Authentication
</title>
</head>
<body>
<div class="oc">
<div class="ic">
<form action="/" method="post">
<input type="hidden" name="4Tredir" value= "https://www.google.com/search?q=bl&ie=utf-8&oe=utf-8">
<input type="hidden" name="magic" value="122713150676bec1">
<h1 class="logo">
Authentication Required
</h1>
<h2>
Please enter your username and password to continue.
</h2>
<div class="fer">
<label for="ft_un">
Username:
</label>
<input name="username" id="ft_un" style="width:245px">
<br>
</div>
<div class="fer">
<label for="ft_pd">
Password:
</label>
<input name="password" id="ft_pd" type="password" style="width:245px">
</div>
<div class="fer">
<input type="submit" value= "Continue">
</div>
</form>
</div>
</div>
</body>
</html>
在这里,我填写用户名和密码,它会将它们发送到服务器,returns 一个空白页面,OK。
所以,我想从 ESP8266 执行此步骤。我分两步看到:
- 请求页面
- 得到结果并存储魔法
- 伪造一个 "agree" 请求页面
- 伪造 "user/id/magic" 请求页面
ESP8266 的请求页面示例可以在这里找到:
https://github.com/iobridge/ThingSpeak-Arduino-Examples/blob/master/Ethernet/Arduino_to_ThingSpeak.ino
我们在这里看到,我们可以将 POST 请求发送为:
client.print("POST /update HTTP/1.1\n");
这里有一个解析页面的好例子:http://blog.nyl.io/esp8266-led-arduino/
所以,我可能会使用它和 post 答案,但首先我需要一些关于如何创建上述 "fake" 请求的线索。
有什么想法吗?
ESP8266 不仅仅能够使用 HTTPS,事实上,最新的 ESP8226 Arduino 代码库包括一个用于连接到 HTTPS 服务器的 WiFiClientSecure class。
假设这个页面永远不会改变,并且您使用的是 Arduino 环境,您将需要编写一些基本函数。其中之一是您已经链接的初始 GET
功能,它会检查您是否收到了您想要的页面,或者您是否被定向到门户。如果您被定向到门户,则需要编写等效的 POST
函数来发送 "I Agree" 响应。
现在,此 POST
函数将要求您向包含 "Answer" 值的服务器发送一个 HTTP 表单编码有效负载 - 您可以在此处 http://www.w3.org/TR/html401/interact/forms.html#h-17.13 阅读相关内容。由于您(可能)不希望页面发生变化,您可以将其硬编码为如下内容:
client.println("POST / HTTP/1.1");
// $PORTAL_HOST should be the host of the captive portal, e.g. 10.1.1.1
client.println("Host: $PORTAL_HOST");
client.println("Content-Type: application/x-www-form-urlencoded");
client.println("Content-Length: 8");
client.print("\n");
client.print("Answer=1");
发送该负载后,您应该会收到辅助 user/password 页面。从那里通过 indexOf
/ substring
或类似的东西提取 magic/session 是一件简单的事情,然后用你现在提取的数据重复上面的代码(如果需要的话)。
如果您需要更好地了解要发送的内容,我建议您打开浏览器上的 debug/networking 选项卡,然后查看浏览器发送的确切数据这个门户页面。您将希望尽可能地模仿这一点。
我想在受强制门户保护的 wifi 网络上连接基于 ESP8266 的传感器(我别无选择,也不能要求减损)。 我有一个 login/password 可以连接。
在一台普通计算机上,当我连接到网络并发出 Internet 请求时(例如,我在 google 上搜索 "bl"),我得到如下页面: https://url:1003/fgtauth?12291a0aff04200a
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
...
</style>
<body>
<div class="oc">
<div class="ic">
<form action="/" method="post">
<input type="hidden" name="4Tredir" value= "https://www.google.com/search?q=test&ie=utf-8&oe=utf-8">
<input type="hidden" name="magic" value="12291a0aff04200a">
<input type="hidden" name="answer" value="0">
<h1 class="logo">
GENERAL CONDITIONS
</h1>
<p>
I. OBJET <br /> <br />
Some blabla..
</p>
<h2>
Do you agree to the above terms?
</h2>
<div class="fec">
<input type="submit" value= "Yes, I agree" onclick="sb('1')">
<input type="submit" value= "No, I decline" onclick="sb('0')">
</div>
</form>
</div>
</div>
<script>
function sb(val) {
document.forms[0].answer.value = val;
document.forms[0].submit();
}
</script>
</body>
</html>
因此,我们在此页面中看到我们得到一个 "magic value",它实际上是会话的 ID。当我点击同意按钮时,我得到这个页面 https://url:1003/ :
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
...
</style>
<title>
Firewall Authentication
</title>
</head>
<body>
<div class="oc">
<div class="ic">
<form action="/" method="post">
<input type="hidden" name="4Tredir" value= "https://www.google.com/search?q=bl&ie=utf-8&oe=utf-8">
<input type="hidden" name="magic" value="122713150676bec1">
<h1 class="logo">
Authentication Required
</h1>
<h2>
Please enter your username and password to continue.
</h2>
<div class="fer">
<label for="ft_un">
Username:
</label>
<input name="username" id="ft_un" style="width:245px">
<br>
</div>
<div class="fer">
<label for="ft_pd">
Password:
</label>
<input name="password" id="ft_pd" type="password" style="width:245px">
</div>
<div class="fer">
<input type="submit" value= "Continue">
</div>
</form>
</div>
</div>
</body>
</html>
在这里,我填写用户名和密码,它会将它们发送到服务器,returns 一个空白页面,OK。
所以,我想从 ESP8266 执行此步骤。我分两步看到:
- 请求页面
- 得到结果并存储魔法
- 伪造一个 "agree" 请求页面
- 伪造 "user/id/magic" 请求页面
ESP8266 的请求页面示例可以在这里找到: https://github.com/iobridge/ThingSpeak-Arduino-Examples/blob/master/Ethernet/Arduino_to_ThingSpeak.ino 我们在这里看到,我们可以将 POST 请求发送为:
client.print("POST /update HTTP/1.1\n");
这里有一个解析页面的好例子:http://blog.nyl.io/esp8266-led-arduino/
所以,我可能会使用它和 post 答案,但首先我需要一些关于如何创建上述 "fake" 请求的线索。
有什么想法吗?
ESP8266 不仅仅能够使用 HTTPS,事实上,最新的 ESP8226 Arduino 代码库包括一个用于连接到 HTTPS 服务器的 WiFiClientSecure class。
假设这个页面永远不会改变,并且您使用的是 Arduino 环境,您将需要编写一些基本函数。其中之一是您已经链接的初始 GET
功能,它会检查您是否收到了您想要的页面,或者您是否被定向到门户。如果您被定向到门户,则需要编写等效的 POST
函数来发送 "I Agree" 响应。
现在,此 POST
函数将要求您向包含 "Answer" 值的服务器发送一个 HTTP 表单编码有效负载 - 您可以在此处 http://www.w3.org/TR/html401/interact/forms.html#h-17.13 阅读相关内容。由于您(可能)不希望页面发生变化,您可以将其硬编码为如下内容:
client.println("POST / HTTP/1.1");
// $PORTAL_HOST should be the host of the captive portal, e.g. 10.1.1.1
client.println("Host: $PORTAL_HOST");
client.println("Content-Type: application/x-www-form-urlencoded");
client.println("Content-Length: 8");
client.print("\n");
client.print("Answer=1");
发送该负载后,您应该会收到辅助 user/password 页面。从那里通过 indexOf
/ substring
或类似的东西提取 magic/session 是一件简单的事情,然后用你现在提取的数据重复上面的代码(如果需要的话)。
如果您需要更好地了解要发送的内容,我建议您打开浏览器上的 debug/networking 选项卡,然后查看浏览器发送的确切数据这个门户页面。您将希望尽可能地模仿这一点。