diff --git a/persistent-memory.d/2026-08-23-anaheim-ipsec-tunnel-ceiling.md b/persistent-memory.d/2026-08-23-anaheim-ipsec-tunnel-ceiling.md index 6e8f7a9..f464775 100644 --- a/persistent-memory.d/2026-08-23-anaheim-ipsec-tunnel-ceiling.md +++ b/persistent-memory.d/2026-08-23-anaheim-ipsec-tunnel-ceiling.md @@ -588,10 +588,8 @@ request returns a fixed 403 whose body is literally: **Not a DNAT.** The full VIP table has 14 entries; only two land on `.42` — `Kokoro-In` (:8880 → 10.250.50.51) and `wg-to-ana-wg` (:31337 → 10.250.50.252). -Worth noting separately: **four VIPs are all-port static NAT** (no `portforward`), -so they map *every* port of their external IP — `Rustdesk` (.44 → 10.250.50.70), -`https-to-tacticalrmm` (.46 → .57), `web-to-webhost` (.45 → .52), -`web-to-sfcontainer` (.43 → 10.250.150.100). +~~Worth noting separately: four VIPs are all-port static NAT~~ — **that claim was +WRONG, see the correction below.** All fourteen VIPs are scoped. ### The methodology error that produced the wrong answer — worth not repeating @@ -614,3 +612,52 @@ bidirectional. `dst host` silently answers a different question.** the internal GUI at 10.250.0.1, where the name would not match anyway. Killing it (`config system acme` → unset interface) would close the last WAN listener at the cost of cert renewal. Operator's call; **not done**. + +--- + +## CLOSED OUT (2026-08-23): ACME disabled; and the "all-port VIP" alarm was FALSE + +### ACME disabled — the WAN IP now exposes nothing + +`config system acme / unset interface` (the account object is left in place; +with no interface bound there is no listener). Verified: + +- **External scan of 38.120.12.42 across 55 ports: no open TCP ports at all.** +- Internal GUI at 10.250.0.1 still answers **200**, SSH still works. +- `admin-server-cert` is still `ana-fw.pfi` — the existing cert is untouched and + serves the internal GUI until **2026-10-27**; it simply will not auto-renew. + +Reverse with `config system acme / set interface "wan1"`. + +### RETRACTION: the four VIPs are NOT all-port + +A previous section claimed `Rustdesk`, `https-to-tacticalrmm`, `web-to-webhost` +and `web-to-sfcontainer` were unrestricted all-port static NATs. **They are not.** +A FortiOS VIP can be scoped **two different ways** and the parser used only +checked one: + +1. `set portforward enable` + `set extport ` — a single mapped port, **or** +2. `set service ""` on the VIP object — constrains the VIP to that service. + +All four use form 2. The custom services are narrow: `Rustdesk` = TCP +21115–21119 + UDP 21116 (the standard RustDesk range), `ssh-mapped-2223` = TCP +2223 only. **Every one of the 14 VIPs is scoped; none is unrestricted.** + +**Lesson: absence of `portforward` does NOT mean all-port on a FortiOS VIP — +check `service` too.** Better still, do what settled it here: scan from outside +rather than reading config. + +### Ground-truth public exposure (external TCP scan, post-change) + +| IP | open | maps to | +|---|---|---| +| 38.120.12.41 | *nothing* | — | +| **38.120.12.42** | ***nothing*** | the FortiGate itself — fully closed | +| 38.120.12.43 | 80, 443 | sf-ana-container 10.250.150.100 (SureFire tenant) | +| 38.120.12.44 | 22, 80, 443, 8025, 21115–21119 | gitea (→222), traefik, mailrise, RustDesk | +| 38.120.12.45 | 80, 443, 2223 | pfi-ana-webhost 10.250.50.52 (2223→22) | +| 38.120.12.46 | 443 | pfi-tacticalrmm 10.250.50.57 | + +Configured-but-closed: 8443 (mattermost-calls), 8444 (webdav-nas), 8880 +(Kokoro-In) — VIPs exist, nothing listening behind them. Worth a tidy-up during +the OPNsense translation but not exposure.