What are we talking about?
Android tries to send the packages over ‘http://clients3.google.com’ and if the answer is successfully you get an HTTP Response-Code 204 (the answer is correct but it doesn’t contain any data). Basically the IP and a timestamp will be transmitted.
Some of the domains used by Google to check for internet connection for Android.
http://clients1.google.com/ http://clients3.google.com http://connectivitycheck.gstatic.com http://connectivitycheck.android.com
and other domains used for this purpose by Google.
If the domain is accessible and returns “generate204” code, the captive portal is not triggered automatically. “generate204” response means the device is connected to the internet.
Why is this a big deal?
- Google knows every time you turn on any network automatically(WiFi, LTE, HSDPA etc.)
- Almost every Android phone has this, even if you do not run Goole Play Services.(ex. LineageOS without Google play services/Gaps)
- Anyone with network logs can theoretically do a co-relation attack. This may or may not be a threat to your operational security. (Captive portal requests generate DNS and http traffic in plain text)
- IP address and time stamps is a huge privacy leak. Google is a PRISM partner. https://en.wikipedia.org/wiki/PRISM_(surveillance_program)
- VPN users can be deanonymized by DNS and IP logs checking for captive portal generates.
Client is resting on IP xxx.xxx.xxx.xxx @ time DD/MM/YY
Switches on VPN
Client is on new IP yyy.yyy.yyy.yyy @ time DD/MM/YY
I tried blocking the
connectivitycheck.gstatic.com host at DNS level with pihole.
It didn’t solve the problem. It would simply give me a WiFi connection error and switch to mobile data where the DNS resolver wasn’t filtered with a pihole.
PSA: By doing this you will lose the ability to automatically check for captive portals and internet connection status.
Settings that need changing in ADB shell.
(Requires root in adb shell only, you can enable it in Developer options in LineageOS)
For Android ~4+
settings put global captive_portal_detection_enabled 0
settings put global captive_portal_server localhost
Since Android 7+ (Tested on Pie)
settings put global captive_portal_mode 0
Connecting to ADB over WiFi.
[email protected] ~> adb connect <phone_IP> * daemon not running; starting now at tcp:5037 * daemon started successfully connected to <phone_IP>
Initiate a shell and accept the keys on phone.
8k@8192 ~> adb shell error: device unauthorized. This adb server's $ADB_VENDOR_KEYS is not set Try 'adb kill-server' if that seems wrong. Otherwise check for a confirmation dialog on your device.
Get in a bash shell, drop the command, exit.
8k@8192 ~> adb shell beryllium:/ $ bash shell@beryllium / $ settings put global captive_portal_mode 0 shell@beryllium / $ exit exit beryllium:/ $ exit
No more checking.
Be sure to let me know if you have more domains that you have caught androids checking connection to. Some of the steps above may not work for your device. Please do research.