Wi-Fi

Wi-Fi Captive Portal

Wi-Fi Captive Portal: Deep Technical Analysis


Overview


A captive portal is a Layer-3 gateway policy, not a Wi-Fi feature. The client associates and gets an address normally, and a stateful enforcement point blocks forwarding until a web or API transaction marks that client as authorized. Nothing in IEEE 802.11 defines it. The IETF standardizes only discovery (RFC 8910) and a status API (RFC 8908), plus an informational architecture (RFC 8952). Everything else interception, the login UI, the session model and the firewall mechanics is implementation specific.


Typical Deployments

DeploymentTypical access method
Public hotspots and cafésTerms-of-service click-through
HotelsRoom number + surname, or PMS-issued voucher
AirportsTime-limited free tier, paid upgrade
Enterprise guest accessSponsor approval, SMS/email OTP
Subscription hotspotsAccount login, often RADIUS-backed
Home routersGuest SSID with a simple portal

Component Roles


ComponentRole in the portal
Wireless client (STA)Associates, runs DHCP/SLAAC, runs OS captive-portal detection, renders the login page.
AP / hostapd + driverBeacons, association, keying, per-STA isolation (ap_isolate), VLAN tagging; emits STA connect/disconnect events. No HTTP role.
DHCP server (dnsmasq/odhcpd)Assigns addresses, advertises RFC 8910 option; leases are the main IP↔MAC binding source.
DNS resolverResolves walled-garden names; must answer truthfully.
Gateway / firewallThe enforcement device: drops or redirects unauthorized forwarding, NATs authorized traffic.
Portal web serverServes the splash page, the RFC 8908 API and the login endpoint.
Portal controller / session DBMaps client → session, holds state, programs the firewall, handles expiry.
Authentication backend / RADIUSValidates credentials or vouchers; returns policy (session timeout, bandwidth, VLAN); receives accounting.

Standard


StandardizedImplementation-specific
802.11 auth/assoc, RSN, SAE, OWE (RFC 8110), 802.1X, 802.11u ANQP elementsHTTP 302 interception and walled-garden lists
DHCPv4 opt 114, DHCPv6 opt 103, RA opt 37 (RFC 8910)OS probe URLs and expected bodies
Captive Portal API, application/captive+json (RFC 8908)Splash page, login flows, vouchers
CAPPORT architecture (RFC 8952, Informational)Client identification, firewall rules, session DB
HTTP 511 Network Authentication Required (RFC 6585)Multi-AP session sharing
RADIUS (RFC 2865/2866), CoA/Disconnect (RFC 5176)Vendor RADIUS attributes for portals (e.g. WISPr)

End-to-end Connection Flow


The client reaches the Internet only after thirteen hand-offs, and only stages 10–11 are portal-specific; most field failures happen at stages 4–7, before any login.

Alt text


Stage-by-stage


#StageInitiator → processorProtocol / messageExpected resultCommon failures
1Scan, SSID selectSTA → APProbe Req/Resp, Beacon; optional ANQP (802.11u)SSID listed with correct securityHidden SSID; wrong country/channel; client refuses OWE transition mode
2802.11 auth + associationSTA → hostapd/driverAuth (Open/SAE), (Re)Assoc Req/RespAID assignedMax STA reached; ACL deny; SAE H2E/PMF mismatch
3Security negotiationAP ↔ STAEAPOL-Key 4-way (WPA2/3/OWE) or EAP (802.1X)PTK/GTK installed, port openWrong PSK; PMF required but unsupported; group rekey timeouts
4Address assignmentSTA → DHCP server; STA → router (RS)DHCPv4 DORA; SLAAC/DHCPv6; RFC 8910 optionsIPv4 lease, IPv6 addresses, opt 114/103/RA 37DHCP blocked by guest firewall; pool exhausted by randomized MACs; VLAN mismatch
5DNSSTA → resolverDNS/UDP 53 (or DoT/DoH)Real answers for all namesResolver unreachable from guest zone; client uses DoH to a blocked IP
6Portal detectionSTA OSRFC 8908 API GET, or HTTP probeOS decides “captive”Probe host in walled garden (no detection); probe blocked instead of redirected (“no Internet”)
7Interception / discoveryGatewaynftables DNAT tcp/80 → portal; or API URL302 or captive:trueHTTPS probe timeouts; IPv6 probe bypasses rules; redirect to IP literal with TLS
8Portal pageSTA → portal web serverHTTPSPage renders in CNA/browserCert not valid for name; CDN assets outside walled garden; CNA lacks cookies/JS features
9User actionUser → portal appHTTPS POSTCredentials/voucher submittedCSRF/session cookie lost between CNA and browser
10Backend authorizationPortal → auth backendRADIUS Access-Request, REST, DBAccept + policyRADIUS secret/timeout; clock skew on vouchers
11Firewall updateController → kernelnetlink (nft), ipsetClient’s addresses in auth setsRace: OS re-probes before rule installed; only IPv4 added
12Internet accessSTA → Internet via gatewayRouted + NATOS shows connectedMTU, upstream DNS, NAT table full
13Expiry / logoutKernel timer or controllerSet timeout, RADIUS Session-Timeout, CoA/Disconnect (RFC 5176), STA disassocClient returns to captiveStale conntrack keeps flows alive; set entries never removed

Captive Portal Detection on Client Devices


Every major OS uses two mechanisms:

  • positive signal (RFC 8910 option → RFC 8908 API)
  • legacy cleartext HTTP probe to a vendor host whose exact response it knows

Any deviation a redirect, a different body, an empty 200 is read as “captive”, a timeout or reset is read as “no Internet”, which shows no login prompt. Probe URLs below are as documented by the vendor where a vendor document exists; anything marked observed comes from third-party captures and can change without notice.


Standards-based Discovery


  • The network places an HTTPS API URI in DHCPv4 option 114, DHCPv6 option 103 or IPv6 RA option 37. RFC 8910 replaced RFC 7710, whose DHCPv4 code 160 conflicted with other uses (RFC 8910). The URI urn:ietf:params:capport:unrestricted tells clients they can skip detection.
  • The client sends GET with Accept: application/captive+json; the server must answer with that content type and a JSON body whose only mandatory key is captive (boolean). Optional keys: user-portal-url, venue-info-url, can-extend-session, seconds-remaining, bytes-remaining (RFC 8908).
  • The API must be HTTPS with a certificate valid for the provisioned hostname; if validation fails the client must ignore the API and fall back to legacy behaviour. Responses should carry Cache-Control: private or no-store. A captive network should still allow OCSP/CRL and NTP so the client can validate the certificate.
  • Client identity: if the API server cannot see the client’s identity itself (e.g. the API is off-box and NATed), RFC 8908 §4 recommends a per-client API URI (e.g. /captive-portal/api/X54PD39JV) handed out in each DHCP lease.

System Architecture


Alt text

The gateway is the only place that sees all guest traffic, has the DHCP bindings, and can NAT. The APs only bridge the guest SSID into VLAN 30 and isolate clients; they hold no authorization state, so roaming between them does not affect the portal session.


Responsibilities


ComponentOwnsInputsOutputsMust not
hostapd + driverAssociation, keying, PMF, per-STA isolation, VLAN mappinghostapd.conf (via netifd/UCI)STA connect/disconnect events (ctrl iface, ubus hostapd.*)Make portal decisions
dnsmasqDHCPv4 leases, opt 114, DNS forwardingUCI dhcpLease DB, dhcp-script / ubus lease eventsFake DNS answers for the whole Internet
odhcpdRA, DHCPv6, NDP proxyingUCI dhcpIPv6 lease/neighbour dataHand out global IPv6 if IPv6 is not enforced
nftables (fw4 + custom table)Packet enforcement, redirect, NAT, rate limitsRules + dynamic setsAccept/drop/DNAT decisions, countersContain business logic
Portal controllerSession lifecycle, client identity binding, timers, RADIUS clientLeases, STA events, login resultsSet element add/del, accounting, logsTrust client-supplied identifiers
Web serverTLS termination, splash, login, APIHTTP requestsCalls to controllerExpose management UI on the guest interface
Auth backend / RADIUSCredentials, vouchers, policyAccess-RequestAccept + attributes; CoA/Disconnect—

Comparison of Deployment Models


Gateway-based enforcement with an optionally external or cloud-hosted portal UI is the right default for embedded products; AP-based enforcement only makes sense for standalone single-AP devices or with a controller that synchronizes state.


AspectA. Gateway-basedB. AP-basedC. Centralized enterprise (controller)D. External portalE. Cloud-managed
Traffic flowAP bridges to gateway; gateway redirects, enforces, NATsAP filters/redirects locally (often bridge-family rules), then bridges or routesAPs tunnel (CAPWAP/GRE/VXLAN) or VLAN-trunk guest traffic to controller/anchorEnforcement local; splash/login on a remote web server, result returned to enforcement point via signed redirect or APILocal enforcement (AP or gateway) driven by cloud policy; portal often cloud-hosted
Session-state locationGatewayEach APController (replicated in HA pairs)Enforcement point + external serverCloud DB, cached on device
RoamingTransparent across APs on the same L2 guest VLANLost on roam unless APs sync stateTransparent (central anchor)Same as the enforcement point usedDepends on whether device or cloud is authoritative; usually re-auth by MAC on new AP
ScalabilityHundreds to low thousands of clients per gateway (CPU/conntrack bound)Scales with APs, but per-AP RAM is smallHigh, controller-sizedPortal scales independentlyHigh; enforcement still local
Security boundaryOne hardened box; guest never touches AP managementEvery AP is an enforcement point and must be hardenedStrong; guests tunneled away from local LANMust authenticate the callback (HMAC/token), or anyone can grant accessCloud account and device-cloud channel become attack surface
External dependencyNone for local ToS/voucherNoneController reachabilityLogin impossible if WAN or portal host is downLogin and policy changes depend on WAN + cloud; define offline behaviour
Operational complexityLow–mediumLow per box, high at scaleHighMediumLow for operator, high for vendor
Home routerBest fitAcceptable (single AP)OverkillRareCommon in ISP CPE
HospitalityGood (PMS integration on portal server)WeakGood for large hotelsCommon (vendor portal)Very common
Public hotspotGoodWeakGood (carrier)CommonVery common
Enterprise guestGood for branchesWeakBest fitCommon (sponsor portal)Common

ModelTypical useKey strengthMain limitation / design note
Gateway-basedSingle-site routers and gatewaysSees every packet, owns DHCP bindings, applies IPv4 and IPv6 policy consistentlyCPU for TLS and nftables set size on small SoCs; budget conntrack entries per client
AP-basedStandalone APs that also route (travel routers, single-AP SOHO)No separate gateway neededWith multiple bridged APs, each sees only its own clients, so a roam re-captures the client unless the session is pushed to all APs. Bridge-family filtering needs br_netfilter or the nftables bridge family and must handle IPv6 ND and DHCP explicitly
Centralized controllerLarge enterprise and campusGuest traffic tunneled to an anchor controller (often in a DMZ): strong isolation, one session storeTunnel MTU overhead; dependency on the controller
External portalVendor or hosted login UI (openNDS calls it FAS; vendors call it external captive portal)UI and authentication scale independently of the enforcement boxSecurity rests on the token exchange: the enforcement device redirects with a signed query string, the external server calls back with a token. openNDS, for example, sends a hashed client id and requires a return hash computed with a pre-shared faskey (openNDS FAS)
Cloud-managedMulti-site operatorsSame as D, plus central configuration and reportingDefine WAN-loss behaviour: fail-closed (no new logins), fail-open for existing sessions, or a local ToS fallback

Linux/OpenWrt Implementation


ComponentChange neededIntegration point
hostapd / wpad, driverNone (config only)UCI wireless; ubus hostapd.<ifname> events and del_client; hostapd_cli
netifdNoneUCI network; ubus network.interface.guest
dnsmasqNone (config; dnsmasq-full if you need nftset walled garden)UCI dhcp, dhcpscript lease hook, dhcp_option
odhcpdNoneUCI dhcp; ubus call dhcp ipv6leases
firewall4NoneUCI zones/rules; custom table in a separate file
nftablesNew table inet portalnft -f, netlink from controller
Web serverNew uhttpd instance or nginx bound to guest IPUCI uhttpd or nginx conf
Portal controllerNew daemonprocd service, ubus object portal, nft netlink, RADIUS client

References