Making Phones Believe the WiFi has Internet

January 20, 2016

We're fighting phone's and other devices to stop them thinking they're in a captive portal AKA walled garden, and show the "Sign in" page, or switch to data instead of WiFi.

Android

From WifiWatchdogStateMachine.java

Android phones from Ice Cream Sandwich will try and get a response from

These are for Nougat, the code for testing connectivity is inside NetworkMonitor.java

This is in Oreo.

Oreo also lists

as a probe URL. Beware that this will require you to setup your DNS so your server is google.com. If users try to do a Google search, e.g. type into their address bar, instead of getting a "Could not connect" error, they'll have a nasty invalid certificate error because your certificate will not be a signed Google SSL certificate.

To fake this, in nginx you'd want something like this

# =====================================================================
# = android walled garden hack                                        =
# =====================================================================

server {
    server_name
        clients3.google.com
        clients.l.google.com
        connectivitycheck.android.com
        connectivitycheck.gstatic.com
        play.googleapis.com
        ;
    listen 80;

    location /generate_204 {
        return 204;
    }
}

iOS

Note: iOS internet detection seems to work differently. It seems to not complain if when a request to these URLs gets no response. But it will believe it is in a captive portal if a server replies. Therefore unless you pretend you're these domains you don't have to do anything, and we don't.

Here are the domains iOS devices contact

We have seen on iOS 9 devices: captive.apple.com

It has been reported that these domains are contacted as well, see Tanaza

They may ask for /library/test/success.html

or just //

They all have wispr in their user agent string

See this stack overflow post

In nginx you'd want something like this in your nginx.conf

# =====================================================================
# = ios garden hack                                                   =
# =====================================================================

server {
    server_name
        apple.com
        captive.apple.com;
    listen 80;

    root /srv/apple/;

    location / {
            try_files /index.html /index.html;
    }

}

And in /srv/apple/index.html

<HTML><HEAD><TITLE>Success</TITLE></HEAD><BODY>Success</BODY></HTML>

DNS

For this to work you need to setup DNS on your router to point the domains in the server_name sections of the nginx configs to your server.

We run DD-WRT on our router and the setup page looks like this. Other routers will have their own interfaces, but the idea is the same (DD-WRT does DNS using dnsmasq, which is a common program to run a dns service).

DD-WRT config page