Personal Nix setup

Switch from dnsmasq/stubby to systemd-networkd/resolved only

Changed files
+95 -226
machines
modules
+1 -1
machines/ramune/configuration.nix
···
cidr = "10.0.0.1/24";
};
};
-
dnsmasq.leases = [
+
leases = [
{ macAddress = "98:ed:7e:c6:57:b2"; ipAddress = "10.0.0.102"; } # eero router
{ macAddress = "c4:f1:74:51:4c:f2"; ipAddress = "10.0.0.124"; } # eero router
{ macAddress = "5c:61:99:7a:16:40"; ipAddress = "10.0.0.103"; } # brother printer
-2
modules/router/default.nix
···
imports = [
./network.nix
./timeserver.nix
-
./dnsOverTLS.nix
-
./dnsmasq.nix
./nftables.nix
./upnp.nix
./kernel.nix
-47
modules/router/dnsOverTLS.nix
···
-
{ lib, config, ... }:
-
-
with lib;
-
let
-
cfg = config.modules.router;
-
in {
-
options.modules.router = {
-
dnsOverTLS = {
-
enable = mkOption {
-
default = cfg.enable;
-
description = "Whether to enable Stubby DNS proxy";
-
type = types.bool;
-
};
-
-
port = mkOption {
-
default = 53000;
-
description = "Port for Stubby";
-
type = types.int;
-
};
-
};
-
};
-
-
config = mkIf cfg.dnsOverTLS.enable {
-
services.stubby = {
-
enable = true;
-
settings = {
-
resolution_type = "GETDNS_RESOLUTION_STUB";
-
dns_transport_list = [ "GETDNS_TRANSPORT_TLS" ];
-
tls_authentication = "GETDNS_AUTHENTICATION_REQUIRED";
-
tls_query_padding_blocksize = 128;
-
edns_client_subnet_private = 1;
-
round_robin_upstreams = 1;
-
tls_connection_retries = 5;
-
listen_addresses = [
-
"127.0.0.1@${toString cfg.dnsOverTLS.port}"
-
"0::1@${toString cfg.dnsOverTLS.port}"
-
];
-
appdata_dir = "/var/cache/stubby";
-
trust_anchors_backoff_time = 2500;
-
upstream_recursive_servers = [
-
{ address_data = "1.1.1.1"; tls_auth_name = "cloudflare-dns.com"; }
-
{ address_data = "1.0.0.1"; tls_auth_name = "cloudflare-dns.com"; }
-
];
-
};
-
};
-
};
-
}
-134
modules/router/dnsmasq.nix
···
-
{ lib, config, ... } @ inputs:
-
-
with lib;
-
let
-
inherit (import ../../lib/ipv4.nix inputs) ipv4;
-
-
cfg = config.modules.router;
-
intern = cfg.interfaces.internal;
-
extern = cfg.interfaces.external;
-
-
leaseType = types.submodule {
-
options = {
-
macAddress = mkOption {
-
type = types.str;
-
example = "00:00:00:00:00:00";
-
};
-
ipAddress = mkOption {
-
type = types.str;
-
example = "10.0.0.10";
-
};
-
};
-
};
-
-
dnsServer = if cfg.dnsOverTLS.enable
-
then [ "127.0.0.1#${toString cfg.dnsOverTLS.port}" ]
-
else [ "1.1.1.1" "1.0.0.1" ];
-
-
dhcpHost = builtins.map (lease: "${lease.macAddress},${lease.ipAddress}") cfg.dnsmasq.leases;
-
-
dhcpIPv4Range = let
-
subnetMask = ipv4.prettyIp (ipv4.cidrToSubnetMask intern.cidr);
-
firstIP = ipv4.prettyIp (ipv4.incrementIp (ipv4.cidrToFirstUsableIp intern.cidr) 1);
-
lastIP = ipv4.prettyIp (ipv4.cidrToLastUsableIp intern.cidr);
-
in "${firstIP}, ${lastIP}, ${subnetMask}, 12h";
-
-
localDomains = builtins.map (host: "/${host}/${cfg.address}") cfg.dnsmasq.localDomains;
-
in {
-
options.modules.router = {
-
dnsmasq = {
-
enable = mkOption {
-
default = cfg.enable;
-
description = "Whether to enable DNSMasq";
-
type = types.bool;
-
};
-
-
leases = mkOption {
-
default = [];
-
type = types.listOf leaseType;
-
description = "List of reserved IP address leases";
-
};
-
-
localDomains = mkOption {
-
default = [];
-
type = types.listOf types.str;
-
};
-
};
-
};
-
-
config = mkIf cfg.dnsmasq.enable {
-
modules.router.dnsmasq.localDomains = [
-
"time.apple.com"
-
"time1.apple.com"
-
"time2.apple.com"
-
"time3.apple.com"
-
"time4.apple.com"
-
"time5.apple.com"
-
"time6.apple.com"
-
"time7.apple.com"
-
"time.euro.apple.com"
-
"time.windows.com"
-
"0.android.pool.ntp.org"
-
"1.android.pool.ntp.org"
-
"2.android.pool.ntp.org"
-
"3.android.pool.ntp.org"
-
];
-
-
networking.nameservers = [ "127.0.0.1" ];
-
-
services.resolved.extraConfig = mkDefault ''
-
[Resolve]
-
DNSStubListener=no
-
'';
-
-
services.dnsmasq = {
-
enable = true;
-
alwaysKeepRunning = true;
-
settings = {
-
server = dnsServer;
-
-
# never forward plain names (without a dot or domain part)
-
domain-needed = true;
-
# never forward addresses in the non-routed address spaces.
-
bogus-priv = true;
-
# filter useless windows-originated DNS requests
-
filterwin2k = true;
-
# never read nameservers from /etc/resolv.conf
-
no-resolv = true;
-
-
cache-size = 5000;
-
no-negcache = true;
-
-
expand-hosts = true;
-
addn-hosts = "/etc/hosts";
-
-
dhcp-host = dhcpHost;
-
-
# listen only on intern0 by excluding extern0
-
except-interface = extern.name;
-
-
# set the DHCP server to authoritative and rapic commit mode
-
dhcp-authoritative = true;
-
dhcp-rapid-commit = true;
-
-
# Detect attempts by Verisign to send queries to unregistered hosts
-
bogus-nxdomain = "64.94.110.11";
-
-
address = localDomains;
-
} // (optionalAttrs (intern != null) {
-
dhcp-range = [
-
dhcpIPv4Range
-
"tag:${intern.name}, ::1, constructor:${intern.name}, ra-names, slaac, 12h"
-
];
-
-
dhcp-option = [
-
"option6:information-refresh-time, 6h"
-
"option:router,${cfg.address}"
-
"ra-param=${intern.name},high,0,0"
-
] ++ (
-
if cfg.timeserver.enable then [ "option:ntp-server,${cfg.address}" ] else []
-
);
-
});
-
};
-
};
-
}
+92 -38
modules/router/network.nix
···
cfg = config.modules.router;
+
leaseType = types.submodule {
+
options = {
+
macAddress = mkOption {
+
type = types.str;
+
example = "00:00:00:00:00:00";
+
};
+
ipAddress = mkOption {
+
type = types.str;
+
example = "10.0.0.10";
+
};
+
};
+
};
+
interfaceType = types.submodule {
options = {
name = mkOption {
···
extern = cfg.interfaces.external;
intern = cfg.interfaces.internal;
-
-
links = {
-
"10-${extern.name}" = {
-
matchConfig.PermanentMACAddress = extern.macAddress;
-
linkConfig = {
-
Description = "External Network Interface";
-
Name = extern.name;
-
# MACAddress = "64:20:9f:16:70:a6";
-
MTUBytes = "1500";
-
};
-
};
-
} // (optionalAttrs (intern != null) {
-
"11-${intern.name}" = {
-
matchConfig.PermanentMACAddress = intern.macAddress;
-
linkConfig = {
-
Description = "Internal Network Interface";
-
Name = intern.name;
-
MTUBytes = "1500";
-
};
-
};
-
});
in {
-
options.modules.router = {
+
options.modules.router = let
+
defaultAddress = if intern != null
+
then ipv4.prettyIp (ipv4.cidrToIpAddress intern.cidr)
+
else "127.0.0.1";
+
in {
address = mkOption {
type = types.str;
-
default = if intern != null
-
then ipv4.prettyIp (ipv4.cidrToIpAddress intern.cidr)
-
else "127.0.0.1";
+
default = defaultAddress;
example = "127.0.0.1";
};
mdns = mkOption {
···
type = types.nullOr interfaceType;
default = null;
};
+
};
+
leases = mkOption {
+
default = [];
+
type = types.listOf leaseType;
+
description = "List of reserved IP address leases";
};
};
-
config = mkIf cfg.enable {
-
networking.useNetworkd = true;
-
-
networking.firewall = mkIf (intern != null) {
-
trustedInterfaces = [ "lo" intern.name ];
+
config = let
+
links = {
+
"10-${extern.name}" = {
+
matchConfig.PermanentMACAddress = extern.macAddress;
+
linkConfig = {
+
Description = "External Network Interface";
+
Name = extern.name;
+
# MACAddress = "64:20:9f:16:70:a6";
+
MTUBytes = "1500";
+
};
+
};
+
} // (optionalAttrs (intern != null) {
+
"11-${intern.name}" = {
+
matchConfig.PermanentMACAddress = intern.macAddress;
+
linkConfig = {
+
Description = "Internal Network Interface";
+
Name = intern.name;
+
MTUBytes = "1500";
+
};
+
};
+
});
+
in mkIf cfg.enable {
+
networking = {
+
useNetworkd = true;
+
firewall = mkIf (intern != null) {
+
trustedInterfaces = [ "lo" intern.name ];
+
};
+
nameservers = [
+
"1.1.1.1#cloudflare-dns.com"
+
"2606:4700:4700::1111#cloudflare-dns.com"
+
];
};
boot.initrd.systemd.network = {
···
};
systemd.network = {
-
inherit links;
enable = true;
-
+
inherit links;
networks = {
"10-${extern.name}" = {
name = extern.name;
networkConfig = {
DHCP = "ipv4";
-
DNS = if cfg.dnsmasq.enable then "127.0.0.1" else "1.1.1.1";
IPv4Forwarding = true;
IPv6Forwarding = true;
};
···
} // (optionalAttrs (intern != null) {
"11-${intern.name}" = {
name = intern.name;
+
networkConfig = {
Address = intern.cidr;
-
DHCPServer = false;
+
DHCPServer = true;
IPv4Forwarding = true;
IPv6Forwarding = true;
ConfigureWithoutCarrier = true;
MulticastDNS = cfg.mdns;
};
+
+
dhcpServerConfig = let
+
gatewayAddress = ipv4.prettyIp (ipv4.cidrToIpAddress intern.cidr);
+
in {
+
EmitDNS = true;
+
EmitNTP = true;
+
DNS = gatewayAddress;
+
NTP = gatewayAddress;
+
DefaultLeaseTimeSec = 43200;
+
MaxLeaseTimeSec = 86400;
+
};
+
+
dhcpServerStaticLeases = builtins.map (lease: {
+
Address = lease.ipAddress;
+
MACAddress = lease.macAddress;
+
}) cfg.leases;
};
});
};
-
services.resolved.extraConfig = optionalString cfg.mdns ''
-
DNSStubListener=no
-
MulticastDNS=yes
-
'';
+
services.resolved = {
+
enable = true;
+
fallbackDns = [
+
"1.0.0.1"
+
"2606:4700:4700::1001"
+
];
+
dnsovertls = "opportunistic";
+
extraConfig = strings.concatStringsSep "\n" [
+
"[Resolve]"
+
(optionalString cfg.mdns ''
+
MulticastDNS=yes
+
'')
+
(optionalString (intern != null) ''
+
DNSStubListener=yes
+
DNSStubListenerExtra=${ipv4.prettyIp (ipv4.cidrToIpAddress intern.cidr)}
+
'')
+
];
+
};
};
}
+2 -4
modules/server/tailscale.nix
···
};
config = mkIf (cfg.enable && cfgRoot.enable) {
-
modules.router.dnsmasq.localDomains = [ "${hostname}.fable-pancake.ts.net" ];
-
networking = {
domain = "fable-pancake.ts.net";
firewall.trustedInterfaces = [ "tailscale0" ];
···
services.tailscale = {
enable = true;
-
useRoutingFeatures = "both";
-
extraUpFlags = [ "--advertise-exit-node" "--ssh" ];
+
useRoutingFeatures = "server";
+
extraUpFlags = [ "--advertise-exit-node" "--ssh" "--accept-dns=false" ];
extraDaemonFlags = [ "--no-logs-no-support" ];
authKeyFile = "/run/secrets/tailscale";
};