mirror of
https://libwebsockets.org/repo/libwebsockets
synced 2024-12-04 13:57:15 +00:00
a60cb84c9e
Implement Captive Portal detection support in lws, with the actual detection happening in platform code hooked up by lws_system_ops_t. Add an implementation using Secure Streams as well, if the policy defines captive_portal_detect streamtype, a SS using that streamtype is used to probe if it's behind a captive portal.
89 lines
3.6 KiB
Markdown
89 lines
3.6 KiB
Markdown
# Captive Portal Detection
|
|
|
|
## Background
|
|
|
|
Wifi devices may face some interception of their connection to the
|
|
internet, it's very common for, eg, coffee shop wifi to present some
|
|
kind of login or other clickthrough before access to the Internet is
|
|
granted. Devices may need to understand that they are in this
|
|
situation, and there are several different techniques for trying to
|
|
gague it.
|
|
|
|
Sequence-wise the device has been granted a DHCP lease and has been
|
|
configured with DNS, but the DNS may be wrongly resolving everything
|
|
to an address on the LAN or a portal on the net.
|
|
|
|
Whether there is a captive portal active should be a sticky state for a given
|
|
connection if there is not going to be any attempt to login or pass the landing
|
|
page, it only needs checking for after DHCP acquisition then. If there will be
|
|
an attempt to satisfy the landing page, the test should be repeated after the
|
|
attempt.
|
|
|
|
## Detection schemes
|
|
|
|
The most popular detection scheme by numbers is Android's method,
|
|
which is to make an HTTP client GET to `http://connectivitycheck.android.com/generate_204`
|
|
and see if a 204 is coming back... if intercepted, typically there'll be a
|
|
3xx redirect to the portal, perhaps on https. Or, it may reply on http with
|
|
a 200 and show the portal directly... either way it won't deliver a 204
|
|
like the real remote server does.
|
|
|
|
Variations include expecting a 200 but with specific http body content, and
|
|
doing a DNS lookup for a static IP that the device knows; if it's resolved to
|
|
something else, it knows there's monkey business implying a captive portal.
|
|
|
|
Other schemes involve https connections going out and detecting that the cert
|
|
of the server it's actually talking to doesn't check out, although this is
|
|
potentially ambiguous.
|
|
|
|
Yet more methods are possible outside of tcp or http.
|
|
|
|
## lws captive portal detect support
|
|
|
|
lws provides a generic api to start captive portal detection...
|
|
|
|
```
|
|
LWS_EXTERN LWS_VISIBLE int
|
|
lws_system_cpd_start(struct lws_context *context);
|
|
```
|
|
|
|
and two states in `lws_system` states to trigger it from, either
|
|
`LWS_SYSTATE_CPD_PRE_TIME` which happens after DHCP acquisition but before
|
|
ntpclient and is suitable for non https-based scheme where the time doesn't
|
|
need to be known, or the alternative `LWS_SYSTATE_CPD_POST_TIME` state which
|
|
happens after ntpclient has completed and we know the time.
|
|
|
|
The actual platform implementation is set using `lws_system_ops_t` function
|
|
pointer `captive_portal_detect_request`, ie
|
|
|
|
```
|
|
int (*captive_portal_detect_request)(struct lws_context *context);
|
|
/**< Check if we can go out on the internet cleanly, or if we are being
|
|
* redirected or intercepted by a captive portal.
|
|
* Start the check that proceeds asynchronously, and report the results
|
|
* by calling lws_captive_portal_detect_result() api
|
|
*/
|
|
```
|
|
|
|
User platform code can provide this to implement whatever scheme they want, when
|
|
it has arrived at a result, it can call the lws api `lws_system_cpd_result()` to
|
|
inform lws. If there isn't any captive portal, this will also try to advance the
|
|
system state towards OPERATIONAL.
|
|
|
|
```
|
|
/**
|
|
* lws_system_cpd_result() - report the result of the captive portal detection
|
|
*
|
|
* \param context: the lws_context
|
|
* \param result: one of the LWS_CPD_ constants representing captive portal state
|
|
* \param redirect_url: NULL, or the url we were redirected to if result is
|
|
* LWS_CPD_HTTP_REDIRECT
|
|
*
|
|
* Sets the context's captive portal detection state to result. User captive
|
|
* portal detection code would call this once it had a result from its test.
|
|
*/
|
|
LWS_EXTERN LWS_VISIBLE int
|
|
lws_system_cpd_result(struct lws_context *context, int result, const char *redirect_url);
|
|
```
|
|
|