3

Has anyone ever succeeded in getting a captive portal to cause a pop-up for the redirected content to a specific landing page on an Arduino or ESP8266? I've tried everything under the sun and while my android will complain about a non-connected internet and other things, it never actually requests/suggests opening a browser as I've seen done on some open-wifi hotspots with sign-in pages. I'm trying to implement what will actually be a non-internet connected device that users would sign into at a remote location to show they had arrived, kind of like a geocache but using wifi sign in. I did the dnsServer glob (all names to local IP), I've done a number of url redirects. I've tried feeding the specific content (instead of the re-directs) but nothing pops up.

Relevant code:

#include <ESPAsyncWebServer.h>
#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <ESP8266mDNS.h>


IPAddress apIp ( 10, 10, 10, 10 );
AsyncWebServer asyncWebServer(80);
DNSServer dnsServer;
const char* captiveRedirect = "/index.htm";
String apSSID = "GeoCache";

dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
dnsServer.start ( DNS_PORT, "*", apIp );

DBG_OUTPUT_PORT.println("Initializing MDNS for local hostname on AP");
if (MDNS.begin(apHostname)) {
    MDNS.addService("http", "tcp", 80);
    DBG_OUTPUT_PORT.println("MDNS responder started");
    DBG_OUTPUT_PORT.print("You can now connect to http://");
    DBG_OUTPUT_PORT.print(apHostname);
    DBG_OUTPUT_PORT.println(".local");
}

//Android captive portal. Maybe not needed. Might be handled by notFound handler.
asyncWebServer.addRewrite( new AsyncWebRewrite("/generate_204", captiveRedirect));
//asyncWebServer.on ( "/generate_204", returnOK );
//Microsoft captive portal. Maybe not needed. Might be handled by notFound handler.
asyncWebServer.addRewrite( new AsyncWebRewrite("/fwlink", captiveRedirect));
//asyncWebServer.on ( "/fwlink", returnOK );
//Microsoft windows 10
//asyncWebServer.on ( "/connecttest.txt", returnOK );
asyncWebServer.addRewrite( new AsyncWebRewrite("/connecttest.txt", captiveRedirect));
// apple devices
asyncWebServer.addRewrite( new AsyncWebRewrite("/hotspot-detect.html", captiveRedirect));
//asyncWebServer.on ( "/hotspot-detect.html", returnOK );
asyncWebServer.addRewrite( new AsyncWebRewrite("/library/test/success.html", captiveRedirect));
//asyncWebServer.on ( "/library/test/success.html", returnOK );
// kindle
asyncWebServer.addRewrite( new AsyncWebRewrite("/kindle-wifi/wifistub.html", captiveRedirect));
//asyncWebServer.on ( "/kindle-wifi/wifistub.html", returnOK );

asyncWebServer.on("/delete", HTTP_DELETE, handleDelete);
// upload a file to /upload
asyncWebServer.on("/upload", HTTP_POST, returnOK, handleUpload);
// Catch-All Handlers
asyncWebServer.onFileUpload(handleUpload);
//asyncWebServer.onRequestBody(onBody);

asyncWebServer.on("/signin", HTTP_GET, addLog);

asyncWebServer.onNotFound(handleNotFound);

asyncWebServer.begin();

WiFi.mode(WIFI_AP);
WiFi.softAPConfig ( apIp, apIp, IPAddress ( 255, 255, 255, 0 ) );
WiFi.softAP(apSSID);
Scott
  • 7,983
  • 2
  • 26
  • 41
  • I even tried setting a special rule in my handleNotFound that checks the 'request->host() against the local IP and local hostname to do different behaviors. Nothing has worked yet. – Scott Sep 18 '17 at 22:57
  • well, fwiw, i've seen it work on a test sketch for something i can't recall now. i know that's not helpful, other than for encouragement... – dandavis Sep 19 '17 at 20:15
  • how long ago? From what I can make out, the method I'm using now 'used' to work on older android/ios versions and 'may' still work on a hard-reset device (that hasn't had a chance to dns cache yet) – Scott Sep 21 '17 at 15:51
  • i just tried the "captive portal" example on windows and it worked, including opening a tab out of nowhere to a weird url that redirected to the demo text. on android 5.1, the demo text appeared in an embedded browser after clicking the notification. both were decent user experiences... – dandavis Sep 26 '17 at 11:11
  • hmm, I've had no luck at all even in seeing the requests. And the most prominent example I've seen (the mobile rick roll) has an open thread by folks sharing my experience. – Scott Sep 27 '17 at 14:31

1 Answers1

0

In the loop(), you have to include:

dnsServer.processNextRequest();

before

server.handleClient(); //Handling of incoming requests

then, create a notfound router:

server.onNotFound([]() {
    char * msg = "HELLO<br>Default landing page<br>";
    server.send(200, "text/html", msg );
  });
  • The problem is it never receives the request because apparently Android (from version 4.4 till about version 7) asks only google nameservers (e.g. 8.8.8.8) for the address of the google generate_204 host. – Scott May 31 '19 at 21:46
  • My short-term fix is to configure the softAP to 8.8.8.8 as the IP since it's not internet-connected. A better solution would be to spoof 8.8.8.8 addresses with low-level lwIP code. But I haven't coded IP stack in years and even then not in C. – Scott May 31 '19 at 21:51