mcp: project-plan — Travel Pi-Router Captive Portal Fix
This commit is contained in:
parent
4938ff09a6
commit
3f2a3581a7
62
Sources/Homelab/travel-pi-router.md
Normal file
62
Sources/Homelab/travel-pi-router.md
Normal file
@ -0,0 +1,62 @@
|
||||
---
|
||||
created: '2026-06-26'
|
||||
path: Sources/Homelab
|
||||
project: travel-pi-router
|
||||
tags:
|
||||
- dns
|
||||
- tailscale
|
||||
type: project-plan
|
||||
---
|
||||
|
||||
## Goal
|
||||
|
||||
Stop hand-running `resolvectl` DNS overrides every time a captive portal won't load on the road. Build a travelmate hook that drops Pi-hole out of the DNS path on a fresh uplink association so the portal's DNS interception can fire, lets the portal auth complete, then restores Pi-hole for normal filtered browsing.
|
||||
|
||||
Scope this trip realistically: the **association-side drop** is the reliable half and the primary deliverable. The **swap-back trigger** (knowing when auth completed) is portal-dependent and flaky across the EU hospitality gateway mix — acceptable to leave that half manual for now.
|
||||
|
||||
## Problem
|
||||
|
||||
Stack is OpenWRT + travelmate + Pi-hole on a Raspberry Pi travel router. LAN clients point at the Pi (Pi-hole) for DNS, which forwards upstream.
|
||||
|
||||
Captive portals deadlock: the portal needs to hijack the client's first DNS queries to serve its login page, but Pi-hole answers authoritatively, so the hijack never lands and the portal page never loads ("you're offline"). Confirmed root cause this trip — pinning a client's DNS directly at the upstream WiFi resolver (`resolvectl dns <iface> <upstream>`) let the portal render and auth succeeded immediately.
|
||||
|
||||
US vs EU difference: US portals lean on standard captive-detection probes (`captive.apple.com`, `connectivitycheck.gstatic.com`) that tolerate Pi-hole in the path. EU hospitality gateways more often rely on transparent DNS interception of whatever you query first, which Pi-hole breaks. RFC 8910 (DHCP-delivered portal URL) would sidestep all of this but adoption is uneven, with more legacy gateways in the EU mix.
|
||||
|
||||
A hardcoded `1.1.1.1` secondary resolver makes this worse — queries that escape to Cloudflare can't be hijacked, so the portal never triggers. During the portal phase DNS must point **only** at the upstream-provided resolver.
|
||||
|
||||
## Locked Decisions
|
||||
|
||||
- Primary deliverable is the **association-side Pi-hole drop**; swap-back can stay manual for now.
|
||||
- **OpenWRT config backup is mandatory before any travelmate edits.** Failure mode of a buggy DNS-rewrite hook is "no DNS at all," which on a captive network means you can't reach the portal to recover — i.e. locked out over SSH in a hotel room. Backup is the rollback.
|
||||
- No `1.1.1.1` (or any fixed public) secondary resolver in the portal-phase config — it lets queries escape the hijack.
|
||||
- `resolvectl` link overrides are runtime-only (don't survive reconnect/reboot); fine as the manual stopgap, not a persistent fix.
|
||||
|
||||
## Open Items
|
||||
|
||||
- [ ] Confirm travelmate version and exact hook filename/mechanism (`opkg list-installed | grep travelmate`) — hook name changed across releases.
|
||||
- [ ] Decide swap-back trigger: manual for this trip vs. a detection probe against a known-good upstream domain once stable.
|
||||
- [ ] Validate the swap-back logic before trusting it (don't ship a hook that can strand DNS).
|
||||
- [ ] Decide whether to build on the road (stable connection + snapshot) or defer to home where rollback is safe.
|
||||
|
||||
## Phases
|
||||
|
||||
### Phase 0 — Backup (do first, non-negotiable)
|
||||
- [ ] `sysupgrade -b /tmp/backup-$(date +%Y%m%d).tar.gz` on the router
|
||||
- [ ] Copy the backup tarball off the router to the laptop
|
||||
- [ ] Confirm the tarball is on the laptop before any config change
|
||||
|
||||
### Phase 1 — Association-side drop (reliable half)
|
||||
- [ ] Identify the travelmate login/captive hook for the installed version
|
||||
- [ ] Hook rewrites OpenWRT dnsmasq to upstream-only DNS on new uplink association (Pi-hole out of path)
|
||||
- [ ] Test: associate to a portal network, confirm the login page renders and auth completes
|
||||
|
||||
### Phase 2 — Swap-back (portal-dependent, optional)
|
||||
- [ ] Define auth-complete detection (probe a known domain through the upstream)
|
||||
- [ ] On detection, restore Pi-hole as LAN resolver
|
||||
- [ ] Validate swap-back end to end; fall back to manual restore if detection is unreliable
|
||||
|
||||
## Notes
|
||||
|
||||
- Manual stopgap that works right now: `sudo resolvectl dns <iface> <upstream-ip>` + `sudo resolvectl flush-caches`, load portal, auth, then `sudo resolvectl revert <iface>`. Auth survives the revert because the portal tracks session by MAC, not DNS.
|
||||
- Tailscale split-DNS is a *separate* concern surfaced same session: `herbylab.dev` failing to resolve while public domains resolve = MagicDNS not routing the private zone to the home resolver. Fix lives in Tailscale admin → DNS (split-DNS / restricted-nameserver entry mapping `herbylab.dev` → home resolver tailnet IP), not in the travel-router config. Track separately if it persists once portals are out of the picture.
|
||||
- Reaching home services remotely requires Tailscale up with an approved subnet route; split-DNS resolving a private LAN IP with no route still won't connect.
|
||||
Loading…
Reference in New Issue
Block a user