diff options
Diffstat (limited to 'nixos/modules/tasks/network-interfaces.nix')
-rw-r--r-- | nixos/modules/tasks/network-interfaces.nix | 161 |
1 files changed, 113 insertions, 48 deletions
diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix index af98123d477..879f077332e 100644 --- a/nixos/modules/tasks/network-interfaces.nix +++ b/nixos/modules/tasks/network-interfaces.nix @@ -144,33 +144,20 @@ let }; tempAddress = mkOption { - type = types.enum [ "default" "enabled" "disabled" ]; - default = if cfg.enableIPv6 then "default" else "disabled"; - defaultText = literalExample ''if cfg.enableIPv6 then "default" else "disabled"''; + type = types.enum (lib.attrNames tempaddrValues); + default = cfg.tempAddresses; + defaultText = literalExample ''config.networking.tempAddresses''; description = '' When IPv6 is enabled with SLAAC, this option controls the use of - temporary address (aka privacy extensions). This is used to reduce tracking. - The three possible values are: - - <itemizedlist> - <listitem> - <para> - <literal>"default"</literal> to generate temporary addresses and use - them by default; - </para> - </listitem> - <listitem> - <para> - <literal>"enabled"</literal> to generate temporary addresses but keep - using the standard EUI-64 ones by default; - </para> - </listitem> - <listitem> - <para> - <literal>"disabled"</literal> to completely disable temporary addresses. - </para> - </listitem> - </itemizedlist> + temporary address (aka privacy extensions) on this + interface. This is used to reduce tracking. + + See also the global option + <xref linkend="opt-networking.tempAddresses"/>, which + applies to all interfaces where this is not set. + + Possible values are: + ${tempaddrDoc} ''; }; @@ -366,6 +353,32 @@ let isHexString = s: all (c: elem c hexChars) (stringToCharacters (toLower s)); + tempaddrValues = { + disabled = { + sysctl = "0"; + description = "completely disable IPv6 temporary addresses"; + }; + enabled = { + sysctl = "1"; + description = "generate IPv6 temporary addresses but still use EUI-64 addresses as source addresses"; + }; + default = { + sysctl = "2"; + description = "generate IPv6 temporary addresses and use these as source addresses in routing"; + }; + }; + tempaddrDoc = '' + <itemizedlist> + ${concatStringsSep "\n" (mapAttrsToList (name: { description, ... }: '' + <listitem> + <para> + <literal>"${name}"</literal> to ${description}; + </para> + </listitem> + '') tempaddrValues)} + </itemizedlist> + ''; + in { @@ -381,15 +394,38 @@ in # syntax). Note: We also allow underscores for compatibility/legacy # reasons (as undocumented feature): type = types.strMatching - "^$|^[[:alpha:]]([[:alnum:]_-]{0,61}[[:alnum:]])?$"; + "^$|^[[:alnum:]]([[:alnum:]_-]{0,61}[[:alnum:]])?$"; description = '' The name of the machine. Leave it empty if you want to obtain it from a DHCP server (if using DHCP). The hostname must be a valid DNS label (see - RFC 1035 section 2.3.1: "Preferred name syntax") and as such must not - contain the domain part. This means that the hostname must start with a - letter, end with a letter or digit, and have as interior characters only + RFC 1035 section 2.3.1: "Preferred name syntax", RFC 1123 section 2.1: + "Host Names and Numbers") and as such must not contain the domain part. + This means that the hostname must start with a letter or digit, + end with a letter or digit, and have as interior characters only letters, digits, and hyphen. The maximum length is 63 characters. Additionally it is recommended to only use lower-case characters. + If (e.g. for legacy reasons) a FQDN is required as the Linux kernel + network node hostname (uname --nodename) the option + boot.kernel.sysctl."kernel.hostname" can be used as a workaround (but + the 64 character limit still applies). + ''; + }; + + networking.fqdn = mkOption { + readOnly = true; + type = types.str; + default = if (cfg.hostName != "" && cfg.domain != null) + then "${cfg.hostName}.${cfg.domain}" + else throw '' + The FQDN is required but cannot be determined. Please make sure that + both networking.hostName and networking.domain are set properly. + ''; + defaultText = literalExample ''''${networking.hostName}.''${networking.domain}''; + description = '' + The fully qualified domain name (FQDN) of this host. It is the result + of combining networking.hostName and networking.domain. Using this + option will result in an evaluation error if the hostname is empty or + no domain is specified. ''; }; @@ -469,7 +505,7 @@ in networking.search = mkOption { default = []; - example = [ "example.com" "local.domain" ]; + example = [ "example.com" "home.arpa" ]; type = types.listOf types.str; description = '' The list of search paths used when resolving domain names. @@ -478,7 +514,7 @@ in networking.domain = mkOption { default = null; - example = "home"; + example = "home.arpa"; type = types.nullOr types.str; description = '' The domain. It can be left empty if it is auto-detected through DHCP. @@ -519,7 +555,7 @@ in <option>networking.useDHCP</option> is true, then every interface not listed here will be configured using DHCP. ''; - type = with types; loaOf (submodule interfaceOpts); + type = with types; attrsOf (submodule interfaceOpts); }; networking.vswitches = mkOption { @@ -544,7 +580,7 @@ in interfaces = mkOption { example = [ "eth0" "eth1" ]; description = "The physical network interfaces connected by the vSwitch."; - type = with types; loaOf (submodule vswitchInterfaceOpts); + type = with types; attrsOf (submodule vswitchInterfaceOpts); }; controllers = mkOption { @@ -1016,6 +1052,21 @@ in ''; }; + networking.tempAddresses = mkOption { + default = if cfg.enableIPv6 then "default" else "disabled"; + type = types.enum (lib.attrNames tempaddrValues); + description = '' + Whether to enable IPv6 Privacy Extensions for interfaces not + configured explicitly in + <xref linkend="opt-networking.interfaces._name_.tempAddress" />. + + This sets the ipv6.conf.*.use_tempaddr sysctl for all + interfaces. Possible values are: + + ${tempaddrDoc} + ''; + }; + }; @@ -1057,7 +1108,6 @@ in ]; boot.kernelModules = [ ] - ++ optional cfg.enableIPv6 "ipv6" ++ optional hasVirtuals "tun" ++ optional hasSits "sit" ++ optional hasBonds "bonding"; @@ -1076,7 +1126,7 @@ in // listToAttrs (forEach interfaces (i: let opt = i.tempAddress; - val = { disabled = 0; enabled = 1; default = 2; }.${opt}; + val = tempaddrValues.${opt}.sysctl; in nameValuePair "net.ipv6.conf.${replaceChars ["."] ["/"] i.name}.use_tempaddr" val)); # Capabilities won't work unless we have at-least a 4.3 Linux @@ -1089,6 +1139,21 @@ in } else { ping.source = "${pkgs.iputils.out}/bin/ping"; }; + security.apparmor.policies."bin.ping".profile = lib.mkIf config.security.apparmor.policies."bin.ping".enable (lib.mkAfter '' + /run/wrappers/bin/ping { + include <abstractions/base> + include <nixos/security.wrappers> + rpx /run/wrappers/wrappers.*/ping, + } + /run/wrappers/wrappers.*/ping { + include <abstractions/base> + include <nixos/security.wrappers> + r /run/wrappers/wrappers.*/ping.real, + mrpx ${config.security.wrappers.ping.source}, + capability net_raw, + capability setpcap, + } + ''); # Set the host and domain names in the activation script. Don't # clear it if it's not configured in the NixOS configuration, @@ -1122,7 +1187,7 @@ in environment.systemPackages = [ pkgs.host - pkgs.iproute + pkgs.iproute2 pkgs.iputils pkgs.nettools ] @@ -1149,7 +1214,7 @@ in wantedBy = [ "network.target" ]; after = [ "network-pre.target" ]; unitConfig.ConditionCapability = "CAP_NET_ADMIN"; - path = [ pkgs.iproute ]; + path = [ pkgs.iproute2 ]; serviceConfig.Type = "oneshot"; serviceConfig.RemainAfterExit = true; script = '' @@ -1166,9 +1231,11 @@ in (pkgs.writeTextFile rec { name = "ipv6-privacy-extensions.rules"; destination = "/etc/udev/rules.d/98-${name}"; - text = '' + text = let + sysctl-value = tempaddrValues.${cfg.tempAddresses}.sysctl; + in '' # enable and prefer IPv6 privacy addresses by default - ACTION=="add", SUBSYSTEM=="net", RUN+="${pkgs.bash}/bin/sh -c 'echo 2 > /proc/sys/net/ipv6/conf/%k/use_tempaddr'" + ACTION=="add", SUBSYSTEM=="net", RUN+="${pkgs.bash}/bin/sh -c 'echo ${sysctl-value} > /proc/sys/net/ipv6/conf/%k/use_tempaddr'" ''; }) (pkgs.writeTextFile rec { @@ -1177,15 +1244,13 @@ in text = concatMapStrings (i: let opt = i.tempAddress; - val = if opt == "disabled" then 0 else 1; - msg = if opt == "disabled" - then "completely disable IPv6 privacy addresses" - else "enable IPv6 privacy addresses but prefer EUI-64 addresses"; + val = tempaddrValues.${opt}.sysctl; + msg = tempaddrValues.${opt}.description; in '' # override to ${msg} for ${i.name} - ACTION=="add", SUBSYSTEM=="net", RUN+="${pkgs.procps}/bin/sysctl net.ipv6.conf.${replaceChars ["."] ["/"] i.name}.use_tempaddr=${toString val}" - '') (filter (i: i.tempAddress != "default") interfaces); + ACTION=="add", SUBSYSTEM=="net", RUN+="${pkgs.procps}/bin/sysctl net.ipv6.conf.${replaceChars ["."] ["/"] i.name}.use_tempaddr=${val}" + '') (filter (i: i.tempAddress != cfg.tempAddresses) interfaces); }) ] ++ lib.optional (cfg.wlanInterfaces != {}) (pkgs.writeTextFile { @@ -1227,7 +1292,7 @@ in ${optionalString (current.type == "mesh" && current.meshID!=null) "${pkgs.iw}/bin/iw dev ${device} set meshid ${current.meshID}"} ${optionalString (current.type == "monitor" && current.flags!=null) "${pkgs.iw}/bin/iw dev ${device} set monitor ${current.flags}"} ${optionalString (current.type == "managed" && current.fourAddr!=null) "${pkgs.iw}/bin/iw dev ${device} set 4addr ${if current.fourAddr then "on" else "off"}"} - ${optionalString (current.mac != null) "${pkgs.iproute}/bin/ip link set dev ${device} address ${current.mac}"} + ${optionalString (current.mac != null) "${pkgs.iproute2}/bin/ip link set dev ${device} address ${current.mac}"} ''; # Udev script to execute for a new WLAN interface. The script configures the new WLAN interface. @@ -1238,11 +1303,11 @@ in ${optionalString (new.type == "mesh" && new.meshID!=null) "${pkgs.iw}/bin/iw dev ${device} set meshid ${new.meshID}"} ${optionalString (new.type == "monitor" && new.flags!=null) "${pkgs.iw}/bin/iw dev ${device} set monitor ${new.flags}"} ${optionalString (new.type == "managed" && new.fourAddr!=null) "${pkgs.iw}/bin/iw dev ${device} set 4addr ${if new.fourAddr then "on" else "off"}"} - ${optionalString (new.mac != null) "${pkgs.iproute}/bin/ip link set dev ${device} address ${new.mac}"} + ${optionalString (new.mac != null) "${pkgs.iproute2}/bin/ip link set dev ${device} address ${new.mac}"} ''; # Udev attributes for systemd to name the device and to create a .device target. - systemdAttrs = n: ''NAME:="${n}", ENV{INTERFACE}:="${n}", ENV{SYSTEMD_ALIAS}:="/sys/subsystem/net/devices/${n}", TAG+="systemd"''; + systemdAttrs = n: ''NAME:="${n}", ENV{INTERFACE}="${n}", ENV{SYSTEMD_ALIAS}="/sys/subsystem/net/devices/${n}", TAG+="systemd"''; in flip (concatMapStringsSep "\n") (attrNames wlanDeviceInterfaces) (device: let |