Travel router, captive portals and vpn

Hey there!

In 9 out of 10 hotels I stay you don't get an ssid and a wpa key but WiFi is open without encryption and you get some code unique to your stay that limits WiFi access to both, time and traffic.
Usually hotels have terms to be accepted in their captive portal stating that they might capture and store traffic or logs for further use or even do live analysis.

That leads to the idea of setting up a VPN connection within the router.

Obviously such a VPN connection conflicts with being able to access the captive portal. Either I restrict routed traffic to always go through VPN. Then I cannot access the captive portal. Or I allow traffic without VPN to access the portal. Then I can never be sure the VPN really works. Chances are my VPN connection cannot be initialized due to traffic rules.

This becomes even more complicated when the hotel forces you to re-enter your access code every couple of minutes.

So one would need an easy to access button that somehow influences a couple of firewall rules and routing. Not very convenient.

The only thing I came up with so far is not making the travel router access the hotel WiFi directly but use USB based tethering of an Android device as WiFi Uplink. That way, all my clients such as different laptops, smart phones and tablets always go through a VPN, and a dedicated Android device handles the captive portal access as well as the SSID iteration (some hotels have different SSIDs depending on where you are).

I know there's the package of Travelmate. But that one doesn't quite cut it due to the explained misconception of VPN and captive portals.

The thing that keeps me from actually using my idea is really bad WiFi in some hotels that isn't very useful with small smartphone antennas. For now I'm using no android tether just because USB WiFi devices I can add to my travel LEDE have detachable antennas that can be replaced with bigger ones.

Any ideas on this?


Hi @golialive,
The usual way to detect captive portals is to try to access a URL with a specific expected answer.
For example, android devices call a generate_204 URL on a google server which returns a 204 response with an empty content (see threads like
You could implement a cron type job which polls for that URL and checks the response matches your expectations. If not, you could switch to an alternative firewall configuration which allows you to get to the captive portal. As soon as you're able to access that test URL again, you can get back to your firewall configuration which forwards all traffic to VPN.
Where possible, you could keep all these rules in your firewall and enable/disable them when needed using the "enabled" option.
Hope that helps.

Hi @VincentR!

Thank you for your response.

I know how captive portal detection works, and doing such a thing like flipping firewall behavior is definitively possible. However, there's a very specific situation I want to avoid:

When I poll captive portal myself, then there will be some delay. I cannot poll every nano second but would do it more like every minute or two. And entering credentials via laptop or smart phoene is async to polling by the router. This leaves room for the firewall being to not forcing VPN, VPN being not enabled but network devices already start doing something. Maybe that's me being paranoid, but I'd rather not have that.

There's another idea I just had. I could setup a HTTP proxy on the router that specifically does not go through VPN. I could set up a dedicated browser profile (apart from the one I usually use) with static proxy settings. This way I could even always keep firewall settings to force every forwarded ip package through VPN in place, accessing the captive portal (obviously without auto detection) simply goes through the HTTP proxy.

To push it one step further: Maybe one could write an electron app or progressive web application or something that uses that HTTP proxy settings, polls for captive portal redirects every couple of minutes, stays in the background and popps open when a portal redirect is detected.

But to not always fall into the NIH trappe, maybe there is something like that already.


From VPN to captive it's fine as your traffic is protected initially and then it's captive - so nothing comes out.
From clear or captive to VPN is where you're at risk of routing packets without VPN (until you've changed your firewall back or openvpn changed the routing).

I've not yet found a way to avoid those leaks. They're usually small and openvpn tends to connect faster than my monitoring/cron most of the time.

When it comes to restricting the type of traffic that is allowed when a captive portal is detected, it's also not straight forward as captive portals differ widely in implementations. Some are only only http(s), some only DNS based, some require a lot more protocols like UAM/radius to be allowed .
I found that my initial implementation to only allow port 80/443 worked most of the time but not always. Then I added any port between the gateway and the router but It still wasn't enough especially for radius checks that happen on a centralised server somewhere else (MAC verification + radius) for example on public transport with fleets of identical WiFi hotspots. So now, I'm accepting that 1s leak between the time I log into the captive portal and the time my traffic goes through VPN. That also mostly happens initially when I only have one device connected and doing the initial setup.

If you find nice implementations out there, I'd be interested in them.