router: expose forwarded ports on eno1; AdGuard rewrite for LAN hostname

- Input chain now accepts WAN traffic for every port in ports.toml so
  external access (SSH, HTTP, HTTPS, game ports) works through the eero's
  upstream port forwards during phase 1, and via our own DNAT in phase 2.
- Add AdGuard DNS rewrite nordhammer.it → 192.168.4.25 so LAN clients
  hit the mediaserver directly instead of relying on eero hairpin NAT.
  Target changes to 10.0.0.1 at phase 2 cutover.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
ediblerope 2026-04-24 10:22:56 +01:00
parent 661ad14948
commit 5426e3847b
2 changed files with 16 additions and 0 deletions

View file

@ -35,6 +35,12 @@
{ enabled = true; id = 3; name = "OISD Big";
url = "https://big.oisd.nl/"; }
];
# Resolve our own hostnames to the mediaserver's LAN IP so LAN
# clients bypass eero hairpin NAT. Update to 10.0.0.1 in phase 2.
filtering.rewrites = [
{ domain = "nordhammer.it"; answer = "192.168.4.25"; }
{ domain = "*.nordhammer.it"; answer = "192.168.4.25"; }
];
};
};

View file

@ -47,6 +47,14 @@ let
(f: ''${f.proto} dport ${f.port} dnat to ${f.dest} comment "${f.name}"'')
forwards;
# Input-chain accept rules so WAN traffic to forwarded ports reaches the
# mediaserver. Works in both phases:
# phase 1: eero DNATs to 192.168.4.25, arrives on eno1 — matched here.
# phase 2: our DNAT rewrites dst to 10.0.0.1 (local), arrives on eno1 — matched here.
wanPortInputRules = lib.concatMapStringsSep "\n "
(f: ''iifname "eno1" ${f.proto} dport ${f.port} accept comment "${f.name}"'')
forwards;
in
{
config = lib.mkIf (config.networking.hostName == "FredOS-Mediaserver") {
@ -109,6 +117,8 @@ in
# Phase 1: also trust the existing eero subnet on eno1 so SSH
# and AdGuard DNS keep working during the transition.
${legacyTrustRules}
# Accept WAN traffic for ports we publicly expose (ports.toml).
${wanPortInputRules}
# ICMP from anywhere (ping, path-MTU)
icmp type echo-request accept
icmpv6 type echo-request accept