nixos/nebula: add CAP_NET_BIND_SERVICE when lighthouse node serves DNS (#353665)

authored by Tristan Ross and committed by GitHub 3789fbc4 654d1888

+59 -8
+45 -7
nixos/modules/services/networking/nebula.nix
··· 84 description = "Whether this node is a relay."; 85 }; 86 87 lighthouses = lib.mkOption { 88 type = lib.types.listOf lib.types.str; 89 default = [ ]; ··· 172 ''; 173 example = lib.literalExpression '' 174 { 175 - lighthouse.dns = { 176 - host = "0.0.0.0"; 177 - port = 53; 178 - }; 179 } 180 ''; 181 }; ··· 203 lighthouse = { 204 am_lighthouse = netCfg.isLighthouse; 205 hosts = netCfg.lighthouses; 206 }; 207 relay = { 208 am_relay = netCfg.isRelay; ··· 231 '' 232 settings 233 ); 234 in 235 { 236 # Create the systemd service for Nebula. ··· 248 Restart = "always"; 249 ExecStart = "${netCfg.package}/bin/nebula -config ${configFile}"; 250 UMask = "0027"; 251 - CapabilityBoundingSet = "CAP_NET_ADMIN"; 252 - AmbientCapabilities = "CAP_NET_ADMIN"; 253 LockPersonality = true; 254 NoNewPrivileges = true; 255 PrivateDevices = false; # needs access to /dev/net/tun (below) ··· 302 ); 303 }; 304 305 - meta.maintainers = with lib.maintainers; [ numinit ]; 306 }
··· 84 description = "Whether this node is a relay."; 85 }; 86 87 + lighthouse.dns.enable = lib.mkOption { 88 + type = lib.types.bool; 89 + default = false; 90 + description = "Whether this lighthouse node should serve DNS."; 91 + }; 92 + 93 + lighthouse.dns.host = lib.mkOption { 94 + type = lib.types.str; 95 + default = "localhost"; 96 + description = '' 97 + IP address on which nebula lighthouse should serve DNS. 98 + 'localhost' is a good default to ensure the service does not listen on public interfaces; 99 + use a Nebula address like 10.0.0.5 to make DNS resolution available to nebula hosts only. 100 + ''; 101 + }; 102 + 103 + lighthouse.dns.port = lib.mkOption { 104 + type = lib.types.nullOr lib.types.port; 105 + default = 5353; 106 + description = "UDP port number for lighthouse DNS server."; 107 + }; 108 + 109 lighthouses = lib.mkOption { 110 type = lib.types.listOf lib.types.str; 111 default = [ ]; ··· 194 ''; 195 example = lib.literalExpression '' 196 { 197 + lighthouse.interval = 15; 198 } 199 ''; 200 }; ··· 222 lighthouse = { 223 am_lighthouse = netCfg.isLighthouse; 224 hosts = netCfg.lighthouses; 225 + serve_dns = netCfg.lighthouse.dns.enable; 226 + dns.host = netCfg.lighthouse.dns.host; 227 + dns.port = netCfg.lighthouse.dns.port; 228 }; 229 relay = { 230 am_relay = netCfg.isRelay; ··· 253 '' 254 settings 255 ); 256 + capabilities = 257 + let 258 + nebulaPort = if !settings.tun.disabled then settings.listen.port else 0; 259 + dnsPort = if settings.lighthouse.serve_dns then settings.lighthouse.dns.port else 0; 260 + in 261 + lib.concatStringsSep " " ( 262 + # creation of tunnel interfaces 263 + lib.optional (!settings.tun.disabled) "CAP_NET_ADMIN" 264 + # binding to privileged ports 265 + ++ lib.optional ( 266 + nebulaPort > 0 && nebulaPort < 1024 || dnsPort > 0 && dnsPort < 1024 267 + ) "CAP_NET_BIND_SERVICE" 268 + ); 269 in 270 { 271 # Create the systemd service for Nebula. ··· 283 Restart = "always"; 284 ExecStart = "${netCfg.package}/bin/nebula -config ${configFile}"; 285 UMask = "0027"; 286 + CapabilityBoundingSet = capabilities; 287 + AmbientCapabilities = capabilities; 288 LockPersonality = true; 289 NoNewPrivileges = true; 290 PrivateDevices = false; # needs access to /dev/net/tun (below) ··· 337 ); 338 }; 339 340 + meta.maintainers = with lib.maintainers; [ 341 + numinit 342 + siriobalmelli 343 + ]; 344 }
+14 -1
nixos/tests/nebula.nix
··· 14 lib.mkMerge [ 15 { 16 # Expose nebula for doing cert signing. 17 - environment.systemPackages = [ pkgs.nebula ]; 18 users.users.root.openssh.authorizedKeys.keys = [ snakeOilPublicKey ]; 19 services.openssh.enable = true; 20 networking.firewall.enable = true; # Implicitly true, but let's make sure. ··· 51 lighthouse = 52 { ... }@args: 53 makeNebulaNode args "lighthouse" { 54 networking.interfaces.eth1.ipv4.addresses = lib.mkForce [ 55 { 56 address = "192.168.1.1"; ··· 76 host = "any"; 77 } 78 ]; 79 }; 80 }; 81 }; ··· 338 # allowAny can ping the lighthouse, but not allowFromLighthouse because of its inbound firewall 339 allowAny.succeed("ping -c3 10.0.100.1") 340 allowAny.fail("ping -c3 10.0.100.3") 341 342 # allowFromLighthouse can ping the lighthouse and allowAny 343 allowFromLighthouse.succeed("ping -c3 10.0.100.1")
··· 14 lib.mkMerge [ 15 { 16 # Expose nebula for doing cert signing. 17 + environment.systemPackages = [ 18 + pkgs.dig 19 + pkgs.nebula 20 + ]; 21 users.users.root.openssh.authorizedKeys.keys = [ snakeOilPublicKey ]; 22 services.openssh.enable = true; 23 networking.firewall.enable = true; # Implicitly true, but let's make sure. ··· 54 lighthouse = 55 { ... }@args: 56 makeNebulaNode args "lighthouse" { 57 + networking.firewall.allowedUDPPorts = [ 53 ]; 58 networking.interfaces.eth1.ipv4.addresses = lib.mkForce [ 59 { 60 address = "192.168.1.1"; ··· 80 host = "any"; 81 } 82 ]; 83 + }; 84 + lighthouse = { 85 + dns = { 86 + enable = true; 87 + host = "10.0.100.1"; # bind to lighthouse interface 88 + port = 53; # answer on standard DNS port 89 + }; 90 }; 91 }; 92 }; ··· 349 # allowAny can ping the lighthouse, but not allowFromLighthouse because of its inbound firewall 350 allowAny.succeed("ping -c3 10.0.100.1") 351 allowAny.fail("ping -c3 10.0.100.3") 352 + # allowAny can also resolve DNS on lighthouse 353 + allowAny.succeed("dig @10.0.100.1 allowToLighthouse | grep -E 'allowToLighthouse\.\s+[0-9]+\s+IN\s+A\s+10\.0\.100\.4'") 354 355 # allowFromLighthouse can ping the lighthouse and allowAny 356 allowFromLighthouse.succeed("ping -c3 10.0.100.1")