-
Notifications
You must be signed in to change notification settings - Fork 7.6k
captiveportal example not working on some platforms #1037
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Bug confirmed here on Arduino IDE also |
I see lots of malformed dns packets in wireshark.
wireshark |
|
Looks like dig always fails, since it sends additional rr OPT every time, I noticed OPT and PTRs fail. Ill look into this again tomorrow on new machines and see what I see, might not be related at all. |
Are you using the captiveportal example, it uses that address instead. |
This fixes it, the dns repsones are not including the question along with the answer. DNSServer.cpp diff @@ -135,15 +119,35 @@
if (_buffer == NULL) return;
_dnsHeader->QR = DNS_QR_RESPONSE;
_dnsHeader->ANCount = _dnsHeader->QDCount;
- _dnsHeader->QDCount = 0;
+ _dnsHeader->QDCount = _dnsHeader->QDCount;
+ //_dnsHeader->RA = 1;
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
_udp.write(_buffer, _currentPacketSize);
+
+ _udp.write((uint8_t)192); // answer name is a pointer
+ _udp.write((uint8_t)12); // pointer to offset at 0x00c
+
+ _udp.write((uint8_t)0); // 0x0001 answer is type A query (host address)
+ _udp.write((uint8_t)1);
+
+ _udp.write((uint8_t)0); //0x0001 answer is class IN (internet address)
+ _udp.write((uint8_t)1);
+
_udp.write((unsigned char*)&_ttl, 4); DNSServer.cpp updated void DNSServer::replyWithIP()
{
if (_buffer == NULL) return;
_dnsHeader->QR = DNS_QR_RESPONSE;
_dnsHeader->ANCount = _dnsHeader->QDCount;
_dnsHeader->QDCount = _dnsHeader->QDCount;
// _dnsHeader->QDCount = 0;
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
_udp.write(_buffer, _currentPacketSize);
_udp.write((uint8_t)192); // answer name is a pointer
_udp.write((uint8_t)12); // pointer to offset at 0x00c
_udp.write((uint8_t)0); // 0x0001 answer is type A query (host address)
_udp.write((uint8_t)1);
_udp.write((uint8_t)0); //0x0001 answer is class IN (internet address)
_udp.write((uint8_t)1);
_udp.write((unsigned char*)&_ttl, 4);
_udp.write((uint8_t)0);
_udp.write((uint8_t)4);
_udp.write(_resolvedIP, 4);
_udp.endPacket();
} |
for the original fix, and forum post |
Not sure if this was left out on purpose or not
Have you found a solution for android 7? Still not showing up popup |
I dont have android to test, this issue should be resolved. Do you have the latest commits? Are you using the captive portal example |
It is important understand if the portal do not work or only do not automatically show the connection webpage. After the connetction try to manually open Chrome browser on the phone and write the address www.test.it (It is important that you use an address not https, so google.com is not a good address) |
Yes of course, but that doesn't help with the issue. Here is my PR to add debugging to DNS server define DEBUG_ESP_PORT in your build flags, or un-comment in the file. If you enable both those and still see no logging, then your device is not even requesting a captive portal. In that case, either it disabled somehow, or it does not have satisfactory dns information to request a site. Which could indicate a bug. Can you get a captive portal to work somewhere else? say a store or coffeeshop or something ? |
This seems to be a problem with most modern iphone, android and other devices. None of the code or examples I've seen of handling captive portal from ESP8266 work on anything newer than somewhere about IceCream I believe on the android side. You can see the DNS requests being made, but the phone doesn't appear to trust the responses as it never makes an http or https request to the 'spoofed' ip address. (at least not in my tests) EDIT: OK, reading some of your linked posts. I hadn't sniffed the actual contents of the packets. Is this because it was sending back 0.0.0.0? |
As for my experiences, I have gotten captive portals before on my android phone where the pop-up appears. Both at public places like McDonald's or xFinity wifi as well as at home on an openWRT router. I've been trying to have someone more knowledgeable in C/Arduino/ESP/tcp/ip look into this for well over a year now. I was about to start boning up on lwip myself and hacking apart both the Android OS source code and openWRT source code to try to figure it out myself. |
So are you saying captive portal example works on neither esp32 nor esp8266 for your device/s? |
I have been trying to find a working captive portal for over a year. I even tried sniffing the packets at one point but had only a limited idea what to look for. The best I have ever achieved on an android device (from an ESP based AP) is a pop-up telling me the device is not connected to the internet. (no redirect - redirect does, however, work fine on my home router and public wifi hotspots with sign-in pages on these devices) |
Can you run android on a raspi or virtuabox? |
I have android nougat running on virtualbox , but the mouse barely moves, and I cannot get the wireless bridge mode to work, not sure if this requires an extension pack or is just not possible. I might need a better vm. |
On android only works if you try to open a http page (not https). And is
not automatic as in ios or a pc.
I've been researching about this, and it seems the problem is that android
dont like that captive portal ip is in the same network. i've tested with a
functional captive portal that dns resolves correctly (for android captive
https://www.gstatic.com/generate_204 as an external ip) but it seems there
is some kind of http redirection of the request to the captive portal.
dns service should give an external ip and then do some kind of http
redirection (that i havent been able to do it with esp8266). Do you know if
there is a way of intercepting http packet to an external ip and deliver a
302 redirection to the captive portal?
2018-04-01 19:05 GMT-03:00 Shawn A <notifications@github.com>:
… I have android nougat running on virtualbox , but the mouse barely moves,
and I cannot get the wireless bridge mode to work, not sure if this
requires an extension pack or is just not possible.
I might need a better vm.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1037 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AFbCFxYADeL053AX5VnhPGoiuFU6rwZSks5tkU9HgaJpZM4Rvalh>
.
|
Android can be run on a pi, but I don't see the download on their standard downloads page anymore. Nor do I know how closely it would resemble what goes on in a phone. I may have to try it with my pi zero w (the one with wifi/bluetooth - they cost about $10-15 btw, Adafruit appears to be out-of-stock at the moment but amazon prime has an 'essentials' kit for $24. piMoroni, piHut and CanaKit don't appear to show them out of stock) But again, if there's anything you need tested, let me know. As mentioned, I could even set up an account on the pi-zero-w or the pi-3. (both have built in wifi. They aren't the most robust platforms for atmel/esp development, but I've done it on them. I generally use platformio when on the pis) |
Also on Android there is an automatic connection to the captive portal, but it depends on the Android version. On an LG G5 with Android 7, it work correctly. On my second phone, Android 4.4 Samsung, i need to manually go to an http address |
Yeah I read that there are some bugs or changes in behavior after a certain android version, I also read about 204 expected url, and redirects expecting 307 temporary redirects, we send location header and a 302 redirect. I also read about, captive portals failing if you leave cellular on, since it can still get out, and some notes about walled garden exceptions for google. .. no idea what that means. Oh and one more note about people using google dns 8.8.8.8 and it not hitting the esp dns causing no captive portal |
re: depends on android version |
re: cellular on |
The problem is not dns, dns already does that with *, the problem is there seems to be a ip restriction requirement. |
Any update on this? Did someone found any official documentation that explains this problem? |
Maybe this does not work because we are not working EXACTLY like a captive portal should. Check this: This is what we do:
The DNS request for clients3.google.com returns the same IP Address as the request for generate_204. We don't hijack the generate_204 http as the linked solutions, we just reply because we pretend to be clients3.google.com. Probably there's a issue with that. I'm thinking out loud here, trying to brain storm this problem. Maybe Google expects us to hijack the generate_204 request by modifying the http and NOT hijacking clients3.google.com by playing with the DNS. That way when we set a non local IP for the AP it works (?). Because Android thinks the request for clients3.google.com was succesful. Just an idea. |
my setup: Android 7.0 on S6 with Firefox browser. (after manually going to 192.168.4.1) |
This has nothing to do with wifimanager this is captive portal testing using default example. Also that is fixed in development version. Use minimal captiveportal code |
Took me quite a while to figure this out, but according to this issue (espressif/arduino-esp32#1037), in order to get a captive notification to show or the popup to open, the DNS server must resolve to a public IP. It will not work with a pivate one (e.g. 192.168.4.1). On Android, a notification ("Register with Network") is displayed in top left notification bar. On IOS, the login popup is displayed.
Took me quite a while to figure this out, but according to this issue (espressif/arduino-esp32#1037), in order to get a captive notification to show or the popup to open, the DNS server must resolve to a public IP. It will not work with a pivate one (e.g. 192.168.4.1). On Android, a notification ("Register with Network") is displayed in top left notification bar. On IOS, the login popup is displayed.
Had the same problem. Found this: https://www.esp8266.com/viewtopic.php?f=6&t=15993 This post of eduperez: "Android devices have the Google DNSs hard-coded, they will always use 8.8.8.8 and 8.8.4.4, despite what the DHPC server might tell them to use. You need to configure your gateway to redirect all outgoing traffic to port 53 to your DNS." That gives the idea, use 8.8.8.8 as IP-address and as DNS-server address. So this demo sketch provided/included at ESP library will work:
|
It may be Vendor dependent "feature". My Samsung A5 with Android 8.0.0 accepts DNS servers received in DHCP response. |
has anyone confirmed @codebeat-nl solution about google dns ? |
@engycz and other, some additional findings. Some google DNS is hard-coded in Android when using auto DHCP. like most people use. If using manual settings (advanced options), assign a static IP address, you can change DNS settings however when second DNS is not altered, it defaults back to 8.8.4.4 (first when empty is 8.8.8.8) when first DNS cannot be found/timeouts. So you can change the DNS however only client-side and you need to alter both DNS fields. This is not very user-friendly so I will use the 8.8.8.8 setting to cover all Android versions. It doesn't harm anything because is an adhoc network. I am using 5.1.1 and other 5.x versions of Android, stock ROMS. |
As per @codebeat-nl, I have just tested setting the AP IP to 8.8.8.8 and am successfully prompted to sign in to the captive portal on a previously-not working stock Samsung Galaxy 9+ when using the more common 192.168.x.x range, and it continues to function as expected on my 3 LineageOS 15.1 (Oreo / 8.1) devices. I will test with a LineageOS 16.0 (Pie / 9) device later tonight. I don't think this is a permanent solution, but it appears to work. |
I found another reference in my re-visiting this topic that suggests if you respond to google's ping domains dns lookup with an address 'other than' your ap address, it will allegedly work.
|
Here's some discussion on these issues on my library for Mongoose OS (which is just FreeRTOS with idf): And my work on splitting it up into separate libraries, working on the fix for samsung related devices: |
Android phones have a operatin system feature that will display a captive portal shortly after connection to a wifi that requires a log in. This is only triggered if you dont use an adress in the private range! This is a new request based on esp8266#5529 and espressif/arduino-esp32#1037 it seems that Android phones will not display the autoredict page if it is in the private IP Range. I found this fix in the two issues above and tried it with several android phones, non of them displayed it bevore: Xiaomi Redmi Note 7 (miui 10.3 Android 7) Samsung Galaxy A7 (Android 8.0.0) Amazon Kindle Fire 7 (Fire OS 5.6.4.0 Android 5.1) I think for easy access to newcomers this should be changed so it works instantly!
I have not followed up on any of the android issues myself, I do not have any android devices to test. |
* Add support for newer mobile OS changes. Took me quite a while to figure this out, but according to this issue (espressif/arduino-esp32#1037), in order to get a captive notification to show or the popup to open, the DNS server must resolve to a public IP. It will not work with a pivate one (e.g. 192.168.4.1). On Android, a notification ("Register with Network") is displayed in top left notification bar. On IOS, the login popup is displayed. * Add support for newer mobile OS changes. Took me quite a while to figure this out, but according to this issue (espressif/arduino-esp32#1037), in order to get a captive notification to show or the popup to open, the DNS server must resolve to a public IP. It will not work with a pivate one (e.g. 192.168.4.1). On Android, a notification ("Register with Network") is displayed in top left notification bar. On IOS, the login popup is displayed.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions. |
This stale issue has been automatically closed. Thank you for your contributions. |
When providing HTTP server you generally have two options:
If you are doing number 1 and pretend using by connecting with an Android device I suggest adding a handler for the error case showing the captive portal:
I noticed that for Android 10, to properly detect the captive portal and make the phone to show "Touch to log in the network" message is necesary. If not you must navigate to any HTTP address and let the DNS do the job for you (not HTTPS). |
**>
You found my question and answer on stackoverflow ;-) |
Yes, I was not a very active user on Internet but after dealing 3 hours with this problem and seeimg some where stuck in the same hole I post what I found. After it I was I trying unsuccessfully :
I luckly found your post on stackoverflow and I made it works and by trying different alternatives I saw that the thing that made the difference was the onNotFound handling. Also I found an issue on tzapu/WiFiManager that have a similar workaround. |
Hardware:
Board: doit v1, ESP32 Dev Module
Core Installation/update date: today
IDE name: platformio
Flash Frequency: ?40Mhz?
Upload Speed: ?115200?
Description:
using captiveportal example
No captive portal launches on windows, linux, android.
surprisingly it works on osx and ios.
The text was updated successfully, but these errors were encountered: