1# This test verifies DHCPv4 interaction between a client and a router.
2# For successful DHCP allocations a dynamic update request is sent
3# towards a nameserver to allocate a name in the lan.nixos.test zone.
4# We then verify whether client and router can ping each other, and
5# that the nameserver can resolve the clients fqdn to the correct IP
6# address.
7
8import ./make-test-python.nix ({ pkgs, lib, ...}: {
9 meta.maintainers = with lib.maintainers; [ hexa ];
10
11 name = "kea";
12
13 nodes = {
14 router = { config, pkgs, ... }: {
15 virtualisation.vlans = [ 1 ];
16
17 networking = {
18 useDHCP = false;
19 firewall.allowedUDPPorts = [ 67 ];
20 };
21
22 systemd.network = {
23 enable = true;
24 networks = {
25 "01-eth1" = {
26 name = "eth1";
27 networkConfig = {
28 Address = "10.0.0.1/29";
29 };
30 };
31 };
32 };
33
34 services.kea.dhcp4 = {
35 enable = true;
36 settings = {
37 valid-lifetime = 3600;
38 renew-timer = 900;
39 rebind-timer = 1800;
40
41 lease-database = {
42 type = "memfile";
43 persist = true;
44 name = "/var/lib/kea/dhcp4.leases";
45 };
46
47 interfaces-config = {
48 dhcp-socket-type = "raw";
49 interfaces = [
50 "eth1"
51 ];
52 };
53
54 subnet4 = [ {
55 subnet = "10.0.0.0/29";
56 pools = [ {
57 pool = "10.0.0.3 - 10.0.0.3";
58 } ];
59 } ];
60
61 # Enable communication between dhcp4 and a local dhcp-ddns
62 # instance.
63 # https://kea.readthedocs.io/en/kea-2.2.0/arm/dhcp4-srv.html#ddns-for-dhcpv4
64 dhcp-ddns = {
65 enable-updates = true;
66 };
67
68 ddns-send-updates = true;
69 ddns-qualifying-suffix = "lan.nixos.test.";
70 };
71 };
72
73 services.kea.dhcp-ddns = {
74 enable = true;
75 settings = {
76 forward-ddns = {
77 # Configure updates of a forward zone named `lan.nixos.test`
78 # hosted at the nameserver at 10.0.0.2
79 # https://kea.readthedocs.io/en/kea-2.2.0/arm/ddns.html#adding-forward-dns-servers
80 ddns-domains = [ {
81 name = "lan.nixos.test.";
82 # Use a TSIG key in production!
83 key-name = "";
84 dns-servers = [ {
85 ip-address = "10.0.0.2";
86 port = 53;
87 } ];
88 } ];
89 };
90 };
91 };
92 };
93
94 nameserver = { config, pkgs, ... }: {
95 virtualisation.vlans = [ 1 ];
96
97 networking = {
98 useDHCP = false;
99 firewall.allowedUDPPorts = [ 53 ];
100 };
101
102 systemd.network = {
103 enable = true;
104 networks = {
105 "01-eth1" = {
106 name = "eth1";
107 networkConfig = {
108 Address = "10.0.0.2/29";
109 };
110 };
111 };
112 };
113
114 services.resolved.enable = false;
115
116 # Set up an authoritative nameserver, serving the `lan.nixos.test`
117 # zone and configure an ACL that allows dynamic updates from
118 # the router's ip address.
119 # This ACL is likely insufficient for production usage. Please
120 # use TSIG keys.
121 services.knot = let
122 zone = pkgs.writeTextDir "lan.nixos.test.zone" ''
123 @ SOA ns.nixos.test nox.nixos.test 0 86400 7200 3600000 172800
124 @ NS nameserver
125 nameserver A 10.0.0.3
126 router A 10.0.0.1
127 '';
128 zonesDir = pkgs.buildEnv {
129 name = "knot-zones";
130 paths = [ zone ];
131 };
132 in {
133 enable = true;
134 extraArgs = [
135 "-v"
136 ];
137 extraConfig = ''
138 server:
139 listen: 0.0.0.0@53
140
141 log:
142 - target: syslog
143 any: debug
144
145 acl:
146 - id: dhcp_ddns
147 address: 10.0.0.1
148 action: update
149
150 template:
151 - id: default
152 storage: ${zonesDir}
153 zonefile-sync: -1
154 zonefile-load: difference-no-serial
155 journal-content: all
156
157 zone:
158 - domain: lan.nixos.test
159 file: lan.nixos.test.zone
160 acl: [dhcp_ddns]
161 '';
162 };
163
164 };
165
166 client = { config, pkgs, ... }: {
167 virtualisation.vlans = [ 1 ];
168 systemd.services.systemd-networkd.environment.SYSTEMD_LOG_LEVEL = "debug";
169 networking = {
170 useNetworkd = true;
171 useDHCP = false;
172 firewall.enable = false;
173 interfaces.eth1.useDHCP = true;
174 };
175 };
176 };
177 testScript = { ... }: ''
178 start_all()
179 router.wait_for_unit("kea-dhcp4-server.service")
180 client.wait_for_unit("systemd-networkd-wait-online.service")
181 client.wait_until_succeeds("ping -c 5 10.0.0.1")
182 router.wait_until_succeeds("ping -c 5 10.0.0.3")
183 nameserver.wait_until_succeeds("kdig +short client.lan.nixos.test @10.0.0.2 | grep -q 10.0.0.3")
184 '';
185})