Cisco – Captive Portal issue with Chrome on Android

captive-portalchromecisco

I have setup WebAuth on our public Wi-Fi. We have a Cisco WLC 5508 and when using iOS, Apple, Windows devices or some Android devices, the page loads correctly, however when I am using a device with Chrome 53.0.2785.124 as the default browser on Marshmallow 6.0.1, I get an error page indicating a possible MTM attack. It reads
"Your connection is not private"
followed by some other text and NET::ERR_CERT_COMMON_NAME_INVALID. Here is a screenshot of the error.

From what I understand, this is due to the browser attempting to reach a URL and is expecting a specific result, however the cert on the requested google.com home page does not match the cert for the host on the returned wlc.mydomain.com SSL certificate.

One section of www.google.com/chrome/browser/privacy/whitepaper.html reads:

In the event that Chrome detects SSL connection timeouts, certificate
errors, or other network issues that might be caused by a captive
portal (a hotel's WiFi network, for instance), Chrome will make a
cookieless request to http:// www.gstatic.com/generate_204 and check
the response code. If that request is redirected, Chrome will open the
redirect target in a new tab on the assumption that it's a login page.
Requests to the captive portal detection page are not logged.

It's actually sending a request to http:// connectivitycheck.android.com/generate_204. The issue I see is in the response from the WLC, the status code is HTTP 1.1 200 OK. I would either expect to see an error due to the page being blocked or a 300 response to indicate a redirection. Based on the text above from Google, it sounds like the browser will enter it's Captive Portal mode (and open a new tab for authentication) WHEN it receives a redirection.

I'm thinking this may be an issue with the WLC configuration, but perhaps it's an issue with Chrome 53 on Android.

If anyone has a recommended solution, I would appreciate it.

Regards,
D

Best Answer

Turns out this is a bug in Chrome.

See Issue 662150

https://bugs.chromium.org/p/chromium/issues/detail?id=662150&can=2&start=0&num=100&q=&colspec=ID%20Pri%20M%20Stars%20ReleaseBlock%20Component%20Status%20Owner%20Summary%20OS%20Modified&groupby=&sort=

Umbrella issue is 335933.

****Update:

We really needed this to work. Google isn't going anywhere fast on coming up with a solution. My new S7E has a captive portal app built in.

I'm guessing other manufactures will still have problems. I did see one patient come in with a Lenovo tablet that experienced this. An employee had the same with her older Samsung device.

I see quite a number of people suffer captive portal pain. I was finally able to resolve this by sinkholing the DNS traffic for the captive portal test FQDNs.

I did try first at my ASA dropping traffic based on FQDN, but as the traffic is sourced from the WLC, I couldn't deny based on VLAN.

So, a DNS hack.

On the WLC, I setup 3 virtual interfaces. 1 is internal. 2 is vendor and 3 is public. Each has their own DHCP scope so I can set all their specific options for their unique situation. 3 has a WLAN with the captive portal associated to it.

I configured my vendor WLAN to use public DNS servers - not a lot of use on that WLAN.

I have two public caching DNS servers running CentOS with BIND 9; I locked them down to a minimize the attack surface. They are VMs on ESXi hosts with a copper NIC installed in each that connects to an isolated virtual switch and my DMZ network. Didn't cost me a dime.

I did this because some users (visiting doctors) using their personal devices and we connect them to the vendor without the captive portal (they connect once and stay connected - Guest have a time limit and need to accept the Acceptable Use Policy).

Added to /etc/named.conf

zone "connectivitycheck.android.com" IN { type master; file "sinkhole.db"; };

zone "clients3.google.com" IN { type master; file "sinkhole.db"; };

/var/named/sinkhole.db

$TTL 600 @ IN SOA localhost root ( 5 ; serial 3h ; refresh 1h ; retry 1w ; expire 1h ) ; min TTL ; IN NS ns. * IN A 127.0.0.1 connectivitycheck.android.com. IN A 127.0.0.1 clients3.google.com. IN A 127.0.0.1

It's not beautiful, but it works very well. I hope this helps someone else.