Files
ha-parental-controls/.claude-context/sessions/2026-05-18-opnsense-alias-dashboard.md
T

4.4 KiB
Raw Blame History

Parental Controls Dashboard with OPNsense Alias Blocking

Date: 2026-05-18 Project: ha-parental-controls Status: resolved Tags: home-assistant, opnsense, firewall-alias, dhcp, websocket, rest_command, input_text, dashboard

Context

Jess wanted a Home Assistant panel to block and unblock internet access per child and per device, backed by the OPNsense firewall, with optional scheduled access windows. The first version (2026-05-10) worked in principle but hit a series of problems over the following week: WebSocket timeouts on load, broken HA auth handshake, config too large for a single input_text, OPNsense rejecting alias updates, and tablets needing credentials entered on every device.

Key Decisions

  • OPNsense firewall alias (parental_blocked) + one LAN block rule — HA only adds/removes IPs from the alias; no per-device firewall rules to manage.
  • Identify devices by MAC, resolve to current IP at block time — blocks re-apply automatically when a device reconnects with a new IP.
  • Standalone HTML panel (panel_iframe) instead of Lovelace cards — the UI (users, devices, toggles, schedules) is too interactive for core cards.
  • Device discovery/status from an OPNsense DHCP lease REST sensor rather than device_tracker entities alone — gives hostnames, addresses and expiry in one place.
  • Config persisted in HA, chunked across 12 input_text entities (12 × 255 = 3060 chars) — a single input_text with max 10000 is invalid (HA caps at 255), and HA storage means config is shared across devices, unlike localStorage.
  • REST API for initial state load, WebSocket for live updates — loading all states over WS timed out; WS timeout raised to 60s.
  • OPNsense alias_util calls use a JSON payload — the API rejects form-encoded bodies.
  • Auto-detect HA URL from window.location.origin — works over HTTP, HTTPS, LAN IP or domain without configuration.
  • Optional token in a CONFIG block in the HTML so the panel works on every device without per-device setup. Trade-off: this contradicts the project principle of no hardcoded credentials — the repo copy must stay blank (CONFIG_HA_TOKEN = ''), and the token is only filled in on the HA host's copy.

Technical Details

  • Files: packages/parental_controls.yaml (rest_commands, scripts, sensors, input_text chunks, optional schedule automation), www/parental_controls.html (panel), secrets_example.yaml.
  • Secrets used: opnsense_alias_add_url, opnsense_alias_del_url, opnsense_apply_url (/api/firewall/alias/reconfigure), opnsense_basic_auth (base64 of key:secret), opnsense_leases_url. Values <redacted>.
  • OPNsense API key needs Firewall: Alias read/write.
  • DHCP sensor: sensor.home_dhcp_leases_lan, data under attributes.Leases (capital L) with address / hostname / expires.
  • HA WS auth: send the auth message with raw ws.send() — the helper send() waits for a result, but HA replies to auth with auth_ok / auth_invalid.
  • lastSaveTime guard prevents the display blanking when the input_text state echo arrives right after a save.
  • Panel added via panel_iframe at /local/parental_controls.html, require_admin: true.

Code Changes

  • packages/parental_controls.yaml — rest_commands (JSON payload), DHCP lease REST sensor, 12 chunked input_text entities, scripts, optional schedule automation.
  • www/parental_controls.html — REST initial load + WS updates, WS auth fix, DHCP-based discovery and HA/DHCP status indicators, chunked parseCfg/saveCfg, save-error handling, lastSaveTime guard, URL auto-detect, optional CONFIG token.
  • secrets_example.yaml, README.md — setup docs.

Open Questions / Next Steps

  • Schedules only run while the panel is open in a browser. For reliable enforcement, move schedule logic into an HA automation (the package has an optional one) so it runs server-side.
  • Consider an HA-side way to supply the token (e.g. trusted network auth or a proxy) so the HTML never needs a hardcoded token.
  • Overlaps with opnsense-device-control, ha-device-assignment and the newer homenet-guardrails — decide which is canonical going forward.

Artifacts

  • bd49964 — Auto-detect URL from page origin
  • 4142d1c — Fix empty display after save + OPNsense JSON payload fix
  • 8a5fe10 / cf8d7ee — Chunked storage (12×255)
  • 4ecdda5 — Redesign on OPNsense DHCP lease sensor
  • 5593d14 — WS auth via ws.send()
  • 76b67d3 — REST initial load, 60s WS timeout