diff options
author | Michele Guerini Rocco <rnhmjoj@users.noreply.github.com> | 2022-01-31 10:06:57 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-31 10:06:57 +0100 |
commit | 09e29560121f00cc238a4ea4960e3a9d74e68afe (patch) | |
tree | 0cc57a81fb7b8dd373a143de57a285e4541b4d7b /nixos | |
parent | b48539da9a48b66f6bbb0c668b81e0b55f602416 (diff) | |
parent | 79b4b7eaa1a00424cbf63305516e92c8dd055c94 (diff) | |
download | nixpkgs-09e29560121f00cc238a4ea4960e3a9d74e68afe.tar nixpkgs-09e29560121f00cc238a4ea4960e3a9d74e68afe.tar.gz nixpkgs-09e29560121f00cc238a4ea4960e3a9d74e68afe.tar.bz2 nixpkgs-09e29560121f00cc238a4ea4960e3a9d74e68afe.tar.lz nixpkgs-09e29560121f00cc238a4ea4960e3a9d74e68afe.tar.xz nixpkgs-09e29560121f00cc238a4ea4960e3a9d74e68afe.tar.zst nixpkgs-09e29560121f00cc238a4ea4960e3a9d74e68afe.zip |
Merge pull request #155895 from rnhmjoj/pr-dhcpd-hard
nixos/dhcpd: switch to DynamicUser [v2]
Diffstat (limited to 'nixos')
4 files changed, 72 insertions, 64 deletions
diff --git a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml index 41a84ed0221..1811c5ec561 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml @@ -237,6 +237,23 @@ </listitem> <listitem> <para> + The DHCP server (<literal>services.dhcpd4</literal>, + <literal>services.dhcpd6</literal>) has been hardened. The + service is now using the systemd’s + <literal>DynamicUser</literal> mechanism to run as an + unprivileged dynamically-allocated user with limited + capabilities. The dhcpd state files are now always stored in + <literal>/var/lib/dhcpd{4,6}</literal> and the + <literal>services.dhcpd4.stateDir</literal> and + <literal>service.dhcpd6.stateDir</literal> options have been + removed. If you were depending on root privileges or + set{uid,gid,cap} binaries in dhcpd shell hooks, you may give + dhcpd more capabilities with e.g. + <literal>systemd.services.dhcpd6.serviceConfig.AmbientCapabilities</literal>. + </para> + </listitem> + <listitem> + <para> The <literal>mailpile</literal> email webclient (<literal>services.mailpile</literal>) has been removed due to its reliance on python2. diff --git a/nixos/doc/manual/release-notes/rl-2205.section.md b/nixos/doc/manual/release-notes/rl-2205.section.md index 50099671f62..f22204801b8 100644 --- a/nixos/doc/manual/release-notes/rl-2205.section.md +++ b/nixos/doc/manual/release-notes/rl-2205.section.md @@ -81,6 +81,11 @@ In addition to numerous new and upgraded packages, this release has the followin - `services.kubernetes.addons.dashboard` was removed due to it being an outdated version. +- The DHCP server (`services.dhcpd4`, `services.dhcpd6`) has been hardened. + The service is now using the systemd's `DynamicUser` mechanism to run as an unprivileged dynamically-allocated user with limited capabilities. + The dhcpd state files are now always stored in `/var/lib/dhcpd{4,6}` and the `services.dhcpd4.stateDir` and `service.dhcpd6.stateDir` options have been removed. + If you were depending on root privileges or set{uid,gid,cap} binaries in dhcpd shell hooks, you may give dhcpd more capabilities with e.g. `systemd.services.dhcpd6.serviceConfig.AmbientCapabilities`. + - The `mailpile` email webclient (`services.mailpile`) has been removed due to its reliance on python2. - The MoinMoin wiki engine (`services.moinmoin`) has been removed, because Python 2 is being retired from nixpkgs. diff --git a/nixos/modules/services/networking/dhcpd.nix b/nixos/modules/services/networking/dhcpd.nix index 54e4f900285..3c4c0069dfd 100644 --- a/nixos/modules/services/networking/dhcpd.nix +++ b/nixos/modules/services/networking/dhcpd.nix @@ -28,38 +28,45 @@ let } ''; - dhcpdService = postfix: cfg: optionalAttrs cfg.enable { - "dhcpd${postfix}" = { - description = "DHCPv${postfix} server"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - - preStart = '' - mkdir -m 755 -p ${cfg.stateDir} - chown dhcpd:nogroup ${cfg.stateDir} - touch ${cfg.stateDir}/dhcpd.leases - ''; - - serviceConfig = - let - configFile = if cfg.configFile != null then cfg.configFile else writeConfig cfg; - args = [ "@${pkgs.dhcp}/sbin/dhcpd" "dhcpd${postfix}" "-${postfix}" - "-pf" "/run/dhcpd${postfix}/dhcpd.pid" - "-cf" "${configFile}" - "-lf" "${cfg.stateDir}/dhcpd.leases" - "-user" "dhcpd" "-group" "nogroup" - ] ++ cfg.extraFlags - ++ cfg.interfaces; - - in { - ExecStart = concatMapStringsSep " " escapeShellArg args; - Type = "forking"; - Restart = "always"; - RuntimeDirectory = [ "dhcpd${postfix}" ]; - PIDFile = "/run/dhcpd${postfix}/dhcpd.pid"; + dhcpdService = postfix: cfg: + let + configFile = + if cfg.configFile != null + then cfg.configFile + else writeConfig cfg; + leaseFile = "/var/lib/dhcpd${postfix}/dhcpd.leases"; + args = [ + "@${pkgs.dhcp}/sbin/dhcpd" "dhcpd${postfix}" "-${postfix}" + "-pf" "/run/dhcpd${postfix}/dhcpd.pid" + "-cf" configFile + "-lf" leaseFile + ] ++ cfg.extraFlags + ++ cfg.interfaces; + in + optionalAttrs cfg.enable { + "dhcpd${postfix}" = { + description = "DHCPv${postfix} server"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + preStart = "touch ${leaseFile}"; + serviceConfig = { + ExecStart = concatMapStringsSep " " escapeShellArg args; + Type = "forking"; + Restart = "always"; + DynamicUser = true; + User = "dhcpd"; + Group = "dhcpd"; + AmbientCapabilities = [ + "CAP_NET_RAW" # to send ICMP messages + "CAP_NET_BIND_SERVICE" # to bind on DHCP port (67) + ]; + StateDirectory = "dhcpd${postfix}"; + RuntimeDirectory = "dhcpd${postfix}"; + PIDFile = "/run/dhcpd${postfix}/dhcpd.pid"; + }; }; - }; - }; + }; machineOpts = { ... }: { @@ -102,15 +109,6 @@ let ''; }; - stateDir = mkOption { - type = types.path; - # We use /var/lib/dhcp for DHCPv4 to save backwards compatibility. - default = "/var/lib/dhcp${if postfix == "4" then "" else postfix}"; - description = '' - State directory for the DHCP server. - ''; - }; - extraConfig = mkOption { type = types.lines; default = ""; @@ -194,7 +192,13 @@ in imports = [ (mkRenamedOptionModule [ "services" "dhcpd" ] [ "services" "dhcpd4" ]) - ]; + ] ++ flip map [ "4" "6" ] (postfix: + mkRemovedOptionModule [ "services" "dhcpd${postfix}" "stateDir" ] '' + The DHCP server state directory is now managed with the systemd's DynamicUser mechanism. + This means the directory is named after the service (dhcpd${postfix}), created under + /var/lib/private/ and symlinked to /var/lib/. + '' + ); ###### interface @@ -210,15 +214,6 @@ in config = mkIf (cfg4.enable || cfg6.enable) { - users = { - users.dhcpd = { - isSystemUser = true; - group = "dhcpd"; - description = "DHCP daemon user"; - }; - groups.dhcpd = {}; - }; - systemd.services = dhcpdService "4" cfg4 // dhcpdService "6" cfg6; }; diff --git a/nixos/tests/systemd-networkd-ipv6-prefix-delegation.nix b/nixos/tests/systemd-networkd-ipv6-prefix-delegation.nix index 68836c73072..37a89fc21e4 100644 --- a/nixos/tests/systemd-networkd-ipv6-prefix-delegation.nix +++ b/nixos/tests/systemd-networkd-ipv6-prefix-delegation.nix @@ -36,19 +36,10 @@ import ./make-test-python.nix ({pkgs, ...}: { }; # Since we want to program the routes that we delegate to the "customer" - # into our routing table we must have a way to gain the required privs. - # This security wrapper will do in our test setup. - # - # DO NOT COPY THIS TO PRODUCTION AS IS. Think about it at least twice. - # Everyone on the "isp" machine will be able to add routes to the kernel. - security.wrappers.add-dhcpd-lease = { - owner = "root"; - group = "root"; - source = pkgs.writeShellScript "add-dhcpd-lease" '' - exec ${pkgs.iproute2}/bin/ip -6 route replace "$1" via "$2" - ''; - capabilities = "cap_net_admin+ep"; - }; + # into our routing table we must give dhcpd the required privs. + systemd.services.dhcpd6.serviceConfig.AmbientCapabilities = + [ "CAP_NET_ADMIN" ]; + services = { # Configure the DHCPv6 server # @@ -80,7 +71,7 @@ import ./make-test-python.nix ({pkgs, ...}: { set Prefix = pick-first-value(binary-to-ascii(16, 16, ":", suffix(option dhcp6.ia-pd, 16)), "n/a"); set PrefixLength = pick-first-value(binary-to-ascii(10, 8, ":", substring(suffix(option dhcp6.ia-pd, 17), 0, 1)), "n/a"); log(concat(IP, " ", Prefix, " ", PrefixLength)); - execute("/run/wrappers/bin/add-dhcpd-lease", concat(Prefix,"/",PrefixLength), IP); + execute("${pkgs.iproute2}/bin/ip", "-6", "route", "replace", concat(Prefix,"/",PrefixLength), "via", IP); } ''; }; |