diff --git a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml index c0f407e11a9..023f0f57a9b 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml @@ -1548,6 +1548,12 @@ Superuser created successfully. Foo-over-UDP encapsulations. + + + networking.sits now supports Foo-over-UDP + encapsulation. + + diff --git a/nixos/doc/manual/release-notes/rl-2111.section.md b/nixos/doc/manual/release-notes/rl-2111.section.md index 6dadcde3ccc..658f3b59da6 100644 --- a/nixos/doc/manual/release-notes/rl-2111.section.md +++ b/nixos/doc/manual/release-notes/rl-2111.section.md @@ -447,3 +447,5 @@ In addition to numerous new and upgraded packages, this release has the followin - The `systemd.network` module has gained support for the FooOverUDP link type. - The `networking` module has a new `networking.fooOverUDP` option to configure Foo-over-UDP encapsulations. + +- `networking.sits` now supports Foo-over-UDP encapsulation. diff --git a/nixos/modules/tasks/network-interfaces-scripted.nix b/nixos/modules/tasks/network-interfaces-scripted.nix index 055580e3ea2..e8e2de090b3 100644 --- a/nixos/modules/tasks/network-interfaces-scripted.nix +++ b/nixos/modules/tasks/network-interfaces-scripted.nix @@ -519,7 +519,12 @@ let ${optionalString (v.remote != null) "remote \"${v.remote}\""} \ ${optionalString (v.local != null) "local \"${v.local}\""} \ ${optionalString (v.ttl != null) "ttl ${toString v.ttl}"} \ - ${optionalString (v.dev != null) "dev \"${v.dev}\""} + ${optionalString (v.dev != null) "dev \"${v.dev}\""} \ + ${optionalString (v.encapsulation != null) + "encap ${v.encapsulation.type} encap-dport ${toString v.encapsulation.port} ${ + optionalString (v.encapsulation.sourcePort != null) + "encap-sport ${toString v.encapsulation.sourcePort}" + }"} ip link set "${n}" up ''; postStop = '' diff --git a/nixos/modules/tasks/network-interfaces-systemd.nix b/nixos/modules/tasks/network-interfaces-systemd.nix index 516764b87db..ccfd7fd4132 100644 --- a/nixos/modules/tasks/network-interfaces-systemd.nix +++ b/nixos/modules/tasks/network-interfaces-systemd.nix @@ -227,7 +227,17 @@ in Local = sit.local; }) // (optionalAttrs (sit.ttl != null) { TTL = sit.ttl; - }); + }) // (optionalAttrs (sit.encapsulation != null) ( + { + FooOverUDP = true; + Encapsulation = + if sit.encapsulation.type == "fou" + then "FooOverUDP" + else "GenericUDPEncapsulation"; + FOUDestinationPort = sit.encapsulation.port; + } // (optionalAttrs (sit.encapsulation.sourcePort != null) { + FOUSourcePort = sit.encapsulation.sourcePort; + }))); }; networks = mkIf (sit.dev != null) { "40-${sit.dev}" = (mkMerge [ (genericNetwork (mkOverride 999)) { diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix index a3b41326168..4e20ec11846 100644 --- a/nixos/modules/tasks/network-interfaces.nix +++ b/nixos/modules/tasks/network-interfaces.nix @@ -10,7 +10,8 @@ let hasVirtuals = any (i: i.virtual) interfaces; hasSits = cfg.sits != { }; hasBonds = cfg.bonds != { }; - hasFous = cfg.fooOverUDP != { }; + hasFous = cfg.fooOverUDP != { } + || filterAttrs (_: s: s.encapsulation != null) cfg.sits != { }; slaves = concatMap (i: i.interfaces) (attrValues cfg.bonds) ++ concatMap (i: i.interfaces) (attrValues cfg.bridges) @@ -948,6 +949,44 @@ in ''; }; + encapsulation = with types; mkOption { + type = nullOr (submodule { + options = { + type = mkOption { + type = enum [ "fou" "gue" ]; + description = '' + Selects encapsulation type. See + ip-link + 8 for details. + ''; + }; + + port = mkOption { + type = port; + example = 9001; + description = '' + Destination port for encapsulated packets. + ''; + }; + + sourcePort = mkOption { + type = nullOr types.port; + default = null; + example = 9002; + description = '' + Source port for encapsulated packets. Will be chosen automatically by + the kernel if unset. + ''; + }; + }; + }); + default = null; + example = { type = "fou"; port = 9001; }; + description = '' + Configures encapsulation in UDP packets. + ''; + }; + }; }); diff --git a/nixos/tests/networking.nix b/nixos/tests/networking.nix index fdcf67f1126..647c8942b37 100644 --- a/nixos/tests/networking.nix +++ b/nixos/tests/networking.nix @@ -431,7 +431,6 @@ let virtualisation.vlans = [ 1 ]; networking = { useNetworkd = networkd; - firewall.enable = false; useDHCP = false; sits.sit = { inherit remote; @@ -446,8 +445,30 @@ let }; in { name = "Sit"; - nodes.client1 = node { address4 = "192.168.1.1"; remote = "192.168.1.2"; address6 = "fc00::1"; }; - nodes.client2 = node { address4 = "192.168.1.2"; remote = "192.168.1.1"; address6 = "fc00::2"; }; + # note on firewalling: the two nodes are explicitly asymmetric. + # client1 sends SIT packets in UDP, but accepts only proto-41 incoming. + # client2 does the reverse, sending in proto-41 and accepting only UDP incoming. + # that way we'll notice when either SIT itself or FOU breaks. + nodes.client1 = args@{ pkgs, ... }: + mkMerge [ + (node { address4 = "192.168.1.1"; remote = "192.168.1.2"; address6 = "fc00::1"; } args) + { + networking = { + firewall.extraCommands = "iptables -A INPUT -p 41 -j ACCEPT"; + sits.sit.encapsulation = { type = "fou"; port = 9001; }; + }; + } + ]; + nodes.client2 = args@{ pkgs, ... }: + mkMerge [ + (node { address4 = "192.168.1.2"; remote = "192.168.1.1"; address6 = "fc00::2"; } args) + { + networking = { + firewall.allowedUDPPorts = [ 9001 ]; + fooOverUDP.fou1 = { port = 9001; protocol = 41; }; + }; + } + ]; testScript = { ... }: '' start_all()