Test dynamic DHCP names in the DNS VM test
A client with a hostname is published with its reverse record, a client claiming a configured name does not take it over, and a name outside the domain is cut to its first label. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AeFqV9dZrK6nipHkPfyM4F
This commit is contained in:
+52
-1
@@ -9,6 +9,18 @@
|
|||||||
let
|
let
|
||||||
common = import ./common.nix;
|
common = import ./common.nix;
|
||||||
clientMac = "02:00:00:00:00:51";
|
clientMac = "02:00:00:00:00:51";
|
||||||
|
|
||||||
|
# Only the settings module's services (router-leases-dns) are used here; the
|
||||||
|
# router itself is configured below.
|
||||||
|
settings = pkgs.writeText "settings.json" (
|
||||||
|
builtins.toJSON {
|
||||||
|
system = {
|
||||||
|
hostName = "router";
|
||||||
|
stateVersion = "26.11";
|
||||||
|
};
|
||||||
|
router = { };
|
||||||
|
}
|
||||||
|
);
|
||||||
in
|
in
|
||||||
pkgs.testers.runNixOSTest {
|
pkgs.testers.runNixOSTest {
|
||||||
name = "router-dns";
|
name = "router-dns";
|
||||||
@@ -55,7 +67,11 @@ pkgs.testers.runNixOSTest {
|
|||||||
router =
|
router =
|
||||||
{ lib, ... }:
|
{ lib, ... }:
|
||||||
{
|
{
|
||||||
imports = [ self.nixosModules.router ];
|
imports = [
|
||||||
|
self.nixosModules.router
|
||||||
|
self.nixosModules.settings
|
||||||
|
];
|
||||||
|
routerSettings.file = settings;
|
||||||
virtualisation.vlans = [
|
virtualisation.vlans = [
|
||||||
1
|
1
|
||||||
2
|
2
|
||||||
@@ -84,6 +100,7 @@ pkgs.testers.runNixOSTest {
|
|||||||
dns = {
|
dns = {
|
||||||
forwarders = [ "203.0.113.1" ];
|
forwarders = [ "203.0.113.1" ];
|
||||||
domain = "lan.test";
|
domain = "lan.test";
|
||||||
|
dynamicLeases = true;
|
||||||
hosts = {
|
hosts = {
|
||||||
nas = [
|
nas = [
|
||||||
"192.168.10.20"
|
"192.168.10.20"
|
||||||
@@ -116,6 +133,23 @@ pkgs.testers.runNixOSTest {
|
|||||||
matchConfig.Name = "eth1";
|
matchConfig.Name = "eth1";
|
||||||
linkConfig.MACAddress = "${clientMac}";
|
linkConfig.MACAddress = "${clientMac}";
|
||||||
networkConfig.DHCP = "ipv4";
|
networkConfig.DHCP = "ipv4";
|
||||||
|
# Claims a name the configuration publishes for someone else.
|
||||||
|
dhcpV4Config.Hostname = "nas";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
laptop =
|
||||||
|
{ lib, ... }:
|
||||||
|
{
|
||||||
|
virtualisation.vlans = [ 2 ];
|
||||||
|
networking.useNetworkd = true;
|
||||||
|
networking.useDHCP = false;
|
||||||
|
networking.firewall.enable = false;
|
||||||
|
networking.interfaces.eth1.ipv4.addresses = lib.mkForce [ ];
|
||||||
|
systemd.network.networks."10-lan" = {
|
||||||
|
matchConfig.Name = "eth1";
|
||||||
|
networkConfig.DHCP = "ipv4";
|
||||||
|
dhcpV4Config.Hostname = "Laptop.evil.example";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -148,6 +182,23 @@ pkgs.testers.runNixOSTest {
|
|||||||
assert q("router") == "192.168.10.1", q("router")
|
assert q("router") == "192.168.10.1", q("router")
|
||||||
assert q("1.10.168.192.in-addr.arpa", "PTR") == "router.lan.test."
|
assert q("1.10.168.192.in-addr.arpa", "PTR") == "router.lan.test."
|
||||||
|
|
||||||
|
with subtest("DHCP clients are published under the name they gave"):
|
||||||
|
laptop.wait_until_succeeds("ip -4 addr show dev eth1 | grep -q 192.168.10.1[0-9][0-9]")
|
||||||
|
addr = laptop.succeed("ip -4 -o addr show dev eth1").split()[3].split("/")[0]
|
||||||
|
router.wait_until_succeeds(f"dig +short @192.168.10.1 laptop.lan.test | grep -qx {addr}", timeout=60)
|
||||||
|
assert q("laptop.lan.test") == addr
|
||||||
|
rev = ".".join(reversed(addr.split("."))) + ".in-addr.arpa"
|
||||||
|
assert q(rev, "PTR") == "laptop.lan.test."
|
||||||
|
|
||||||
|
with subtest("a client cannot take over a name the configuration publishes"):
|
||||||
|
assert q("nas.lan.test") == "192.168.10.20", q("nas.lan.test")
|
||||||
|
assert q("20.10.168.192.in-addr.arpa", "PTR") == "nas.lan.test."
|
||||||
|
|
||||||
|
with subtest("the status shows what was published and skipped"):
|
||||||
|
import json
|
||||||
|
st = json.loads(router.succeed("cat /run/router-leases-dns/status.json"))
|
||||||
|
router.log(str(st))
|
||||||
|
|
||||||
with subtest("the local domain is authoritative: unknown names are not forwarded"):
|
with subtest("the local domain is authoritative: unknown names are not forwarded"):
|
||||||
# Positive control: resolving through the router works at all.
|
# Positive control: resolving through the router works at all.
|
||||||
assert q("other.example.test") == "203.0.113.8"
|
assert q("other.example.test") == "203.0.113.8"
|
||||||
|
|||||||
Reference in New Issue
Block a user