Captive portal popups: the definitive guide

17,717

Solution 1

All mobile OS just check a web page to decide whether they're behind a captive portal or not.

The mechanism is this:

  1. GET/POST http://foo.com/bar.html
  2. If bar.html == [expected content] > Open Internet
  3. If bar.html != [expected content] > Captive Portal
  4. If bar.html[status] != SUCCESS > No Network

Also, for iOS, you need to have a domain for your WiFi network as it assumes a domainless network without access is a home network and just marks it as No Network instead of Captive Portal.

Just make sure to explicitly redirect the following urls to your captive portal with HTTP Success:

Android / Chromebook:

  • clients3.google.com

iOS 6:

  • gsp1.apple.com
  • *.akamaitechnologies.com

iOS 7:

  • www.appleiphonecell.com
  • www.airport.us
  • *.apple.com.edgekey.net
  • *.akamaiedge.net
  • *.akamaitechnologies.com

iOS 8/9:

Windows

  • ipv6.msftncsi.com
  • www.msftncsi.com

Many vendors have also began to use the User Agent "CaptiveNetworkSupport", though it's not as common as the URL method above. Just check for that UA and always give it your portal page...doesn't work 100% though.

I use the URL method and it's been working fine.

Solution 2

Amazon Kindle (Fire)

The Amazon Kindle (Fire) makes the following request, and if it cannot be retrieved "... it assumes that the user has to login and throws up a Log In screen.":

iOS 8.4

For the latest iOS I had to match all URIs for requests to http://captive.apple.com - not just "/hotspot-detect.html".

iOS 8.4 clients are making requests with randomly generated URIs (e.g. "/xmqPyZUv/3r8jTjv8.html" and "/7exN0TV7q0COX0/eKlBU8baU2tape/fjXUzDHBdE6W0O/BGbw7iYU2DVBh1/sVBlx8icYzTTtE.html") in URL requests to the following domains to detect a captive portal:

Share:
17,717

Related videos on Youtube

ppparadox
Author by

ppparadox

Updated on September 18, 2022

Comments

  • ppparadox
    ppparadox almost 2 years

    I'm manually implementing a WiFi captive portal. I've got everything pretty much working BUT a single hitch: i want everyone to see their mobile OSs' (or computer OSs') captive portal popup for a flawless experience.

    Since each one of them has its own twisted way of doing it i'm seemingly unable to get a consistent cross-platform experience.

    To make this happen, can I have some help to describe either (1) what URL requests from WiFi clients need to be redirected to a login page, and/or (2) what nginx or apache web server configuration can be used to redirect WiFi clients to a login page?

    My captive portal login page in this example is http://captiveportal.lan . Here are some of the Operating Systems I am trying to resolve this for.


    Android 4/5/6

    • Apache:
      RedirectMatch 302 /generate_204 http://captiveportal.lan
    • nginx: ?

    Previous Android versions

    • Apache: ?
    • nginx: ?

    iOS 8

    • Apache .htaccess:
      RewriteEngine on
      RewriteCond %{HTTP_USER_AGENT} ^CaptiveNetworkSupport(.*)$ [NC]
      RewriteRule ^(.*)$ http://captiveportal.lan [L,R=302]

    • nginx: ?

    Previous iOS versions

    • Apache: ?
    • nginx: ?


    Windows phone

    • Apache:
      RedirectMatch 302 /ncsi.txt http://captiveportal.lan
    • nginx: ?


    Windows 7\8\10

    • Apache: see windows phone (works on win7).
    • nginx: ?

    Mac OS

    • Apache: ?
    • nginx: ?

    Amazon Kindle - does it have a popup?

    • Apache: ?
    • nginx: ?
    • ppparadox
      ppparadox about 8 years
      No it is not too broad, it is simply a multi-platform issue. THE MOST multi-platform issue there can be, perhaps. It has also reached the "notable question" status (more than 2500 views) so people are really interested in it and you're rendering a HUGE disservice to all by preventing contributions from pouring in. For shame!
    • Rui F Ribeiro
      Rui F Ribeiro almost 7 years
      Thanks so much for the post; it allowed me to do this unix.stackexchange.com/questions/386242/…
  • ppparadox
    ppparadox almost 9 years
    Does iOS 8.4 set the UserAgent to "CaptiveNetworkSupport"? Care to share some working webserver conf\firewall rules\php snippets you use to obtain the popup? Also, why has someone downvoted you without bothering to explain why? Stupid people...
  • ppparadox
    ppparadox almost 9 years
    Care to share some working webserver conf\firewall rules\php snippets you use to obtain the popup?
  • Russell E Glaue
    Russell E Glaue almost 9 years
    The exact agent string is "CaptiveNetworkSupport-277.10.5 wispr". When I redirect these requests (listed in this question) to a login page, Apple iOS will pop up a login page, and Android will show a login header bar. After successfully logging in on the Login page, the captive portal system must allow these HTTP requests to be successful in order for the popup window and login bar to disappear. I have successfully tested this in a custom captive portal I created using only Linux, dnsmasq, and Apache httpd server.
  • ppparadox
    ppparadox almost 9 years
    Forgot to ask if the Kindle sets that user agent too.
  • Russell E Glaue
    Russell E Glaue almost 9 years
    For kindle I am seeing "Dalvik/2.1.0 (Linux; U; Android 5.0.1; VS985 4G Build/LRX21Y)" (maybe it is a kindle app?). This thread mobileread.com/forums/showthread.php?t=188439 says "Mozilla /5.0 (Linux; like iPhone; U; en-US) AppleWebKit/528.5+ (KHTML, like Gecko, Safari/528.5+) Version/4.0"
  • Russell E Glaue
    Russell E Glaue almost 9 years
    @ppparadox I don't know why I got the down vote seconds after I posted. If you like my contribution, please give me an upvote. Thanks.
  • ppparadox
    ppparadox almost 9 years
    I did but i am yet to build up enough reputation in order to count... will do my best!
  • DavidT
    DavidT over 8 years
    Looks like Android v6 is using a different url. connectivitycheck.gstatic.com which is mentioned here
  • ppparadox
    ppparadox about 8 years
    Does the kindle even have a captive portal popup?
  • AShelly
    AShelly over 7 years
    Why would you have to explicitly redirect the test URLs? Wouldn't you just serve the login page for every URL until the user logged in?