+167
−1
cmd/felis/tui_edge_apply_test.go
0 → 100644
+84
−0
Loading
After the Cloudflare tunnel connector is installed and the origin has rolled out, applyCloudflareEdge now fences the panel NodePort so the origin is reachable only over loopback -- the hop the host-side connector uses -- and never from a public interface. This closes the Access-bypass hole where a direct https://<node-ip>:<nodeport>/ with the right Host header reached the origin behind Cloudflare Access. The fence is an nftables table hooked at prerouting priority -300 (raw), before kube-proxy's NodePort DNAT (dstnat, -100), so it catches the packet on its original destination port; a filter/INPUT rule would miss the DNAT'd, then FORWARDed NodePort packet. Loopback is accepted first, so the connector origin hop is untouched; the inet family fences a public IPv6 NodePort too. It is gated on the connector actually serving (verifyConnectorServing polls `cloudflared tunnel info`): fencing a dead tunnel would sever the only web path to a still-up origin. If serving cannot be confirmed the port is left open (its pre-tunnel state) and the failure is surfaced loudly. unfenceOriginNodePort is the on-host break-glass reversal. The nft/cloudflared calls are INTEGRATION-ONLY; the ruleset shape and the conn-count gate are pure and unit-tested. KNOWN-LIMITATION: targets nftables; firewalld-native coordination is not yet handled (a firewalld reload can flush the standalone table).