Bypassing captive portal detection on Android 10

(Yes, I know my phone is running an old version of Android. I am tempted to try GrapheneOS, on a new Pixel device, so that I am on Android 13.)

I run a WireGuard server, listening on port 53, to which my phone is connected the whole time, and my laptop connects “on-demand”.

One of the advantages of using port 53 is that, when using public Wi-Fi with a captive portal - where you have to hand over personal data to connect, usually - my laptop will sometimes bypass the login requirement, and let me use the Internet unhindered. Sometimes it works (great), sometimes it does not (acceptable; I am not expecting this to be perfect, since it depends on the Wi-Fi network’s configuration / firewalling).

Despite WireGuard on port 53, my phone, running Android 10, detects that there is a captive portal, and will not connect without me logging in. I guess that this is what most people want, but typically, I’d rather not log in. I’d prefer not to use a Wi-Fi access point which requires me to log in, than to log in.

But I am curious to see whether I could disable Android’s captive portal detection.

And I think I’ve got it working…

Apparently, there is a way of changing the captive portal detection settings from within the phone itself, but I have not managed to achieve that.

Instead, I’ve done it using the Android Debugging Bridge (adb), connecting to my phone via a USB cable.

On my laptop, I installed the Android ADB tooling with apt install adb.

I enabled ADB debugging on my phone. It was a bit convoluted, and consisted of:

On my laptop, I could then start adb with adb start-server and then connect to the phone’s shell with adb shell.

Within the shell, settings get global captive_portal_mode returned null.

I set up a Wi-Fi network with a captive portal and, by default, the phone’s Wi-Fi settings showed that that was the case, and prompted me to connect:

Wi-Fi settings, showing “Tap here to sign in to network”

Changing the captive_portal_mode setting to 0 should mean the phone ignores captive portals, so I made the change with settings put global captive_portal_mode 0.

I attempted to connect to the test Wi-Fi network, and the phone behaved differently, as it showed the state as just “Connected”:

Wi-Fi settings, showing “Connected”

So that was progress, and may well be success.

It still did not connect, but that could be because my captive portal setup was doing its job properly, and preventing connections.