blob: d3f89cc50c0661a6b9ca92bea32ecfadff066fa0 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
{ config, lib, ... }:
let
cfg = config.nix.firewall;
in
{
options.nix.firewall = {
enable = lib.mkEnableOption "firewalling for outgoing traffic of the nix daemon";
allowLoopback = lib.mkOption {
description = "Whether to allow traffic on the loopback interface. Traffic is still subject to protocol/port rules";
default = false;
example = true;
};
allowPrivateNetworks = lib.mkOption {
description = "Whether to allow traffic to local networks. Traffic is still subject to protocol/port rules. Note that this option may break DNS resolution when the DNS resolver is in a local network";
default = true;
example = false;
};
allowNonTCPUDP = lib.mkOption {
description = "Whether to allow traffic that is neither TCP nor UDP";
type = lib.types.bool;
default = false;
example = true;
};
allowedTCPPorts = lib.mkOption {
description = "TCP ports to which traffic is allowed. Specifying no ports will allow all TCP traffic";
type = lib.types.listOf (
lib.types.oneOf [
lib.types.singleLineStr
lib.types.port
]
);
default = [ ];
example = [
"http"
443
"30000-31000"
];
};
allowedUDPPorts = lib.mkOption {
description = "UDP ports to which traffic is allowed. Specifying no ports will allow all UDP traffic";
type = lib.types.listOf (
lib.types.oneOf [
lib.types.singleLineStr
lib.types.port
]
);
default = [ ];
example = [ 53 ];
};
extraNftablesRules = lib.mkOption {
description = "Extra nftables rules to prepend to the generated ones";
type = lib.types.listOf lib.types.singleLineStr;
default = [ ];
example = [ "ip daddr 1.1.1.1 udp dport accept" ];
};
};
config = lib.mkIf cfg.enable {
# Ensure we can properly use nftables
assertions = [
{
assertion = config.networking.nftables.enable;
message = ''
The nix-daemon firewall requires an nftables-based firewall.
networking.nftables.enable must be set to true.
'';
}
{
assertion = !config.networking.nftables.flushRuleset;
message = ''
The nix-daemon firewall writes extra tables to nftables.
networking.nftables.flushRuleset must be set to false.
'';
}
];
systemd.services.nix-daemon = {
after = [ "nftables.service" ];
# Add the cgroup ID to a nft set on daemon start
serviceConfig.NFTSet = "cgroup:inet:nix_daemon_firewall:nix_daemon";
};
# Generate nftables rules
networking.nftables.ruleset = ''
table inet nix_daemon_firewall {
set nix_daemon {
type cgroupsv2
}
chain output {
type filter hook output priority 0;
socket cgroupv2 level 2 @nix_daemon goto nix_daemon_traffic
accept
}
chain nix_daemon_traffic {
# Extra rules
${lib.concatStringsSep "\n" cfg.extraNftablesRules}
# Loopback
${lib.optionalString (!cfg.allowLoopback) "ip daddr 127.0.0.0/8 counter drop"}
${lib.optionalString (!cfg.allowLoopback) "ip6 daddr ::1 counter drop"}
# Local networks
${lib.optionalString (
!cfg.allowPrivateNetworks
) "ip daddr { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 } counter drop"}
${lib.optionalString (
!cfg.allowPrivateNetworks
) "ip6 daddr { fd00::/8, fe80::/10 } counter drop"}
# TCP
${lib.optionalString (cfg.allowedTCPPorts != [ ]) ''
tcp dport { ${lib.concatStringsSep ", " (map toString cfg.allowedTCPPorts)} } accept
ip protocol tcp counter drop
ip6 nexthdr tcp counter drop
''}
# UDP
${lib.optionalString (cfg.allowedUDPPorts != [ ]) ''
udp dport { ${lib.concatStringsSep ", " (map toString cfg.allowedUDPPorts)} } accept
ip protocol udp counter drop
ip6 nexthdr udp counter drop
''}
# Non-TCP and non-UDP
${lib.optionalString (!cfg.allowNonTCPUDP) "ip protocol != { tcp, udp } counter drop"}
${lib.optionalString (!cfg.allowNonTCPUDP) "ip6 nexthdr != { tcp, udp } counter drop"}
accept
}
}
'';
# Not supported by LKL yet so the ruleset check would fail
networking.nftables.preCheckRuleset = ''
sed -i 's/socket cgroupv2 level 2 @nix_daemon//g' ruleset.conf
'';
};
}
|