router: let allowWan VLANs out through the staging uplink
With stagingPort set, the box itself had internet over the staging DHCP
uplink but LAN/Wi-Fi clients had none: forward and masquerade were scoped
to ppp0 only. Worse, pppd's `defaultroute` refuses to install its route
while the staging DHCP default route (metric 1024) exists ("not replacing
existing default route"), so even a live PPPoE session was never used.
- firewall: forward-allow + masquerade allowWan VLANs -> stagingPort in a
separate `router-staging-nat` postrouting chain (networking.nat only
takes one external interface). Same allowWan set as nixos-nat.
- pppoe: `defaultroute-metric 0`, so pppd only checks for a metric-0
default route, installs ppp0 as the preferred exit and removes it on
hangup, leaving the staging route as the fallback.
This commit is contained in:
@@ -3,7 +3,8 @@
|
||||
# other VLANs -> DNS/DHCP on the router + WAN (if allowWan); no inter-VLAN
|
||||
# WAN (ppp0) -> nothing inbound beyond established/related
|
||||
# mesh -> admin SSH + metrics scrapes (same trust boundary as the fleet)
|
||||
# staging -> admin SSH only (pre-cutover uplink into the old LAN)
|
||||
# staging -> admin SSH only inbound (pre-cutover uplink into the old LAN);
|
||||
# allowWan VLANs are NATed out through it while ppp0 is down
|
||||
{ settings }:
|
||||
{ lib, ... }:
|
||||
let
|
||||
@@ -14,6 +15,13 @@ let
|
||||
lib.filterAttrs (_: vlan: vlan.allowWan) cfg.vlans
|
||||
);
|
||||
nonMgmtIfs = lib.filter (i: i != "vlan-mgmt") vlanIfs;
|
||||
|
||||
# allowWan VLANs may also leave through the staging uplink. Same set as
|
||||
# networking.nat.internalInterfaces below, so `allowWan` holds on both
|
||||
# exits. The kernel picks the exit: ppp0 (metric 0, see pppoe.nix) while
|
||||
# the session is up, the staging DHCP route (metric 1024) otherwise.
|
||||
stagingExit = cfg.stagingPort != null && wanVlanIfs != [ ];
|
||||
wanVlanSet = "{ ${lib.concatMapStringsSep ", " (i: ''"${i}"'') wanVlanIfs} }";
|
||||
in
|
||||
{
|
||||
networking.nftables.enable = true;
|
||||
@@ -50,6 +58,9 @@ in
|
||||
extraForwardRules = ''
|
||||
tcp flags syn tcp option maxseg size set rt mtu comment "MSS clamp for PPPoE mtu 1492"
|
||||
iifname "vlan-mgmt" accept comment "mgmt reaches all VLANs and the WAN"
|
||||
''
|
||||
+ lib.optionalString stagingExit ''
|
||||
iifname ${wanVlanSet} oifname "${cfg.stagingPort}" accept comment "allowWan VLANs out via the staging uplink"
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -62,4 +73,19 @@ in
|
||||
externalInterface = "ppp0";
|
||||
internalInterfaces = wanVlanIfs;
|
||||
};
|
||||
|
||||
# networking.nat only masquerades on its single externalInterface; the
|
||||
# staging uplink needs its own postrouting chain (nixos-nat's is
|
||||
# oifname-scoped to ppp0, so the two never both apply).
|
||||
networking.nftables.tables = lib.optionalAttrs stagingExit {
|
||||
router-staging-nat = {
|
||||
family = "ip";
|
||||
content = ''
|
||||
chain post {
|
||||
type nat hook postrouting priority srcnat;
|
||||
iifname ${wanVlanSet} oifname "${cfg.stagingPort}" masquerade comment "allowWan VLANs out via the staging uplink"
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user