blob: 1aaddc0eb469e2d0cf07fbf61cc7d849a36c2fd1 (
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
|
# Test the firewall module.
{ lib, backend, ... }:
{
name = "firewall-${backend}";
meta = with lib.maintainers; {
maintainers = [
prince213
rvfg
garyguo
];
};
nodes = {
walled =
{ lib, ... }:
{
networking.firewall = {
enable = true;
inherit backend;
logRefusedPackets = true;
# Syntax smoke test, not actually verified otherwise
allowedTCPPorts = [
25
993
8005
];
allowedTCPPortRanges = [
{
from = 980;
to = 1000;
}
{
from = 990;
to = 1010;
}
{
from = 8000;
to = 8010;
}
];
interfaces = lib.mkIf (backend != "firewalld") {
eth0 = {
allowedTCPPorts = [ 10003 ];
allowedTCPPortRanges = [
{
from = 10000;
to = 10005;
}
];
};
eth3 = {
allowedUDPPorts = [ 10003 ];
allowedUDPPortRanges = [
{
from = 10000;
to = 10005;
}
];
};
};
};
services.firewalld.enable = backend == "firewalld";
networking.nftables.enable = backend != "iptables";
services.httpd.enable = true;
services.httpd.adminAddr = "foo@example.org";
specialisation.different-config.configuration = {
networking.firewall.rejectPackets = true;
};
};
attacker =
{ ... }:
{
services.httpd.enable = true;
services.httpd.adminAddr = "foo@example.org";
networking.firewall.enable = false;
};
};
testScript =
{ nodes, ... }:
let
unit = if backend == "iptables" then "firewall" else backend;
openPort =
if backend == "firewalld" then
"firewall-cmd --add-port=80/tcp"
else
"nixos-firewall-tool open tcp 80";
reset = if backend == "firewalld" then "firewall-cmd --reload" else "nixos-firewall-tool reset";
# https://github.com/firewalld/firewalld/issues/1571
waitForFirewalld = lib.optionalString (backend == "firewalld") ''
walled.wait_until_succeeds("firewall-cmd --state")
'';
in
''
start_all()
walled.wait_for_unit("${unit}")
walled.wait_for_unit("httpd")
${waitForFirewalld}
attacker.wait_for_unit("network.target")
# Local connections should still work.
walled.succeed("curl -v http://localhost/ >&2")
# Connections to the firewalled machine should fail, but ping should succeed.
attacker.fail("curl --fail --connect-timeout 2 http://walled/ >&2")
attacker.succeed("ping -c 1 walled >&2")
# Outgoing connections/pings should still work.
walled.succeed("curl -v http://attacker/ >&2")
walled.succeed("ping -c 1 attacker >&2")
# Open tcp port 80 at runtime
walled.succeed("${openPort}")
attacker.succeed("curl -v http://walled/ >&2")
# Reset the firewall
walled.succeed("${reset}")
attacker.fail("curl --fail --connect-timeout 2 http://walled/ >&2")
# Check whether activation of a new configuration reloads the firewall.
walled.succeed(
"/run/booted-system/specialisation/different-config/bin/switch-to-configuration test 2>&1 | grep -F ${unit}.service"
)
# If we stop the firewall, then connections should succeed.
walled.stop_job("${unit}")
attacker.succeed("curl -v http://walled/ >&2")
'';
}
|