Giter Site home page Giter Site logo

Comments (87)

Marfjeh avatar Marfjeh commented on August 17, 2024 2

made the pull request. #30

from mobile-rr.

ratmandu avatar ratmandu commented on August 17, 2024

Just tested with Android 6.0.1 on a Nexus 5X, and a Nexus 6. Connecting to the hotspot brings up a "Sign in to wifi network" notification and toast. Clicking the notification loads the captive portal.

What version of android are you running?

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

I'm using a Galaxy S5 with Android 6.0.1. I'm not sure why my phone doesn't work the same. I'd like for it to open a browser page like it does on iOS. It does pop open a browser when I connect to some captive portals at restaurants and parks with free wifi though. I'd like for mobile-rr to work the same as those captive portals. I just need to do some packet sniffing to find out what the difference is.

from mobile-rr.

Starbix avatar Starbix commented on August 17, 2024

The captive portal also doesn't work for me although I'm on iOS. Is it possible that it's broken on iOS 10?
Edit: It seems to work with dev beta 7 / public beta 6

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

I don't have an iOS 10 device but will see what I can come up with to test with.

from mobile-rr.

Starbix avatar Starbix commented on August 17, 2024

It just worked once for iOS 10, while it works again if I renew my release in iOS 9

from mobile-rr.

Noki avatar Noki commented on August 17, 2024

Please check if my pull request fixes it: #10

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

Hmmm... still the same for me on my Android device but if it fixed it for you I'll merge it.
Thanks.

from mobile-rr.

Starbix avatar Starbix commented on August 17, 2024

This doesn't fix it for iOS 10

from mobile-rr.

Noki avatar Noki commented on August 17, 2024

Hmm. Stopped working for me as well. Strange thing is that it works sometimes. It might be a caching issue. Probalby it is a good idea to send nocaching headers for the redirects and the captive portal index and set the TTL of DNS answers to 0 seconds.

The DNS setting can be set using:

dnsd.setTTL(0);

And the caching directives could be set using something like this:

AsyncWebServerResponse *response = request->beginResponse(302);
response->addHeader("Cache-Control","no-cache");
response->addHeader("Pragma","no-cache");
response->addHeader ("Location", "http://10.10.10.1/" );
request->send(response);

However that also was not enough. But maybe because of the fact that things are still cached and I don't know how to reset the DNS cache and other caches on my phone.

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

Thanks for the suggestions. I'm adding them now. I still have to do some WiFi sniffing to try and determine the difference between this captive portal and others.

Is there a way to set DHCP option 160. I'm curious if that is what the difference is.

from mobile-rr.

Starbix avatar Starbix commented on August 17, 2024

It looks like it works on iOS 10 (dev beta 8/ public beta 7) now.

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

Oh great! Thanks for the feedback.

from mobile-rr.

tpmodding avatar tpmodding commented on August 17, 2024

on my ios 10.0.1 iphone 6 doestn work anymore...i use a nodemcu and had to change the platformio.ini to this:

[env:nodemcuv2]
platform = espressif8266
board = nodemcuv2
framework = arduino
build_flags = -ULWIP_OPEN_SRC -Wl,-Tesp8266.flash.4m.ld

than compiling and uploading is no problem anymore...but as said the portal doesnt open...can only go to console if i type the url :/

from mobile-rr.

treii28 avatar treii28 commented on August 17, 2024

Not working for me either, but I can't imagine it being a device dns-cache issue because places like McDonald's still cause a pop-up on my phone. Has anyone tried sniffing the wifi when connecting to a mcdoogles hotspot? Tell me a good program to grab wifi frames on connection and I'll try it myself.

By the way, you can see what android does by looking at the source code. Among other things, I see a reference to not follow redirects when pulling the 204. (google CaptivePortalTracker.java for whatever version of android you are curious about)

e.g.
/ core / java / android / net / CaptivePortalTracker.java

from mobile-rr.

treii28 avatar treii28 commented on August 17, 2024

Further testing on my part with your dns server library, and I can see the dns requests are being answered, but I never see the requests combing back to the web server. My guess appears to be dns caching or otherwise not-trusting the response of the local-net address on the part of the mobile device. I'm wondering if there is any way to get the web server code to answer the /generate_204 and other urls regardless of the address they are being sent to. Something similar to IPTables redirects in linux or something.
I see they have an lwip implementation in the esp8266 code and some of the libraries (including ESPAsyncTCP) use it for some of their protocol handling. Maybe there's some way in there (it's a tad beyond my skill level at the moment, but I'm trying to find resources to learn as much as I can about it) that could help?

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

I added a callback to be able to override the IP of a DNS query to point the DNS to an IP that is inactive on the local network and that did not solve the issue either.

This post suggested that method.
https://socifi-doc.atlassian.net/wiki/spaces/SC/pages/94371841/DNS+Workaround+to+keep+Android+Splash+Page+and+the+Captive+Portal+Notification+active

I'm just now getting back to this to see if I can come up with a solution. My phone pops up the CP Helper every time at a McDonalds or Taco Bell and other CPs at restaurants but not from this little device. I will do some sniffing again soon to see if I can find any differences.

Any feedback is greatly appreciated. I'd love to solve this issue.

from mobile-rr.

drzony avatar drzony commented on August 17, 2024

I'm working on a bit different project which uses Captive Portal. I have rewritten DNS code from scratch using AsyncUDP, extended it to handle most of DNS requests and it still did not help (manual browser navigation redirects correctly).
The problem seems to be limited to Samsung devices. I have S7 edge and have no luck with pop-up (only "Internet may not be available" shows). On my Tab Pro with Cyanogen installed it works as intended.
It seems that my phone does not request /generate204 from web server (nor does it make any other requests). I've looked into AOSP code and it should visit those URLs, so it seems that Samsung has changed the way that CP detection works.
Still I was not able to determine what triggers the pop-up on my phone. Maybe there is some IP whitelist and/or some special DNS answer required.

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

Did you try to implement DNS Option 160 in your custom DNS code? I'm curious if that would activate the CP Helper.

from mobile-rr.

drzony avatar drzony commented on August 17, 2024

There is no such thing as DNS option 160, it's DHCP option 160 and it's implemented in DHCP server on ESP (I have verified that), if it was not implemented then the device would not receive address of DNS server (and it would not receive any DNS query packets). From inspection of packets coming to my DNS server I can see that the phone asks for the IPs for google servers and my ESP sends responses (I've verified that those responses are valid). But there are no HTTP requests made to web server, which is weird. If I open Chrome manually then if I type http://github.com then I'm properly redirected to my captive portal (which means that both DNS and web server are working), but there is no "Sign in to WiFi network" popup. As I've written in my post before on my Tab Pro with Cyanogen everything works as expected.

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

Ooops sorry... Yes it is for DHCP but it is not for sending the DNS server address. It is for sending the url for a captive portal within the DHCP configuration. How would you set it in the ESP if it is already implemented?

This article explains it's use a bit better.

http://community.arubanetworks.com/t5/Technology-Blog/RFC-7710-Captive-Portal-Identification-Using-DHCP-or-Router/ba-p/255737

from mobile-rr.

drzony avatar drzony commented on August 17, 2024

Unfortunately this would require change in ESP SDK, you can see DHCP options here https://github.com/esp8266/Arduino/blob/f9ac524b13348e18a1ceb00261d947d6c1e0f9b5/tools/sdk/lwip/src/app/dhcpserver.c#L134
Captive portal is only a small part of my project, so checking this out will take some time (and I wonder if it's worth the effort)

from mobile-rr.

ChrisSteinbach avatar ChrisSteinbach commented on August 17, 2024

I just tried with a change to lwip, adding DHCP option 160 to the offer. Unfortunately this didn't help for a Samsung S8; there was no automatic opening of the captive portal browser. I double checked the option looked correct using wireshark on a Linux machine (no captive portal browser opened there either).

I guess option 160 is a dead-end, at least for now.

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

Oh shoot... ok. Thanks for trying it out and letting us know.
This bugs me every time I think about it. It has been a while.
Getting this working consistently across all devices would be the icing on the cake for the project.

from mobile-rr.

vidharv avatar vidharv commented on August 17, 2024

Did you guys manage to get it working!??

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

I have not looked at it again in a long time. Still an open issue until we find a solution.

from mobile-rr.

Marfjeh avatar Marfjeh commented on August 17, 2024

I got it working!

there are some commeted out lines on mobile-rr.ino line 576 ish..

remove the comments and adding

                if ( strstr(domain, "connectivitycheck.gstatic.com") )
                    dnsd.overrideIP =  IPAddress(74, 125, 21, 113);
                // connectivitycheck.android.com -> 74.125.21.113
                if ( strstr(domain, "connectivitycheck.android.com") )
                    dnsd.overrideIP =  IPAddress(74, 125, 21, 113);

                // dns.msftncsi.com -> 131.107.255.255
                if ( strstr(domain, "msftncsi.com") )
                    dnsd.overrideIP =  IPAddress(131, 107, 255, 255);

It works! it seems my phone (s7 edge) was sending the request to connectivitycheck.gstatic.com not to connectivitycheck.android.com

I also enabled dnsd.setTTL(0);

from mobile-rr.

Noki avatar Noki commented on August 17, 2024

@Marfjeh Good job! Do you send in a pull request for all the lazy people? ;-)

from mobile-rr.

Marfjeh avatar Marfjeh commented on August 17, 2024

Sure. i'll fork the project

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

Awesome! I will check this out as soon as a get a moment.

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

I was looking at my code that I hadn't committed and at some point I did try "connectivity.gstatic.com" but it didn't seem to work on my Galaxy S5. This is what I had to cover all of the android check domains.

// connectivitycheck.android.com -> 74.125.21.113
if ( strstr( "clients1.google.com|clients2.google.com|clients3.google.com|clients4.google.com|connectivitycheck.android.com|connectivitycheck.gstatic.com", domain ) )
    dnsd.overrideIP =  IPAddress(74, 125, 21, 113);

Going to test this again shortly with on my S5.

Looks like a few of the comment lines in your pull request were uncommented.

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

It's good to hear it is working on the S7 but unfortunately I still get the same results on my S5.

from mobile-rr.

Marfjeh avatar Marfjeh commented on August 17, 2024

Wierd, which android version are you using?

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

It's Android 6.0.1. The latest update from Verizon.

If I go to a place with free wifi and connect I get the popup so I know it is capable. I just don't know what is different about how I'm handling it in this code versus what is going on with the captive portal at restaurants and other places where it works.

I had tried the code that you uncommented at one point but it didn't make a difference and that is why I commented it out. If that did the trick for you though then it needs to stay in. :)

from mobile-rr.

Marfjeh avatar Marfjeh commented on August 17, 2024

hmm. i wonder what packets it sends... maybe we capture it with Wireshark?

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

Yeah... I did some captures to try and compare at one point but didn't find any clues. I have been meaning to get back to it at some point. It would be nice to solve this mystery.

from mobile-rr.

Noki avatar Noki commented on August 17, 2024

according to some pages I found it's "connectivitycheck.gstatic.com" for Android 6:

https://enterprisenetworkingatlarge.wordpress.com/2018/04/21/captive-portal-detection-on-android-and-others-client-vendors-vs-ap-vendors/

from mobile-rr.

drzony avatar drzony commented on August 17, 2024

According to my research Samsungs with Android 6 and 7 do something differently. When checking the logs from ESP DNS I have noticed that they ask for much more pages that connectivitycheck. I think they may be related to some "social services" login like Facebook or something like that. I have updated my S7 to Android 8.0, but haven't had the time to verify if it changed anything. The easiest way to verify what DNS requests are made is to add some logging on ESP. However I have tried to redirect all of them to captive portal using DNS and then combinations of HTTP redirects and it failed. Samsung has made some additional "checks" that are required to show "sign in" popup.

from mobile-rr.

Noki avatar Noki commented on August 17, 2024

ok, so maybe we have to add a form to the html and hide it with CSS ;-)

from mobile-rr.

drzony avatar drzony commented on August 17, 2024

Does not help, I have a captive portal with a proper form on my project and it still does not work. Maybe Samsung added some MAC filter for Access Points or some weird "smart" checks. As I wrote in a post before, going manually to some page in Chrome works like a charm.

from mobile-rr.

Marfjeh avatar Marfjeh commented on August 17, 2024

then they need to add MAC addresses on the whole world, thats not going to work. but i can agree samsung maybe expects something

from mobile-rr.

Noki avatar Noki commented on August 17, 2024

There is an RFC for Captive-Portal Identification Using DHCP or Router Advertisements: https://tools.ietf.org/html/rfc7710

I think this would be the correct approach. However it works totally different than the method currently implemented.

from mobile-rr.

Marfjeh avatar Marfjeh commented on August 17, 2024

Hmm intresting!

from mobile-rr.

drzony avatar drzony commented on August 17, 2024

RFC7710 details DHCP option 160 which was tested above in #2 (comment)

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

Yep... I was hoping DHCP option 160 would be the solution. I will have more time next week to go do some captures to analyze. If anyone else has time and would like to help that would be awesome. I know it's probably something simple.

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

I was able to find the source code for the firmware on my phone here.

http://opensource.samsung.com/reception/receptionSub.do?method=sub&sub=F&searchValue=G900V

Maybe there will be a clue in there. I'll take a look and see what I can find.

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

No luck with that code. :(

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

Found this post with others having this same issue. Their solution describes what we were just doing.

https://unix.stackexchange.com/questions/432190/why-isnt-androids-captive-portal-detection-triggering-a-browser-window

https://unix.stackexchange.com/questions/212871/captive-portal-detection-popup-implementation/303807#303807

I need someone else with a Galaxy S5 or other device that is having this same issue to confirm and compare. A device test chart might be useful for figuring this out.

I was just wondering if changing the device default IP to 192.168.1.1 would make a difference. The current setup is a Class A private subnet but I also have it using a Class C subnet mask. That should be corrected. Going to test that next.

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

It looks like we are missing a port forward in LwIP to localhost for any IP request to port 80.
I think the following project may be able to be used to get that done via it's NAPT implementation.

https://github.com/martin-ger/esp-open-lwip

I'm looking into it now but not sure how it would be easily implemented in this project.
Any ideas or help are greatly appreciated.

from mobile-rr.

drzony avatar drzony commented on August 17, 2024

I finally managed to make it work, it turns out that DNS redirects for:

  • clients3.google.com
  • clients.l.google.com
  • connectivitycheck.android.com
  • connectivitycheck.gstatic.com
  • play.googleapis.com

need to be answered with invalid address e.g. 192.168.4.11 (if softAPIP is 192.168.4.1)
I've just verified that this works, but it needs custom DNS server, because the one that is included in ESP Arduino lib always answers with single IP.

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

I put in a callback so you can override the IP address being returned from DNS. But from what I was finding it has to be a non-local IP address and you also have to override all connections to port 80 on any IP and direct them to the softAPIP to get it to work correctly.

I will try this though and see if it works for me too. :) Thanks for the feedback.
This one has been bugging me for a long time.

from mobile-rr.

drzony avatar drzony commented on August 17, 2024

You do not need IP redirection. Here is my exact setup that works:

  1. DNS server answering with:
IPAddress dest_address = WiFi.softAPIP();

if (strcmp(label, "clients3.google.com") == 0 || strcmp(label, "clients.l.google.com") == 0 ||
    strcmp(label, "connectivitycheck.android.com") == 0 ||
    strcmp(label, "connectivitycheck.gstatic.com") == 0 ||
    strcmp(label, "play.googleapis.com") == 0) {
    dest_address[3] += 10;
}
  1. HTTP server redirecting "notFound" and everything that is not meant for "myhost.manager.net" to "http://myhost.manager.net", with the following redirect:
if (request->host() != "myhost.manager.net" && request->host() != WiFi.softAPIP().toString()) {
    AsyncWebServerResponse *response = request->beginResponse(307);
    response->addHeader("X-Frame-Options", "deny");
    response->addHeader("Cache-Control", "no-cache");
    response->addHeader("Pragma", "no-cache");
    response->addHeader("Location", "http://myhost.manager.net");
    request->send(response);
}

And that's all that is needed.

from mobile-rr.

treii28 avatar treii28 commented on August 17, 2024

Let me know as soon as there is something final to try out. I would love to get that project down off the 'waiting for resolution' shelf.
In the meantime I'll play with the recent suggestions. Maybe I'll get lucky.

from mobile-rr.

treii28 avatar treii28 commented on August 17, 2024

@drzony is your dnsserver code posted anywhere?

from mobile-rr.

drzony avatar drzony commented on August 17, 2024

Not yet, it's part of a bigger project and it will take a while to release, you can modify included DNSServer in line

( _domainName == "*" || getDomainName() == _domainName )

Just add comparisons with addresses from my comment and then add replyWithFakeIp()

from mobile-rr.

treii28 avatar treii28 commented on August 17, 2024

but isn't _domainName in that instance the one specified when the server instance is created? It appears to me the UDP _buffer is what is going to contain the incoming request but it's going to be in the raw UDP packet format (with the domain name started at I believe position 13 -- thus the +12 offset in the code)

Edit: OH wait, duh - ok, your custom dns server isn't removing the prefix. Gotcha - ok, thanks. I'll take a look at that later. I had the regular one open in another window which was why I was confused.

from mobile-rr.

treii28 avatar treii28 commented on August 17, 2024

btw, if you control your own code and always plan to use low 4th digit ips, you should be fine, but I'd probably do something like this:

if(dest_address[3] < 244)
dest_address[3] += 10;
else
dest_address[3] -= 10;

(255 is broadcast so you want to fall on 254 or below)

from mobile-rr.

drzony avatar drzony commented on August 17, 2024

@treii28 concerning dest_address[3] += 10, it does not matter since it's uint8_t, so it will overflow to zero automatically. In terms of address clashes it should also work as the address I'm returning needs to be fake, any connection to broadcast will fail, so it should trigger the sign-in popup.
As for you code, if you are using DNSServer from this repo you can provide callback to onOverride and change the address there (sorry for the confusion, I did not notice earlier that the callback option was already added)

from mobile-rr.

treii28 avatar treii28 commented on August 17, 2024

ok, wasn't sure on the type - but overflow to zero could also equal zero for 246. And zero is a network address. Again, not good.

from mobile-rr.

treii28 avatar treii28 commented on August 17, 2024

And I'm not understanding how your step 2) is working if you are responding with a different dns address for the urls. The ESP won't try to answer it if the incoming request isn't sent to it's AP address.

from mobile-rr.

treii28 avatar treii28 commented on August 17, 2024

nope - no helper pop-up when returning a different address for the googles. Same ole 'Internet may not be available' with no redirect to a landing page. I inserted my offset in the wrong spot, but added debug stuffs to make sure it was detecting the google addresses and returning the non-ap address. No change in android behavior. (I also tried it with the sketch's override ip method)

Or are you actually answering those with a second AP assigned to the address?

from mobile-rr.

drzony avatar drzony commented on August 17, 2024

Here is a diff that should work, I have not tested it:

index 5acb53f..379ff13 100644
--- a/src/mobile-rr.ino
+++ b/src/mobile-rr.ino
@@ -573,13 +573,10 @@ void setupDNSServer()
         dbg_printf ( "DNS Query [%d]: %s -> %s", remoteIP[3], domain, ipToString ( resolvedIP ).c_str() );
 
         // connectivitycheck.android.com -> 74.125.21.113
-        if ( strstr( "clients1.google.com|clients2.google.com|clients3.google.com|clients4.google.com|connectivitycheck.android.com|connectivitycheck.gstatic.com", domain ) )
-            dnsd.overrideIP =  IPAddress(74, 125, 21, 113);
-
-        // dns.msftncsi.com -> 131.107.255.255
-        if ( strstr(domain, "msftncsi.com") )
-            dnsd.overrideIP =  IPAddress(131, 107, 255, 255);
-
+        if ( strstr( "msftncsi.com|clients1.google.com|clients2.google.com|clients3.google.com|clients4.google.com|connectivitycheck.android.com|connectivitycheck.gstatic.com", domain ) ) {
+            dnsd.overrideIP =  WiFi.softAPIP();
+            dnsd.overrideIP[3] += 10;
+        }
     } );
     dnsd.onOverride ( [] ( const IPAddress & remoteIP, const char *domain, const IPAddress & overrideIP )
     {
@@ -596,7 +593,7 @@ void setupHTTPServer()
     dbg_printf ( "Starting HTTP Captive Portal" );
 
     // Handle requests
-    httpd.on ( "/generate_204", onRequest );  //Android captive portal. Maybe not needed. Might be handled by notFound handler.
+    //httpd.on ( "/generate_204", onRequest );  //Android captive portal. Maybe not needed. Might be handled by notFound handler.
     httpd.on ( "/fwlink", onRequest );  //Microsoft captive portal. Maybe not needed. Might be handled by notFound handler.
     httpd.onNotFound ( onRequest );
 
@@ -1099,6 +1096,18 @@ void wifi_handle_event_cb ( System_Event_t *evt )
     }
 }
 
+void redirectRequest(AsyncWebServerRequest *request)
+{
+    String redirect_address = "http://wifi.manager.net";
+
+    AsyncWebServerResponse *response = request->beginResponse(307);
+    response->addHeader("X-Frame-Options", "deny");
+    response->addHeader("Cache-Control", "no-cache");
+    response->addHeader("Pragma", "no-cache");
+    response->addHeader("Location", redirect_address);
+    request->send(response);
+}
+
 //***************************************************************************
 // HTTPD onRequest                                                          *
 //***************************************************************************
@@ -1116,26 +1125,9 @@ void onRequest ( AsyncWebServerRequest *request )
 
     String path = request->url();
 
-    if ( ( !SPIFFS.exists ( path ) && !SPIFFS.exists ( path + ".gz" ) ) ||  ( request->host() != "10.10.10.1" ) )
+    if ( ( !SPIFFS.exists ( path ) && !SPIFFS.exists ( path + ".gz" ) ) || ( request->host() != "10.10.10.1" && request->host() != "wifi.manager.net") )
     {
-        AsyncWebServerResponse *response = request->beginResponse ( 302, "text/plain", "" );
-//        response->addHeader ( "Cache-Control", "no-cache, no-store, must-revalidate" );
-//        response->addHeader ( "Pragma", "no-cache" );
-//        response->addHeader ("Expires", "-1");
-//        response->setContentLength (CONTENT_LENGTH_UNKNOWN);
-        response->addHeader ( "Location", "http://10.10.10.1/index.htm" );
-        request->send ( response );
-
-        /*        AsyncWebServerResponse *response = request->beginResponse(
-                    511,
-                    "text/html",
-                    "<html><head><meta http-equiv='refresh' content='0; url=http://10.10.10.1/index.htm'></head></html>"
-                );
-                //response->addHeader("Cache-Control","no-cache");
-                //response->addHeader("Pragma","no-cache");
-                //response->addHeader ("Location", "http://10.10.10.1/index.htm" );
-                request->send(response);
-         */
+        redirectRequest(request);
     }
     else
     {

from mobile-rr.

drzony avatar drzony commented on August 17, 2024

@treii28 Here is how it works:

  1. DNS responds with invalid IP for "check" hosts
  2. The phone tries to connect and when it fails it looks for sign-in page via HTTP
  3. DNS redirects all other addresses to APIP
  4. If the request is for 10.10.10.1 or wifi.manager.net - WebServer serves RR
  5. All other HTTP requests are redirected to wifi.manager.net

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

What devices are you testing on? It still doesn't work properly on my Samsung Galaxy S5.
A lot of devices work with just responding to all DNS requests with the AP IP Address.

From my digging a modified lwip with port redirection is what is going to solve this issue for these older devices.
I just haven't figured out how to use a different lwip with the napt feature in this project yet.

from mobile-rr.

treii28 avatar treii28 commented on August 17, 2024

I have a galaxy note 4. And I get what your code is trying to do. But if you are providing DNS responses for the generate_204 and other connect-check urls to ip addresses that your wifi isn't configured to answer, you can put as many redirect or other 'handle' methods in your webserver that you like. It's never going to receive the generate_204 request because the wifi isn't answering the requests for 74.125.21.13 or 131.107.255.255

from mobile-rr.

treii28 avatar treii28 commented on August 17, 2024

As far as the code snippet above, it's doing little more than the original DNSServer was doing but adding extra conditionals that aren't really doing anything. (it's sending the softAP ip address whenever the generate_204 and other host urls are called which is what the original DNSServer code essentially did for 'everything')

from mobile-rr.

drzony avatar drzony commented on August 17, 2024

@treii28
I'm using Note 9 and only after changing the responses it started to work (it's on my own code, so I'm not sure that my patch above is enough, my DNS server sticks to spec better). I'll have esp8266 setup on the weekend, so maybe I'll have time to make a PoC on it and send you some example for testing. The whole idea here is that on pure Android it's enough to return 404 on generate_204 (I have verified this on my tablet) on Samsung phones the connectivity addresses have to be unreachable, that is what my patch does on DNS. The other part is HTTP redirection, which allows the sign-in page to work.

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

From what I understand, those specific domains need to resolve via DNS to an IP address that is not on the local network and be unreachable. Then when the device tries to connect to that IP via port 80 or 443 the ESP8266 AP has to detect and redirect at that point to the localhost.

If you look at the first answer on this post it describes what they did on a rPI to get it work correctly and consistently across a lot of different devices.

https://unix.stackexchange.com/questions/432190/why-isnt-androids-captive-portal-detection-triggering-a-browser-window

I'm just trying to find a way to do the same. I think a modified lwip will give us the ability to do this kind of redirect.

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

Just updated with some minor changes so it builds on the latest platform update and some tweaks.

from mobile-rr.

drzony avatar drzony commented on August 17, 2024

@idolpx
I don't think port redirection is required. I'll make a separate "Hello world" project on the weekend, since your code has a lot of other functionality that may interfere. I think I'll be able to do this on original DNS server code with only slight modifications

from mobile-rr.

treii28 avatar treii28 commented on August 17, 2024

Maybe I am not understanding the esp code then. Is it answering port 80 regardless of the target? I thought the AP configuration only grabbed traffic designated for it's configured IP so the webserver wouldn't ever even see the requests.

EDIT: Lulz, i was going to post the link you had just posted above. I had it open in my browser yesterday before you posted it.

from mobile-rr.

treii28 avatar treii28 commented on August 17, 2024

BTW, if anyone can find any good resources on learning LWIP, I tried looking all over to get any kind of good doc on that library a few months back and couldn't find much. I struggle enough with C/C++. Trying to translate my limited knowledge of the TCP/IP stack into an undocumented library is probably beyond my skill/knowledge. But if I could find something that broke down the functionality, I might be able to duct tape something together.

from mobile-rr.

drzony avatar drzony commented on August 17, 2024

Ok, I found the issue with my previous patch, strstr was too greedy, it also returned fake for google.com, here is the new patch:

diff --git a/src/mobile-rr.ino b/src/mobile-rr.ino
index 1fb4e70..127e603 100644
--- a/src/mobile-rr.ino
+++ b/src/mobile-rr.ino
@@ -573,17 +573,26 @@ void setupDNSServer()
     {
         dbg_printf ( "DNS Query [%d]: %s -> %s", remoteIP[3], domain, ipToString ( resolvedIP ).c_str() );
 
-        // connectivitycheck.android.com -> 74.125.21.113, 172.217.21.67
-        //if ( strstr( "clients1.google.com|clients2.google.com|clients3.google.com|clients4.google.com|clients.l.google.com|connectivitycheck.android.com|connectivitycheck.gstatic.com|android.clients.google.com|play.googleapis.com", domain ) )
-        //    dnsd.overrideIP =  IPAddress(172, 217, 21, 67);
-
-        // dns.msftncsi.com -> 131.107.255.255
-        //if ( strstr(domain, "msftncsi.com") )
-        //    dnsd.overrideIP =  IPAddress(131, 107, 255, 255);
-
-        //if ( strstr( "msftncsi.com|clients1.google.com|clients2.google.com|clients3.google.com|clients4.google.com|clients.l.google.com|connectivitycheck.android.com|connectivitycheck.gstatic.com|android.clients.google.com|play.googleapis.com", domain ) )
-        //    dnsd.overrideIP =  IPAddress(ip[0], ip[1], ip[2], ip[3]+10);
-
+        const char *domains[] = {
+            "msftncsi.com",
+            "clients1.google.com",
+            "clients2.google.com",
+            "clients3.google.com",
+            "clients4.google.com",
+            "connectivitycheck.android.com",
+            "connectivitycheck.gstatic.com",
+            "clients.l.google.com",
+            "play.googleapis.com",
+            NULL
+        };
+        size_t i = 0;
+        bool fake = false;
+        while (domains[i]) {
+            if (strcmp(domain, domains[i]) == 0) {
+                dnsd.overrideIP = WiFi.softAPIP();
+                dnsd.overrideIP[3] += 10;
+            }
+        }
     } );
     dnsd.onOverride ( [] ( const IPAddress & remoteIP, const char *domain, const IPAddress & overrideIP )
     {

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

I noticed that too and just did a strcmp to see if the domain was "google.com" before checking for the override domains. It still didn't work on my test device.

I'm working on a modified lwip now but not sure how to replace the one in the platformio framework for building the firmware.

from mobile-rr.

drzony avatar drzony commented on August 17, 2024

I've made a simple example at: https://github.com/drzony/captive_portal
I've tested it on ESP32, but it should work on ESP8266.
@idolpx Could you verify it on your setup?

from mobile-rr.

treii28 avatar treii28 commented on August 17, 2024

IT WORKS!!!

For the first time in two years working on this issue on any android over v4.3 (kitkat) I got the pop-up redirect to finally work. I was asking in a facebook forum about the possibility of somehow configuring the esp8266 to answer additional addresses such as the overrides you are using or perhaps other DNS servers (such as the google default dns servers).
He made a suggestion that is so braindead stupid, I'm kicking myself for not thinking of it myself. It may not work for all applications, but if you do not intend to connect your device to the internet anyway, just set your ap's address to the google primary dns address (8.8.8.8).

Apparently the versions of Android from 4.3 through at least my version (v7) have either a behavior/feature or a bug where they will ask 8.8.8.8 for their generate_204 address by default. So you basically have to answer the DNS request on 8.8.8.8 or you won't be able to override it.

I'll still keep asking around about configuring a second address, but for the time being this solution will work just fine for my geocaches and will probably work just fine for your mobile rick rolls. Configure your AP to use 8.8.8.8 and you'll get the pop-up helper with the redirect again.

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

IT WORKS!!!
.....
Configure your AP to use 8.8.8.8 and you'll get the pop-up helper with the redirect again.

Holy hell... I got the popup when I tried this for the first time too on my Galaxy S5 but it tried to go to https://google.com by default and it doesn't get redirected to the portal page.

@drzony I will try your project a when I get back this evening. Thanks for posting that.

I'm almost done with the modified lwip but I don't know how to replace the one included with the framework in platformio yet. Still working on that.

from mobile-rr.

idolpx avatar idolpx commented on August 17, 2024

@drzony I had a few mins and went ahead and tried your project and I get the same results as mine. No popup helper on connect. But does redirect automatically when I browse manually like mine does.

from mobile-rr.

drzony avatar drzony commented on August 17, 2024

@idolpx I just noticed that you wrote https://google.com that means that it's trying to connect via https which is on port 443 not 80. If it's really SSL, then it will never work, since you won't be able to spoof the domain (you won't be able to get a signed server certificate for google.com, which is checked before redirect). I've seen this problem with several hotspots on older phones and the only thing to be done was manual visit to some http site. Maybe there is some weird way to redirect https to http without certificate, but it seems unlikely.

from mobile-rr.

tripflex avatar tripflex commented on August 17, 2024

This seems to be a major issue on Samsung devices. I wrote a captive portal library for Mongoose OS and have only had issues on Samsung Devices for some reason:
https://github.com/tripflex/captive-portal

Was reading through here hoping i could find some details as to why Samsung versions of android don't work with the standard 302 redirect -- even when I respond to all DNS requests with the AP IP address .. ugh.

https://android.stackexchange.com/questions/213341/samsung-android-source-code-captive-portal-handling

from mobile-rr.

drzony avatar drzony commented on August 17, 2024

@tripflex
I can confirm that my solution from the above works on Oreo Galaxy S7 Edge and Pie Note 9 (Guys above say that it does not work on S5, but I have no way to verify that). It seems that on Samsung phones getting 302 from google servers is not enough, they need to be pointed to an invalid address by DNS.

from mobile-rr.

DE8MSH avatar DE8MSH commented on August 17, 2024

Hey @ALL.

On a Moto G XT1039 with Lineage-OS (14.1.20190207-NIGHTLY-peregrine) it works flawlessly with out modification of the code.

from mobile-rr.

DE8MSH avatar DE8MSH commented on August 17, 2024

[Sorry. Can not edit]
What's not working: Console. All fields are empty.

And what OS doesn't work, too: Galaxy J5 SM-J500FN (Android 6.0.1 MMB29MJ500FNXXS1BQG1).

from mobile-rr.

DE8MSH avatar DE8MSH commented on August 17, 2024

...but: The captive portal advance from DNSServer examples works like a charm on my Galaxy J5 SM-J500FN (Android 6.0.1 MMB29MJ500FNXXS1BQG1). It calls the HTML output right after connecting the ESP8266 ap. 🤔 Is this a clue?

from mobile-rr.

drzony avatar drzony commented on August 17, 2024

@DE8MSH Could you try my example from https://github.com/drzony/captive_portal ?

from mobile-rr.

DE8MSH avatar DE8MSH commented on August 17, 2024

@drzony: Nope. But I don't use this platformio thingy dingy. I use Arduino IDE:

/coding/captive_portal/src/CP/CP.ino: In function 'void setup()':
CP:61: error: 'class ESP8266WiFiClass' has no member named 'softAPsetHostname'
     WiFi.softAPsetHostname(HOSTNAME);
          ^

from mobile-rr.

drzony avatar drzony commented on August 17, 2024

@29g The only difference is AP IP address (172.0.0.1), change 10.10.10.1 to 172.0.0.1 in line 142 and try to test it. I doubt it will work, but maybe something changed in Arduino for ESP.

from mobile-rr.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.