Skip to content

Commit 3789fbc

Browse files
nixos/nebula: add CAP_NET_BIND_SERVICE when lighthouse node serves DNS (NixOS#353665)
2 parents 654d188 + a247dd2 commit 3789fbc

File tree

2 files changed

+59
-8
lines changed

2 files changed

+59
-8
lines changed

nixos/modules/services/networking/nebula.nix

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,28 @@ in
8484
description = "Whether this node is a relay.";
8585
};
8686

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+
87109
lighthouses = lib.mkOption {
88110
type = lib.types.listOf lib.types.str;
89111
default = [ ];
@@ -172,10 +194,7 @@ in
172194
'';
173195
example = lib.literalExpression ''
174196
{
175-
lighthouse.dns = {
176-
host = "0.0.0.0";
177-
port = 53;
178-
};
197+
lighthouse.interval = 15;
179198
}
180199
'';
181200
};
@@ -203,6 +222,9 @@ in
203222
lighthouse = {
204223
am_lighthouse = netCfg.isLighthouse;
205224
hosts = netCfg.lighthouses;
225+
serve_dns = netCfg.lighthouse.dns.enable;
226+
dns.host = netCfg.lighthouse.dns.host;
227+
dns.port = netCfg.lighthouse.dns.port;
206228
};
207229
relay = {
208230
am_relay = netCfg.isRelay;
@@ -231,6 +253,19 @@ in
231253
''
232254
settings
233255
);
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+
);
234269
in
235270
{
236271
# Create the systemd service for Nebula.
@@ -248,8 +283,8 @@ in
248283
Restart = "always";
249284
ExecStart = "${netCfg.package}/bin/nebula -config ${configFile}";
250285
UMask = "0027";
251-
CapabilityBoundingSet = "CAP_NET_ADMIN";
252-
AmbientCapabilities = "CAP_NET_ADMIN";
286+
CapabilityBoundingSet = capabilities;
287+
AmbientCapabilities = capabilities;
253288
LockPersonality = true;
254289
NoNewPrivileges = true;
255290
PrivateDevices = false; # needs access to /dev/net/tun (below)
@@ -302,5 +337,8 @@ in
302337
);
303338
};
304339

305-
meta.maintainers = with lib.maintainers; [ numinit ];
340+
meta.maintainers = with lib.maintainers; [
341+
numinit
342+
siriobalmelli
343+
];
306344
}

nixos/tests/nebula.nix

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ import ./make-test-python.nix (
1414
lib.mkMerge [
1515
{
1616
# Expose nebula for doing cert signing.
17-
environment.systemPackages = [ pkgs.nebula ];
17+
environment.systemPackages = [
18+
pkgs.dig
19+
pkgs.nebula
20+
];
1821
users.users.root.openssh.authorizedKeys.keys = [ snakeOilPublicKey ];
1922
services.openssh.enable = true;
2023
networking.firewall.enable = true; # Implicitly true, but let's make sure.
@@ -51,6 +54,7 @@ import ./make-test-python.nix (
5154
lighthouse =
5255
{ ... }@args:
5356
makeNebulaNode args "lighthouse" {
57+
networking.firewall.allowedUDPPorts = [ 53 ];
5458
networking.interfaces.eth1.ipv4.addresses = lib.mkForce [
5559
{
5660
address = "192.168.1.1";
@@ -77,6 +81,13 @@ import ./make-test-python.nix (
7781
}
7882
];
7983
};
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+
};
8091
};
8192
};
8293

@@ -338,6 +349,8 @@ import ./make-test-python.nix (
338349
# allowAny can ping the lighthouse, but not allowFromLighthouse because of its inbound firewall
339350
allowAny.succeed("ping -c3 10.0.100.1")
340351
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'")
341354
342355
# allowFromLighthouse can ping the lighthouse and allowAny
343356
allowFromLighthouse.succeed("ping -c3 10.0.100.1")

0 commit comments

Comments
 (0)