pfsense: SNI-routed internal 443 — mail.viktorbarzin.me serves webmail everywhere

Completes the internal port table of the mail front door (10.0.20.1):
443 was squatted by the pfSense webGUI (self-signed cert expired 2022),
so internal webmail and the kuma [External] mail probe hit the firewall
login instead of Roundcube — the last leg of the mail split-brain name.

Design (Viktor): route by what the client asked for. New HAProxy
frontend internal_https_443 (binds 10.0.20.1+10.0.10.1 :443, mode tcp):
SNI present -> Traefik .203 with send-proxy-v2 (trusted, IPv6-bridge
pattern, no health check per the PROXY-probe gotcha); SNI of
pfsense.viktorbarzin.{lan,me} or NO SNI (bare-IP admin access) -> webGUI,
which moved to :8443 (invisible to habits — https://10.0.20.1 still
lands on the login page; :8443 doubles as direct fallback). The
reverse-proxy pfsense ingress now targets :8443 directly.

Declared idempotently in pfsense-haproxy-bootstrap.php; config.xml
backed up on-box (config.xml.bak-2026-06-10-pre-sni443). Verified:
bare IP -> GUI login; pfsense.viktorbarzin.lan -> GUI;
pfsense.viktorbarzin.me -> 302 via ingress; mail.viktorbarzin.me ->
Roundcube with STRICT cert validation; :993 IMAPS untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Viktor Barzin 2026-06-10 18:41:07 +00:00
parent 176a65d3d2
commit eae35c511a
4 changed files with 113 additions and 4 deletions

View file

@ -55,7 +55,7 @@ External mail (WAN) path — PROXY v2
│ pfSense WAN:{25,465,587,993} │
│ │ NAT rdr → 10.0.20.1:{same} │
│ ▼ │
│ pfSense HAProxy (mode tcp, 4 frontends, 4 backend pools) │
│ pfSense HAProxy (mode tcp, 5 frontends, 6 backend pools) │
│ │ data: send-proxy-v2 → :{30125..30128} (PROXY-aware pod) │
│ │ health: TCP-check → :{30145..30147} (no-PROXY pod) │
│ │ inter 5000 │
@ -113,6 +113,28 @@ kubectl logs -c docker-mailserver deployment/mailserver -n mailserver \
# Expect external source IPs (e.g., Brevo 77.32.148.x), NOT 10.0.20.x
```
## SNI-routed internal :443 frontend (2026-06-10)
`internal_https_443` binds `10.0.20.1:443` + `10.0.10.1:443` and completes
the internal port table of the mail front door so `mail.viktorbarzin.me`
(internal A record → 10.0.20.1) serves webmail too. Routing (Viktor's
design — route by what the client asked for):
| Client connects with | Routed to |
|---|---|
| SNI = `pfsense.viktorbarzin.{lan,me}` | webgui backend `127.0.0.1:8443` |
| any other SNI (hostnames, e.g. `mail.…`) | Traefik `10.0.20.203:443`, send-proxy-v2 |
| no SNI (bare IP — `https://10.0.20.1`) | webgui backend `127.0.0.1:8443` |
The **pfSense webGUI was moved to `:8443`** (config.xml
`system.webgui.port`, 2026-06-10) to free the 443 socket; admin access by
IP keeps working through the no-SNI route, and `:8443` remains a direct
fallback if HAProxy is down. The `pfsense.viktorbarzin.me` Traefik ingress
(stacks/reverse-proxy) targets `:8443` directly. Traefik leg mirrors the
IPv6 bridge: send-proxy-v2 (Traefik trusts 10.0.20.1), **no health check**
(PROXY-expecting receivers reject bare probes — gotcha above). All of this
is declared in `pfsense-haproxy-bootstrap.php` — re-run to reset.
## Bootstrap / restore from scratch
pfSense HAProxy config lives in `/cf/conf/config.xml` under