From 17256403d085dcc12e7a42d99688d38f717b31d4 Mon Sep 17 00:00:00 2001 From: Lin Jian Date: Wed, 14 Jan 2026 14:04:57 +0800 Subject: [PATCH 1/2] nixos/network-interfaces: allow setting virtualOwner to null null will not set owner, allowing any user to access the virtual device. Previously, this behavior can be achieved by using systemd.network.netdevs.* options direcly and leaving systemd.network.netdevs..tapConfig.User unset. With this patch, this behavior can be achieved using the generic networking.interfaces.* options by setting networking.interfaces..virtualOwner to null. If needed, we can change the default value from "root" to null in the future to be consistent with systemd-networkd's default behavior. --- nixos/modules/tasks/network-interfaces-scripted.nix | 4 +++- nixos/modules/tasks/network-interfaces.nix | 3 ++- nixos/tests/networking/networkd-and-scripted.nix | 8 +++++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/nixos/modules/tasks/network-interfaces-scripted.nix b/nixos/modules/tasks/network-interfaces-scripted.nix index 9e6529e487b4..e4408b6771d2 100644 --- a/nixos/modules/tasks/network-interfaces-scripted.nix +++ b/nixos/modules/tasks/network-interfaces-scripted.nix @@ -322,7 +322,9 @@ let RemainAfterExit = true; }; script = '' - ip tuntap add dev "${i.name}" mode "${i.virtualType}" user "${i.virtualOwner}" + ip tuntap add dev "${i.name}" mode "${i.virtualType}" ${ + lib.optionalString (i.virtualOwner != null) ''user "${i.virtualOwner}"'' + } ''; postStop = '' ip link del dev ${i.name} || true diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix index 2a6d00296303..92c151142215 100644 --- a/nixos/modules/tasks/network-interfaces.nix +++ b/nixos/modules/tasks/network-interfaces.nix @@ -348,9 +348,10 @@ let virtualOwner = mkOption { default = "root"; - type = types.str; + type = types.nullOr types.str; description = '' In case of a virtual device, the user who owns it. + `null` will not set owner, allowing access to any user. ''; }; diff --git a/nixos/tests/networking/networkd-and-scripted.nix b/nixos/tests/networking/networkd-and-scripted.nix index b75f82218a69..c9b9d75cdcfd 100644 --- a/nixos/tests/networking/networkd-and-scripted.nix +++ b/nixos/tests/networking/networkd-and-scripted.nix @@ -1053,6 +1053,7 @@ let } ]; virtual = true; + virtualOwner = null; mtu = 1342; macAddress = "02:de:ad:be:ef:01"; }; @@ -1070,13 +1071,14 @@ let } ]; virtual = true; + virtualOwner = "root"; mtu = 1343; }; }; testScript = '' targetList = """ - tap0: tap persist user 0 + tap0: tap persist tun0: tun persist user 0 """.strip() @@ -1101,6 +1103,10 @@ let machine.wait_until_succeeds("ip link show dev tap0 | grep 'mtu 1342'") machine.wait_until_succeeds("ip link show dev tun0 | grep 'mtu 1343'") assert "02:de:ad:be:ef:01" in machine.succeed("ip link show dev tap0") + with subtest("Test virtualOwner are configured"): + for interface, expected_owner in [("tap0", "-1"), ("tun0", "0")]: + actual_owner = machine.succeed(f"cat /sys/class/net/{interface}/owner").strip() + assert expected_owner == actual_owner, f"{interface} owner: expect {expected_owner}, got {actual_owner}" '' # network-addresses-* only exist in scripted networking + lib.optionalString (!networkd) '' with subtest("Test interfaces' addresses clean up"): From 5724c3197a99bc1df434ef5b11eb8c4f1adc6d68 Mon Sep 17 00:00:00 2001 From: Lin Jian Date: Wed, 14 Jan 2026 14:17:05 +0800 Subject: [PATCH 2/2] nixos/tayga: always set virtualOwner to null Previously, due to the limitation of networking.interfaces.*.virtualOwner, it is only set to null when using systemd-networkd backend. With this patch, virtualOwner is always set to null. --- nixos/modules/services/networking/tayga.nix | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/nixos/modules/services/networking/tayga.nix b/nixos/modules/services/networking/tayga.nix index f7221bdaf8c7..b6ed216d1992 100644 --- a/nixos/modules/services/networking/tayga.nix +++ b/nixos/modules/services/networking/tayga.nix @@ -167,7 +167,7 @@ in networking.interfaces."${cfg.tunDevice}" = { virtual = true; virtualType = "tun"; - virtualOwner = mkIf config.networking.useNetworkd ""; + virtualOwner = null; ipv4 = { addresses = [ { @@ -205,9 +205,7 @@ in ExecReload = "${pkgs.coreutils}/bin/kill -SIGHUP $MAINPID"; Restart = "always"; - # Hardening Score: - # - nixos-scripts: 2.1 - # - systemd-networkd: 1.6 + # Hardening Score: 1.5 ProtectHome = true; SystemCallFilter = [ "@network-io" @@ -216,9 +214,6 @@ in "~@resources" ]; ProtectKernelLogs = true; - AmbientCapabilities = [ - "CAP_NET_ADMIN" - ]; CapabilityBoundingSet = ""; RestrictAddressFamilies = [ "AF_INET" @@ -226,7 +221,7 @@ in "AF_NETLINK" ]; StateDirectory = "tayga"; - DynamicUser = mkIf config.networking.useNetworkd true; + DynamicUser = true; MemoryDenyWriteExecute = true; RestrictRealtime = true; RestrictSUIDSGID = true;