5

There are several captive portal parameters one could apply to an Android device via settings put global – the most famous probably being

settings put global captive_portal_detection_enabled 0

to completely turn off captive portal check (for Android < 8). Can someone explain how to use the others – e.g. to define a "custom captive portal server for tin-foils"? For example, one cannot simply do a

settings put global captive_portal_server example.com

as that would, in most cases, cause captive portal check to permanently fail (background: doing so, portal check would construct an URL http://example.com/generate_204 and check against that, expecting a specific response).

So apart from simply deactivating captive portal check altogether (which might, as I've read, lead to other issues like not being redirected to the correct portal in some cases), what else can one do to enhance privacy in this context?

Examples (if I got them right):

  • captive_portal_mode (Android 8+?):
    • 0: Don't attempt to detect captive portals
    • 1: Prompt the user to sign in
    • 2: Immediately disconnect from the network and do not reconnect to that network in the future
  • captive_portal_detection_enabled (Android <8?):
    • 0: Completely disable captive portal checks
    • 1: Enable it (default)

While these examples are pretty much straight-forward: How to use the other parameters?

4

Configuring captive portal behaviour

  • captive_portal_detection_enabled (<= Android 7.1.1)
    • works as described in question body
  • captive_portal_mode (>= Android 7.1.2)
    • works as described in question body

Setting captive portal URL(s)

  • captive_portal_server (<= Android 6.0.1)
    • The server that holds a generate_204 page, used to internally craft a URL for captive portal detection (new URL("http", mServer, "/generate_204"); – obsolete as of Android 7.0, see below)
  • captive_portal_use_https (>= Android 7.0)
    • 0: Don't use HTTPS for network validation
    • 1: Use HTTPS (default)
  • captive_portal_http_url (>= Android 7.0)
    • The URL used for HTTP captive portal detection - use in pair with captive_portal_use_https (set to 0)
    • >= Android 7.1.1: OS no longer appends generate_204 to URL automatically, giving input URL some flexibility
  • captive_portal_https_url (>= Android 7.0)
    • The URL used for HTTPS captive portal detection - use in pair with captive_portal_use_https (set to 1)
    • >= Android 7.1.1: OS no longer appends generate_204 to URL automatically

Requirement for the URL to be used

A HTTP 204 response code ("no content") from the server is used for validation, no extra content needed: take the default detection URL for example, curl clients3.google.com/generate_204 returns empty, and inspecting HTTP response by adding --write-out %{http_code} returns 204.'

A small list of usable captive portal server URLs in mainland China (personally tested)

https://captive.v2ex.co/generate_204 (hosted by v2ex.com)

https://connect.rom.miui.com/generate_204 (hosted by Xiaomi, used by default on MIUI)

https://noisyfox.cn/generate_204 (hosted by noisyfox.cn)

https://www.google.cn/generate_204 & https://developers.google.cn/generate_204 (hosted by Google)

https://www.qualcomm.cn/generate_204 (hosted by Qualcomm)

Further notes

The source also mentions parameters captive_portal_user_agent, captive_portal_fallback_url and captive_portal_other_fallback_urls:

  • captive_portal_fallback_url (>= Android 7.1.1) obviously is supposed to hold a single URL, while
  • captive_portal_other_fallback_urls holds multiple further URLs (comma separated list, so the URLs might not contain any comma).

But I personally conducted tests on Android 8.0.0, and both fallback parameters don't work. Assuming they're declarations without an implementation for now.

Some examples of captive portal settings of Android in China show the use of some of the above settings:

adb shell settings put global captive_portal_http_url http://www.google.cn/generate_204
adb shell settings put global captive_portal_https_url https://www.google.cn/generate_204
adb shell settings put global captive_portal_fallback_url http://www.google.cn/generate_204
adb shell settings put global captive_portal_other_fallback_urls http://www.qualcomm.cn/generate_204

Knowing that, "tin foils" even could set up their own verification service. With Apache:

RewriteEngine On
RewriteCond %{REQUEST_URI} /generate_204$
RewriteRule $ / [R=204,L]

or with Nginx:

location / generate_204 { return 204 ; }

References

1, 2 (Chinese), 3 (Chinese)

  • 1
    Related post – and at least with MM, the following code is used: new URL("http", mServer, "/generate_204"); (with mServer being initialized by captive_portal_server if set) – so this should just be the server name (or IP) there (which was most likely one of the reasons it failed for me on a MM device). Not sure when it changed then – but from what you write probably with N. For the 204, I've found this – so it seems I assumed correctly: just the 204 code, no content. – Izzy Nov 27 '17 at 16:42
  • @Izzy Unfortunately the 2 fallback options don't seem to work. Using the default captive_portal_https_url and putting a reachable URL in captive_portal_fallback_url doesn't eliminate the cross mark, and same goes for putting in captive_portal_other_fallback_urls - Setting captive_portal_https_url straight is the only way out. Note that the tests are conducted under LTE instead of WiFi, because for some reason my school WiFi would always direct me to the captive portal even if I set a completely invalid URL. – Andy Yan Nov 28 '17 at 1:52
  • Those fallback parameters might have been introduced with Oreo (note we've looked at Oreo code to find them). Guess you've checked on Nougat, right? // Good idea to include a little server list. AFAIK there also was g.cn available ;) – Izzy Nov 28 '17 at 7:38
  • 1
    @Izzy Oh yeah, didn't realize that, I haven't flashed any of my devices with LOS15 yet. Might be worthy of checking out, and if it works I'll update and ping you to clean up the comments. Also, the HTTPS cert of g.cn is said to have expired in mainland, so it's no longer usable for HTTPS. // But wait... The 7.1.2 source code does also contain reference to captive_portal_fallback_url. – Andy Yan Nov 28 '17 at 8:44
  • Like with many new features, references sometimes turn up before the feature is complete. And the file referenced mainly defines the constants, not the functionality, right? – Izzy Nov 28 '17 at 9:10

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.