nixos/dhcpcd: fix hostname via DHCP (#385348)
This commit is contained in:
@@ -69,7 +69,7 @@ let
|
||||
hostname
|
||||
|
||||
# A list of options to request from the DHCP server.
|
||||
option domain_name_servers, domain_name, domain_search, host_name
|
||||
option domain_name_servers, domain_name, domain_search
|
||||
option classless_static_routes, ntp_servers, interface_mtu
|
||||
|
||||
# A ServerID is required by RFC2131.
|
||||
@@ -112,6 +112,7 @@ let
|
||||
${lib.optionalString (config.networking.enableIPv6 && cfg.IPv6rs == false) ''
|
||||
noipv6rs
|
||||
''}
|
||||
${lib.optionalString cfg.setHostname "option host_name"}
|
||||
|
||||
${cfg.extraConfig}
|
||||
'';
|
||||
@@ -137,7 +138,7 @@ in
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whenever to leave interfaces configured on dhcpcd daemon
|
||||
Whether to leave interfaces configured on dhcpcd daemon
|
||||
shutdown. Set to true if you have your root or store mounted
|
||||
over the network or this machine accepts SSH connections
|
||||
through DHCP interfaces and clients should be notified when
|
||||
@@ -145,6 +146,22 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
networking.dhcpcd.setHostname = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to set the machine hostname based on the information
|
||||
received from the DHCP server.
|
||||
|
||||
::: {.note}
|
||||
The hostname will be changed only if the current one is
|
||||
the empty string, `localhost` or `nixos`.
|
||||
|
||||
Polkit ([](#opt-security.polkit.enable)) is also required.
|
||||
:::
|
||||
'';
|
||||
};
|
||||
|
||||
networking.dhcpcd.denyInterfaces = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ ];
|
||||
@@ -185,6 +202,15 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
networking.dhcpcd.allowSetuid = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to relax the security sandbox to allow running setuid
|
||||
binaries (e.g. `sudo`) in the dhcpcd hooks.
|
||||
'';
|
||||
};
|
||||
|
||||
networking.dhcpcd.runHook = lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
default = "";
|
||||
@@ -196,7 +222,7 @@ in
|
||||
::: {.note}
|
||||
To use sudo or similar tools in your script you may have to set:
|
||||
|
||||
systemd.services.dhcpcd.serviceConfig.NoNewPrivileges = false;
|
||||
networking.dhcpcd.allowSetuid = true;
|
||||
|
||||
In addition, as most of the filesystem is inaccessible to dhcpcd
|
||||
by default, you may want to define some exceptions, e.g.
|
||||
@@ -263,11 +289,16 @@ in
|
||||
# dhcpcd. So do a "systemctl restart" instead.
|
||||
stopIfChanged = false;
|
||||
|
||||
path = [
|
||||
dhcpcd
|
||||
pkgs.nettools
|
||||
config.networking.resolvconf.package
|
||||
];
|
||||
path =
|
||||
[
|
||||
dhcpcd
|
||||
config.networking.resolvconf.package
|
||||
]
|
||||
++ lib.optional cfg.setHostname (
|
||||
pkgs.writeShellScriptBin "hostname" ''
|
||||
${lib.getExe' pkgs.systemd "hostnamectl"} set-hostname --transient $1
|
||||
''
|
||||
);
|
||||
|
||||
unitConfig.ConditionCapability = "CAP_NET_ADMIN";
|
||||
|
||||
@@ -299,7 +330,7 @@ in
|
||||
"CAP_NET_RAW"
|
||||
"CAP_NET_BIND_SERVICE"
|
||||
];
|
||||
CapabilityBoundingSet = [
|
||||
CapabilityBoundingSet = lib.optionals (!cfg.allowSetuid) [
|
||||
"CAP_NET_ADMIN"
|
||||
"CAP_NET_RAW"
|
||||
"CAP_NET_BIND_SERVICE"
|
||||
@@ -313,7 +344,7 @@ in
|
||||
DeviceAllow = "";
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = lib.mkDefault true; # may be disabled for sudo in runHook
|
||||
NoNewPrivileges = lib.mkDefault (!cfg.allowSetuid); # may be disabled for sudo in runHook
|
||||
PrivateDevices = true;
|
||||
PrivateMounts = true;
|
||||
PrivateTmp = true;
|
||||
@@ -338,15 +369,18 @@ in
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"~@aio"
|
||||
"~@keyring"
|
||||
"~@memlock"
|
||||
"~@mount"
|
||||
"~@privileged"
|
||||
"~@resources"
|
||||
];
|
||||
SystemCallFilter =
|
||||
[
|
||||
"@system-service"
|
||||
"~@aio"
|
||||
"~@keyring"
|
||||
"~@memlock"
|
||||
"~@mount"
|
||||
]
|
||||
++ lib.optionals (!cfg.allowSetuid) [
|
||||
"~@privileged"
|
||||
"~@resources"
|
||||
];
|
||||
SystemCallArchitectures = "native";
|
||||
UMask = "0027";
|
||||
};
|
||||
@@ -371,17 +405,27 @@ in
|
||||
/run/current-system/systemd/bin/systemctl reload dhcpcd.service
|
||||
'';
|
||||
|
||||
security.polkit.extraConfig = lib.mkIf config.services.resolved.enable ''
|
||||
polkit.addRule(function(action, subject) {
|
||||
if (action.id == 'org.freedesktop.resolve1.revert' ||
|
||||
action.id == 'org.freedesktop.resolve1.set-dns-servers' ||
|
||||
action.id == 'org.freedesktop.resolve1.set-domains') {
|
||||
if (subject.user == '${config.systemd.services.dhcpcd.serviceConfig.User}') {
|
||||
return polkit.Result.YES;
|
||||
}
|
||||
}
|
||||
});
|
||||
'';
|
||||
security.polkit.extraConfig = lib.mkMerge [
|
||||
(lib.mkIf config.services.resolved.enable ''
|
||||
polkit.addRule(function(action, subject) {
|
||||
if (action.id == 'org.freedesktop.resolve1.revert' ||
|
||||
action.id == 'org.freedesktop.resolve1.set-dns-servers' ||
|
||||
action.id == 'org.freedesktop.resolve1.set-domains') {
|
||||
if (subject.user == 'dhcpcd') {
|
||||
return polkit.Result.YES;
|
||||
}
|
||||
}
|
||||
});
|
||||
'')
|
||||
(lib.mkIf cfg.setHostname ''
|
||||
polkit.addRule(function(action, subject) {
|
||||
if (action.id == 'org.freedesktop.hostname1.set-hostname' &&
|
||||
subject.user == 'dhcpcd') {
|
||||
return polkit.Result.YES;
|
||||
}
|
||||
});
|
||||
'')
|
||||
];
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -178,6 +178,29 @@ let
|
||||
router.wait_until_succeeds("ping -c 1 fd00:1234:5678:2::2")
|
||||
'';
|
||||
};
|
||||
dhcpHostname = {
|
||||
name = "hostnameDHCP";
|
||||
nodes.router = router;
|
||||
nodes.client = clientConfig {
|
||||
# use the name given by the DHCP server
|
||||
system.name = "client";
|
||||
networking.hostName = lib.mkForce "";
|
||||
security.polkit.enable = true;
|
||||
virtualisation.interfaces.enp1s0.vlan = 1;
|
||||
networking.interfaces.enp1s0.useDHCP = true;
|
||||
};
|
||||
testScript = ''
|
||||
router.start()
|
||||
router.systemctl("start network-online.target")
|
||||
router.wait_for_unit("network-online.target")
|
||||
|
||||
client.start()
|
||||
client.wait_for_unit("network.target")
|
||||
|
||||
with subtest("Wait until we have received the hostname"):
|
||||
client.wait_until_succeeds("hostname | grep -q 'client1'")
|
||||
'';
|
||||
};
|
||||
dhcpOneIf = {
|
||||
name = "OneInterfaceDHCP";
|
||||
nodes.router = router;
|
||||
|
||||
@@ -44,6 +44,7 @@ stdenv.mkDerivation rec {
|
||||
"--localstatedir=/var"
|
||||
"--disable-privsep"
|
||||
"--dbdir=/var/lib/dhcpcd"
|
||||
"--with-default-hostname=nixos"
|
||||
(lib.enableFeature enablePrivSep "privsep")
|
||||
] ++ lib.optional enablePrivSep "--privsepuser=dhcpcd";
|
||||
|
||||
@@ -62,7 +63,12 @@ stdenv.mkDerivation rec {
|
||||
) "[ -e ${placeholder "out"}/lib/dhcpcd/dev/udev.so ]";
|
||||
|
||||
passthru.tests = {
|
||||
inherit (nixosTests.networking.scripted) macvlan dhcpSimple dhcpOneIf;
|
||||
inherit (nixosTests.networking.scripted)
|
||||
macvlan
|
||||
dhcpSimple
|
||||
dhcpHostname
|
||||
dhcpOneIf
|
||||
;
|
||||
};
|
||||
|
||||
meta = with lib; {
|
||||
|
||||
Reference in New Issue
Block a user