at 23.11-pre 4.1 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 cfg = config.services.babeld; 8 9 conditionalBoolToString = value: if (isBool value) then (boolToString value) else (toString value); 10 11 paramsString = params: 12 concatMapStringsSep " " (name: "${name} ${conditionalBoolToString (getAttr name params)}") 13 (attrNames params); 14 15 interfaceConfig = name: 16 let 17 interface = getAttr name cfg.interfaces; 18 in 19 "interface ${name} ${paramsString interface}\n"; 20 21 configFile = with cfg; pkgs.writeText "babeld.conf" ( 22 '' 23 skip-kernel-setup true 24 '' 25 + (optionalString (cfg.interfaceDefaults != null) '' 26 default ${paramsString cfg.interfaceDefaults} 27 '') 28 + (concatMapStrings interfaceConfig (attrNames cfg.interfaces)) 29 + extraConfig); 30 31in 32 33{ 34 35 meta.maintainers = with maintainers; [ hexa ]; 36 37 ###### interface 38 39 options = { 40 41 services.babeld = { 42 43 enable = mkEnableOption (lib.mdDoc "the babeld network routing daemon"); 44 45 interfaceDefaults = mkOption { 46 default = null; 47 description = lib.mdDoc '' 48 A set describing default parameters for babeld interfaces. 49 See {manpage}`babeld(8)` for options. 50 ''; 51 type = types.nullOr (types.attrsOf types.unspecified); 52 example = 53 { 54 type = "tunnel"; 55 split-horizon = true; 56 }; 57 }; 58 59 interfaces = mkOption { 60 default = {}; 61 description = lib.mdDoc '' 62 A set describing babeld interfaces. 63 See {manpage}`babeld(8)` for options. 64 ''; 65 type = types.attrsOf (types.attrsOf types.unspecified); 66 example = 67 { enp0s2 = 68 { type = "wired"; 69 hello-interval = 5; 70 split-horizon = "auto"; 71 }; 72 }; 73 }; 74 75 extraConfig = mkOption { 76 default = ""; 77 type = types.lines; 78 description = lib.mdDoc '' 79 Options that will be copied to babeld.conf. 80 See {manpage}`babeld(8)` for details. 81 ''; 82 }; 83 }; 84 85 }; 86 87 88 ###### implementation 89 90 config = mkIf config.services.babeld.enable { 91 92 boot.kernel.sysctl = { 93 "net.ipv6.conf.all.forwarding" = 1; 94 "net.ipv6.conf.all.accept_redirects" = 0; 95 "net.ipv4.conf.all.forwarding" = 1; 96 "net.ipv4.conf.all.rp_filter" = 0; 97 } // lib.mapAttrs' (ifname: _: lib.nameValuePair "net.ipv4.conf.${ifname}.rp_filter" (lib.mkDefault 0)) config.services.babeld.interfaces; 98 99 systemd.services.babeld = { 100 description = "Babel routing daemon"; 101 after = [ "network.target" ]; 102 wantedBy = [ "multi-user.target" ]; 103 serviceConfig = { 104 ExecStart = "${pkgs.babeld}/bin/babeld -c ${configFile} -I /run/babeld/babeld.pid -S /var/lib/babeld/state"; 105 AmbientCapabilities = [ "CAP_NET_ADMIN" ]; 106 CapabilityBoundingSet = [ "CAP_NET_ADMIN" ]; 107 DevicePolicy = "closed"; 108 DynamicUser = true; 109 IPAddressAllow = [ "fe80::/64" "ff00::/8" "::1/128" "127.0.0.0/8" ]; 110 IPAddressDeny = "any"; 111 LockPersonality = true; 112 NoNewPrivileges = true; 113 MemoryDenyWriteExecute = true; 114 ProtectSystem = "strict"; 115 ProtectClock = true; 116 ProtectKernelTunables = true; 117 ProtectKernelModules = true; 118 ProtectKernelLogs = true; 119 ProtectControlGroups = true; 120 RestrictAddressFamilies = [ "AF_NETLINK" "AF_INET6" "AF_INET" ]; 121 RestrictNamespaces = true; 122 RestrictRealtime = true; 123 RestrictSUIDSGID = true; 124 RemoveIPC = true; 125 ProtectHome = true; 126 ProtectHostname = true; 127 ProtectProc = "invisible"; 128 PrivateMounts = true; 129 PrivateTmp = true; 130 PrivateDevices = true; 131 PrivateUsers = false; # kernel_route(ADD): Operation not permitted 132 ProcSubset = "pid"; 133 SystemCallArchitectures = "native"; 134 SystemCallFilter = [ 135 "@system-service" 136 "~@privileged @resources" 137 ]; 138 UMask = "0177"; 139 RuntimeDirectory = "babeld"; 140 StateDirectory = "babeld"; 141 }; 142 }; 143 }; 144}