some dns fix + dnsmasq

This commit is contained in:
asyncnomi 2025-07-27 01:15:27 +02:00
parent 7b3c103b5b
commit b46c2a8355
5 changed files with 154 additions and 36 deletions

View file

@ -9,5 +9,6 @@
./commons/networking.nix
./commons/mesh.nix
./commons/nftables.nix
./commons/resolver.nix
];
}

View file

@ -53,6 +53,18 @@ in
udp dport 51920 accept
'' else ""}
${if myName == mapping.dns.master then ''
# DNS Master
iifname mesh tcp dport 53 accept
iifname mesh udp dport 53 accept
'' else ""}
${if lib.elem myName mapping.dns.secondary then ''
# DNS Secondary
tcp dport 53 accept
udp dport 53 accept
'' else ""}
# Log anything else
ip protocol tcp counter log prefix "tcp.in.dropped: "
ip protocol udp counter log prefix "udp.in.dropped: "
@ -65,11 +77,8 @@ in
ct state invalid counter drop
${if lib.elem myName mapping.bastion.hosts then ''
iifname mgmt oifname mesh* accept
iifname mgmt oifname mesh accept
'' else ""}
# Allow mesh bounces
iifname mesh* oifname mesh* accept
}
chain output {
type filter hook output priority 0; policy accept;

View file

@ -0,0 +1,53 @@
{ ... }:
let
# Import nodes
nodes = import ./../../nodes.nix;
myName = config.hostName;
myPeer = nodes."${myName}";
myId = myPeer.id;
myZone = myPeer.zone;
# Import mapping
mapping = import ./../../mapping.nix;
in
{
services.resolved.enable = false;
networking.resolvconf.enable = false;
networking.domain = "lf";
environment.etc."resolv.conf".text = ''
# Do not edit, will be overwritten by Nixos
domain ${config.networking.domain}
search ${config.networking.domain}
${builtins.concatStringsSep "\n" (map (ip: "nameserver ${ip}") config.services.dnsmasq.settings.listen-address)}
options edns0 trust-ad
'';
services.dnsmasq = {
enable = true;
settings = {
listen-address = [
"::1"
"127.0.0.1"
];
local = [
"/${config.networking.domain}/"
];
server = [
"1.1.1.1"
"8.8.8.8"
"9.9.9.9"
] ++ map (hostName: "/lf/172.19.${nodes.${hostName}.zone}.${nodes.${hostName}.id}") mapping.dns.hosts
++ map (hostName: "/lf/fc00::${nodes.${hostName}.zone}:${nodes.${hostName}.id}") mapping.dns.hosts;
no-resolv = true;
# Resolvconf can auto-generated /etc/dnsmasq-{conf,resolv}.conf
# By default dnsmasq import them
# We've disable resolvconf, but just to be on the safe side
resolv-file = false;
conf-file = false;
log-queries = false;
};
};
}

View file

@ -3,7 +3,8 @@
let
# Import nodes
nodes = import ./../../nodes.nix;
myNode = nodes."${config.hostName}";
myName = config.hostName;
myNode = nodes."${myName}";
# And mapping
mapping = import ./../../mapping.nix;
@ -24,13 +25,12 @@ let
segments = ((lib.stringLength domainkey) / 255);
domainkeySplitted = map (x: lib.substring (x*255) 255 domainkey) (lib.range 0 segments);
#####
## Knot specific
#####
# Define remote based on current role
remotes = if myNode == mapping.dns.master then
remotes = if myName == mapping.dns.master then
map (hostname: {
id = hostname;
address = "172.19.${toString nodes.${hostname}.zone}.${toString nodes.${hostname}.id}@53";
@ -44,23 +44,23 @@ let
remotesNames = map (remote: remote.id) remotes;
# Remotes ACL
remotesACL = if myNode == mapping.dns.master then
remotesACL = if myName == mapping.dns.master then
map (hostname: {
id = "acl_${hostname}";
address = "172.19.${toString nodes.${hostname}.zone}.${toString nodes.${hostname}.id}@53";
address = "172.19.${toString nodes.${hostname}.zone}.${toString nodes.${hostname}.id}";
action = "transfer";
}) mapping.dns.secondary
else
[{
id = "acl_${mapping.dns.master}";
address = "172.19.${toString nodes.${mapping.dns.master}.zone}.${toString nodes.${mapping.dns.master}.id}@53";
address = "172.19.${toString nodes.${mapping.dns.master}.zone}.${toString nodes.${mapping.dns.master}.id}";
action = "notify";
}];
remotesACLNames = map (remote: remote.id) remotesACL;
# Other ACL
letsencryptACL = if myNode == mapping.dns.master then
letsencryptACL = if myName == mapping.dns.master then
[{
id = "acl_le_challenge";
address = [
@ -73,35 +73,64 @@ let
}]
else [];
acls = remotesACL ++ letsencryptACL;
# Mod-query ACLs
modQueryACLs = [{
id = "local";
address = [
"172.19.0.0/16"
"fc00::/96"
];
}];
#####
## Zone specific
#####
# host to dn
hostToDomain = hostname: builtins.replaceStrings ["-"] ["."] hostname;
hostToLfDomain = hostname: builtins.replaceStrings [".lasuite.federez"] [".lf."] (hostToDomain hostname);
# Remove cidr notation
rmCidr = ip: builtins.head (builtins.split "/" ip);
# Gen NS
toNSRecord = host: "IN NS ${hostToDomain host}.net.";
toNSRecord = host: "\tIN NS ${hostToDomain host}.net.";
nsRecords = map toNSRecord mapping.dns.secondary;
dnsSecondaryConfigs = lib.filterAttrs (peerName: _peerConfig: lib.elem peerName mapping.dns.secondary) nodes;
# Gen A NS
nsARecords = lib.flatten (lib.mapAttrsToList (hostname: node:
lib.optional (supportsIPv4 node) "${hostToDomain hostname}.net. IN A ${node.ip4}"
lib.optional (supportsIPv4 node) "${hostToDomain hostname}.net. IN A ${rmCidr node.ip4}"
) dnsSecondaryConfigs);
# Gen AAAA NS
nsAAAARecords = lib.flatten (lib.mapAttrsToList (hostname: node:
lib.optional (supportsIPv6 node) "${hostToDomain hostname}.net. IN AAAA ${node.ip6}"
lib.optional (supportsIPv6 node) "${hostToDomain hostname}.net. IN AAAA ${rmCidr node.ip6}"
) dnsSecondaryConfigs);
# Gen A records for lf zone
lfARecords = lib.flatten (lib.mapAttrsToList (hostname: node:
lib.optional (supportsIPv4 node) "${hostToLfDomain hostname} IN A 172.19.${toString node.zone}.${toString node.id}"
) nodes);
# Gen AAAA records for lf zone
lfAAAARecords = lib.flatten (lib.mapAttrsToList (hostname: node:
lib.optional (supportsIPv6 node) "${hostToLfDomain hostname} IN AAAA fc00::${toString node.zone}:${toString node.id}"
) nodes);
# Gen first NS for SOA
firstNS = builtins.head mapping.dns.secondary;
firstNSDn = "${hostToDomain firstNS}.net.";
# Zone conf
zoneFilePath = "/var/lib/knot/zones/zone-lasuite-federez-net";
zoneLasuiteFederezNetFilePath = "/var/lib/knot/zones/zone-lasuite-federez-net";
zone-lasuite-federez-net = pkgs.writeText "zone-lasuite-federez-net" ''
$ORIGIN lasuite.federez.net.
$TTL 60
@ IN SOA ${builtins.head nsRecords}. monitoring.lasuite.federez.net. (
@ IN SOA ${firstNSDn} monitoring.lasuite.federez.net. (
${timestamp} ; serial
60 ; refresh
60 ; retry
@ -110,7 +139,7 @@ let
IN TXT "v=spf1 a:lasuite.federez.net ~all"
${builtins.concatStringsSep "\n" nsRecords}
${builtins.concatStringsSep "\n" nsRecords}
${builtins.concatStringsSep "\n" nsARecords}
${builtins.concatStringsSep "\n" nsAAAARecords}
@ -119,7 +148,21 @@ let
_mta-sts IN TXT "v=STSv1; id=1"
_smtp._tls IN TXT "v=TLSRPTv1;rua=mailto:postmaster@lasuite.federez.net"
default._domainkey IN TXT "${lib.concatStringsSep "\" \"" domainkeySplitted}"
cause-toujours IN TXT "v=spf1 a:lasuite.federez.net ~all"
'';
zoneLfFilePath = "/var/lib/knot/zones/zone-lf";
zone-lf = pkgs.writeText "zone-lf" ''
$ORIGIN lf.
$TTL 60
@ IN SOA dns.lf. monitoring.lasuite.federez.net. (
${timestamp} ; serial
60 ; refresh
60 ; retry
60 ; expire
60 ) ; minimum TTL
${builtins.concatStringsSep "\n" lfARecords}
${builtins.concatStringsSep "\n" lfAAAARecords}
'';
in
{
@ -170,23 +213,40 @@ in
remote = remotes;
acl = remotesACL ++ otherACL;
acl = acls;
mod-queryacl = modQueryACLs;
zone = if myNode == mapping.dns.master then [
zone = if myName == mapping.dns.master then [
{
domain = "lasuite.federez.net";
file = zoneFilePath;
file = zoneLasuiteFederezNetFilePath;
dnssec-signing = "on";
dnssec-policy = "default";
zonefile-load = "difference";
notify = remotesNames;
acl = remotesACLNames ++ [
"acl_le_challenge"
];
}
{
domain = "lf";
file = zoneLfFilePath;
notify = remotesNames;
acl = remotesACLNames;
module = "mod-queryacl/local";
}
] else [
{
domain = "lasuite.federez.net";
master = builtins.head remotesNames;
acl = remotesACLNames;
}
{
domain = "lf";
master = builtins.head remotesNames;
acl = remotesACLNames;
module = "mod-queryacl/local";
}
];
log = [
@ -199,11 +259,19 @@ in
};
# Write the generated zone file to the writable path
systemd.services.writeZoneFile = {
systemd.services.writeLasuiteFederezNetZoneFile = {
before = [ "knot.service" ];
description = "Write initial zone file for lasuite.federez.net";
serviceConfig = {
ExecStart = "${pkgs.coreutils}/bin/cp '${zone-lasuite-federez-net}' ${zoneFilePath}";
ExecStart = "${pkgs.coreutils}/bin/cp '${zone-lasuite-federez-net}' ${zoneLasuiteFederezNetFilePath}";
};
wantedBy = [ "multi-user.target" ];
};
systemd.services.writeLfZoneFile = {
before = [ "knot.service" ];
description = "Write initial zone file for lasuite.federez";
serviceConfig = {
ExecStart = "${pkgs.coreutils}/bin/cp '${zone-lf}' ${zoneLfFilePath}";
};
wantedBy = [ "multi-user.target" ];
};