How Captive Portals Work: The Technical Story
You connect to hotel WiFi. You open a browser. Instead of your homepage, you land on a page asking for a room number or email address. Nothing else works - no apps, no email, no other websites. Just that one page.
That's a captive portal. It's one of the most commonly encountered pieces of network infrastructure in public spaces, and it works through a specific chain of mechanisms that most users never think about: a modified DHCP response, a DNS server that lies to you, and an HTTP redirect that catches your first request.
This article covers each step in that chain, why it works, where it breaks down, and how the BLEShark Nano implements its own captive portal for security testing.
Step 1: DHCP - Getting on the Network
When you connect to a WiFi network, your device requests an IP address via DHCP (Dynamic Host Configuration Protocol). Your device broadcasts a DHCP Discover; the network's DHCP server responds with an Offer; your device sends a Request; the server confirms with an Acknowledgement. This four-way exchange (DORA: Discover, Offer, Request, Acknowledge) assigns you an IP address.
Along with the IP address, the DHCP response includes several other parameters:
- Subnet mask
- Default gateway (the router IP you send traffic to)
- DNS server addresses
- Lease duration
In a captive portal network, the DHCP response looks legitimate. You get a real IP address and a real gateway. The subtle change is in the DNS server field - the DNS server you're pointed to is controlled by the portal operator, not a public resolver. This sets up the next step.
graph TD
subgraph "Phase 1: DHCP Assignment"
A["Device sends DHCP Discover"] --> B["AP responds with Offer"]
B --> C["Device sends Request"]
C --> D["AP sends ACK with IP, Gateway, DNS"]
D --> E["DNS field points to portal server"]
end
subgraph "Phase 2: DNS Hijacking"
E --> F["Device queries any domain"]
F --> G["Portal DNS returns its own IP"]
G --> H["All domains resolve to portal"]
end
subgraph "Phase 3: HTTP Redirect"
H --> I["Browser sends HTTP GET"]
I --> J["Portal returns 302 redirect"]
J --> K["Browser loads login page"]
end
The three-phase captive portal interception chain - from DHCP assignment through DNS hijacking to HTTP redirect
Step 2: DNS Hijacking - All Roads Lead to the Portal
DNS (Domain Name System) translates human-readable domain names into IP addresses. When your browser wants to load example.com, it first asks the DNS server "what's the IP address for example.com?" The server responds with something like 93.184.216.34, and your browser connects to that IP.
On a captive portal network, the DNS server is configured to return the portal's own IP address for every query, regardless of what domain was requested.
Ask for google.com? You get the portal IP.
Ask for apple.com? Portal IP.
Ask for your email server? Portal IP.
Any domain at all? Portal IP.
This is DNS hijacking - the DNS server is lying about every name resolution response. Every hostname your device queries resolves to the same address: the captive portal server.
This is why you can't use any other website or service while in the captive portal - all DNS queries resolve to the portal's IP, so all connections attempt to reach the portal server. Your email client times out because it can't reach its mail server. Your messaging app can't connect. Only the portal page itself responds.
Step 3: The HTTP Redirect
At this point, your device has an IP address and every DNS query resolves to the portal server. When your browser makes its first HTTP request - say, an automatic request to a connectivity check URL, or you manually opening a page - the portal server responds with an HTTP 302 redirect to the portal page URL.
The redirect response looks like this:
HTTP/1.1 302 Found
Location: http://portal.example.com/login
Your browser follows the redirect and loads the portal login page. From the user's perspective, they opened a browser and got the portal page. The underlying chain was: DNS hijacked -> request reached portal server instead of real destination -> redirect sent -> portal page loaded.
Some implementations skip the redirect and just serve the portal page directly for any HTTP GET request, regardless of the requested host. This is slightly less clean (the URL bar won't show the original domain) but functionally identical.
How OS Captive Portal Detection Works
sequenceDiagram
participant Device as Device OS
participant DHCP as DHCP Server
participant DNS as Portal DNS
participant Portal as Portal Server
participant Real as Real Internet
Device->>DHCP: DHCP Discover
DHCP->>Device: DHCP ACK (IP + DNS = portal)
Note over Device: OS triggers connectivity check
Device->>DNS: A record for captive.apple.com?
DNS->>Device: Returns portal server IP
Device->>Portal: GET /hotspot-detect.html
Portal->>Device: HTTP 302 to /login
Note over Device: Expected "Success" page not found
Note over Device: Captive portal detected!
Device->>Device: Show portal popup/sheet
Device->>Portal: User submits credentials
Portal->>Portal: Whitelist device IP
Device->>DNS: A record for apple.com?
DNS->>Device: Real IP (now unblocked)
Device->>Real: Normal traffic resumes
Full OS captive portal detection sequence - from DHCP through probe request to authentication and release
Modern operating systems don't wait for a user to open a browser. They actively detect captive portals immediately after connecting to a network by making HTTP requests to known endpoints and checking for expected responses.
Apple devices connect to captivedetect.apple.com and expect an HTTP 200 response with specific content. If they get a redirect instead, they know they're behind a captive portal and automatically open the portal page in a dedicated browser sheet.
Android devices check connectivitycheck.gstatic.com similarly. Windows checks msftconnecttest.com. Linux and most non-Apple/Google systems have their own endpoints.
Each check works the same way: make a known HTTP request, verify the response is what's expected. If you get a redirect or wrong content, you're behind a portal. The OS then shows the portal notification or automatically opens the portal window.
The captive portal server needs to handle these OS-specific probe URLs correctly for auto-detection to work smoothly. A well-implemented portal intercepts these probe requests and serves the redirect. A poorly implemented one may not recognize them, causing inconsistent "no internet connection" alerts alongside the portal redirect.
Why HTTPS Breaks Captive Portals
sequenceDiagram
participant Browser
participant DNS as Portal DNS
participant Portal as Portal Server
participant CA as Certificate Authority
Browser->>DNS: Resolve www.google.com
DNS->>Browser: Returns portal IP (not Google)
Browser->>Portal: TLS ClientHello (SNI: google.com)
Portal->>Browser: TLS ServerHello + Certificate
Note over Browser: Certificate says "portal.example.com"
Note over Browser: Expected "www.google.com"
Browser->>CA: Verify certificate chain
CA->>Browser: Valid cert, but wrong domain
Note over Browser: CERTIFICATE MISMATCH ERROR
Browser->>Browser: Display security warning
Note over Browser: Connection blocked - no redirect possible
Why HTTPS breaks the captive portal redirect chain - TLS certificate validation prevents the interception
HTTPS is encrypted and authenticated. For HTTPS to work, your browser verifies that the server's TLS certificate is valid for the domain you requested. The portal server can't intercept an HTTPS request the same way it intercepts HTTP.
Here's what happens when your browser makes an HTTPS request on a captive portal network:
- Your device asks DNS for the IP of, say, www.google.com
- DNS returns the portal server's IP
- Your browser initiates a TLS handshake with the portal server, expecting a valid certificate for www.google.com
- The portal server can only present its own certificate, which is valid for portal.example.com, not www.google.com
- Your browser sees the certificate mismatch and displays a security error
- The connection fails
This is why captive portals rely on HTTP for the initial redirect. They need that first HTTP request to deliver the redirect response. Once you've authenticated through the portal and your IP is whitelisted, normal HTTPS traffic is allowed through to the real internet.
HSTS (HTTP Strict Transport Security) makes this even more complicated. If a browser has previously seen an HSTS header for a domain, it will refuse to connect via HTTP at all - it will only try HTTPS. If your browser has visited a major HTTPS site before and cached its HSTS policy, that site can't be used as the first HTTP request to trigger the portal redirect. This is why captive portal OS detection uses known plain HTTP endpoints rather than relying on the user's first browsing request.
The Walled Garden Model
Not all captive portals are purely authentication gates. Some implement a "walled garden" - a set of IP addresses or domains that are accessible before authentication. This allows things like:
- Connecting to an external payment processor for credit card access
- Loading the portal's own static assets (images, CSS) from a CDN
- Allowing access to a company's public website before employees authenticate
- Providing emergency service access (call 911 before logging in)
The walled garden is implemented in the portal's firewall rules. DNS still hijacks all queries to the portal IP, but the portal server or an upstream firewall has a whitelist of IPs that are allowed through without authentication. Traffic to those IPs bypasses the redirect.
BLEShark Nano: Captive Portal Implementation
The BLEShark Nano implements a full captive portal stack. When the captive portal feature is active, the Nano does the following:
Hosts a WiFi access point: The Nano broadcasts an SSID (configurable). Connecting devices associate with this AP.
Runs a DHCP server: Connected clients receive IP addresses in the 192.168.4.x range, with the Nano as gateway and DNS server.
Runs a DNS server that hijacks all queries: Every DNS request from connected clients is answered with the Nano's own IP address, regardless of the queried domain. This is the core of the portal redirect mechanism.
Serves an HTTP server: Any HTTP request to the Nano's IP (which is every HTTP request, since DNS resolves everything to that IP) serves the captive portal page. The initial response for unknown paths is a redirect to the portal page URL.
Captures form submissions: If the portal page contains a form, submissions are captured and stored in JSON format, accessible via the file portal. This is used in security awareness demonstrations - not for credential harvesting in an unauthorized context.
The portal HTML is fully customizable. You upload a custom HTML file via the BLEShark's file portal, and the Nano serves it instead of the default template. The custom HTML supports standard HTML elements, inline CSS within the file, and JavaScript. Forms work - submissions are captured in portal.json on the device.
OS Detection and Auto-Open Behavior
When a device connects to the BLEShark's AP and receives DHCP, the OS immediately performs its captive portal probe. The BLEShark's HTTP server handles these probes and returns redirect responses, triggering the OS to automatically open the portal page in the system browser or captive portal sheet.
This means on iPhones and Android phones, connecting to the BLEShark AP will automatically open the portal without any user action. On Windows and macOS, a notification appears prompting the user to sign in. The experience matches exactly what users encounter at hotels and airports - because it uses the same underlying mechanism.
Why This Matters for Security Testing
Captive portals are a standard social engineering vector in authorized red team assessments. The scenario: an attacker sets up an AP with a familiar or plausible SSID, waits for devices to auto-connect (or convinces targets to connect), and presents a portal page that looks like a corporate login or a terms-of-service acceptance page.
Testing this with BLEShark lets a security team demonstrate the attack concretely - not just describe it as a theoretical risk. Running the demo in a controlled environment, with staff consent and a clearly fake portal page, builds more understanding than a written finding ever will.
The BLEShark also lets you test your organization's detection posture: does anyone notice the new AP? Does anything alert on the rogue DHCP server? Does the DNS hijacking get flagged? These are all meaningful questions for a wireless security audit.
For testing at scale across multiple areas simultaneously, Shiver mesh support (up to 16 nodes, ESP-NOW, 20-50m range) lets you deploy multiple captive portal instances across a physical space and aggregate results from all of them to the master node.
The Technical Chain, Summarized
Captive portals work through three chained mechanisms:
- DHCP: Point the client at a portal-controlled DNS server
- DNS: Resolve every domain to the portal server's IP
- HTTP redirect: Intercept the first HTTP request and redirect to the portal page
HTTPS breaks the redirect chain because TLS certificate validation can't be faked without triggering browser security errors. OS captive portal detection exists precisely because this flow is predictable - probe a known HTTP endpoint, check for an unexpected response, infer portal presence.
Understanding each of these steps in detail is the difference between a security professional who knows "captive portals redirect traffic" and one who can audit a portal implementation, identify weaknesses, and build one from scratch for an authorized assessment.