diff --git a/headscale/config.yaml b/headscale/config.yaml index dd98cd6..31d0b76 100644 --- a/headscale/config.yaml +++ b/headscale/config.yaml @@ -57,6 +57,14 @@ dns: - 1.1.1.1 - 1.0.0.1 search_domains: [] + # Served only to tailnet clients via MagicDNS: overrides falcon.pivoine.art + # app hostnames to resolve to the VPS's tailscale IP instead of its public + # one, so VPN-connected clients route straight over the tunnel and satisfy + # Traefik's falcon-vpn-only IP allowlist. + extra_records: + - name: "triggershell.falcon.pivoine.art" + type: "A" + value: "100.64.0.3" # TLS is terminated by Traefik; headscale itself serves plain HTTP internally. tls_letsencrypt_hostname: "" diff --git a/traefik/dynamic/falcon.yaml b/traefik/dynamic/falcon.yaml index fb8763a..e8d77ee 100644 --- a/traefik/dynamic/falcon.yaml +++ b/traefik/dynamic/falcon.yaml @@ -11,6 +11,15 @@ http: triggershell-redirect-web-secure: redirectScheme: scheme: https + # Only let traffic through whose source IP is inside the Tailscale/Headscale + # mesh (100.64.0.0/10, fd7a:115c:a1e0::/48). Public DNS still resolves these + # hostnames, but anyone reaching them over the open internet gets a 403 — + # this range is only reachable by actually being a peer on the tailnet. + falcon-vpn-only: + ipAllowList: + sourceRange: + - "100.64.0.0/10" + - "fd7a:115c:a1e0::/48" routers: triggershell-web: @@ -18,6 +27,7 @@ http: entrypoints: - web middlewares: + - falcon-vpn-only - triggershell-redirect-web-secure service: triggershell @@ -28,6 +38,7 @@ http: tls: certResolver: resolver middlewares: + - falcon-vpn-only - security-headers@file service: triggershell