summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assets/internal-tls.crt14
-rw-r--r--machines/corsac/default.nix2
-rw-r--r--modules/dns.nix134
-rw-r--r--secrets/internal-tls.age12
-rw-r--r--secrets/secrets.nix4
5 files changed, 146 insertions, 20 deletions
diff --git a/assets/internal-tls.crt b/assets/internal-tls.crt
new file mode 100644
index 0000000..091395a
--- /dev/null
+++ b/assets/internal-tls.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKzCCAbCgAwIBAgIUYcBKrl7FErRDTmgQxxVty3FCVh4wCgYIKoZIzj0EAwIw
+TDELMAkGA1UEBhMCREUxDzANBgNVBAoMBlJlbmFyZDEQMA4GA1UEAwwHcm5yZC5l
+dTEaMBgGCSqGSIb3DQEJARYLbWVsQHJucmQuZXUwHhcNMjUwMjE5MDIyNTQ1WhcN
+MzUwMjE3MDIyNTQ1WjBMMQswCQYDVQQGEwJERTEPMA0GA1UECgwGUmVuYXJkMRAw
+DgYDVQQDDAdybnJkLmV1MRowGAYJKoZIhvcNAQkBFgttZWxAcm5yZC5ldTB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABNddXJB4zyixrOCRBotlqGbLTFpIZzUqqoQvAavK
+hSqMfci+vglB/Quz5tm68HL2ibR3j2TT8hR1nSiojLSLljcfyIXxCP+QrE39Er0G
+uV3DCl8qARMwL2RTUzQm0l5JTKNTMFEwHQYDVR0OBBYEFOUCR4AvmCrjXKuxAUGk
+YuG+HNhQMB8GA1UdIwQYMBaAFOUCR4AvmCrjXKuxAUGkYuG+HNhQMA8GA1UdEwEB
+/wQFMAMBAf8wCgYIKoZIzj0EAwIDaQAwZgIxAJbLR1QLVKHF1u92lGV8OxeBiNMJ
+4idfA0Usd9x0OCcDK7G7NqFmgi6Au/Z81LD3qwIxAPOBt6iKW4U2L+dpcKm1N3ek
+MEgCtSv4o9mgprgOZr2HBsZIdmIZuSrkruhsAlqfTQ==
+-----END CERTIFICATE-----
diff --git a/machines/corsac/default.nix b/machines/corsac/default.nix
index 66c898c..fde09f6 100644
--- a/machines/corsac/default.nix
+++ b/machines/corsac/default.nix
@@ -19,7 +19,7 @@
foundation.monitoring = {
client.enable = true;
- services = [ "base" "jellyfin" "immich" ];
+ services = [ "base" "dns" "jellyfin" "immich" ];
};
system.stateVersion = "24.05";
diff --git a/modules/dns.nix b/modules/dns.nix
index 235411d..0e17259 100644
--- a/modules/dns.nix
+++ b/modules/dns.nix
@@ -1,42 +1,138 @@
-{ oisd, ... }:
+{ config, oisd, ... }:
let
+ inherit (config.age) secrets;
+
tailscaleDns = [ "/serval-moth.ts.net/100.100.100.100" ];
cloudflareServers = [
- "1.1.1.1" "1.0.0.1"
- "2606:4700:4700::1111" "2606:4700:4700::1001"
+ "1.1.1.1"
+ "1.0.0.1"
+ "2606:4700:4700::1111"
+ "2606:4700:4700::1001"
];
quad9Servers = [
- "9.9.9.9" "149.112.112.112"
- "2620:fe::fe" "2620:fe::9"
+ "9.9.9.9"
+ "149.112.112.112"
+ "2620:fe::fe"
+ "2620:fe::9"
];
upstreamServers = cloudflareServers ++ quad9Servers ++ tailscaleDns;
+
+ dnsProxyPort = 4157;
+ dohInternalPort = 4158;
+ dotInternalPort = 4159;
+
+ # well-known
+ dnsPort = 53;
+ dotPort = 853;
in
{
+ networking.firewall = {
+ allowedTCPPorts = [
+ dnsPort
+ dotPort
+ ];
+ allowedUDPPorts = [ dnsPort ];
+ };
services.resolved.enable = false;
- services.dnsmasq = {
- enable = true;
+ age.secrets.internal-tls = {
+ file = ../secrets/internal-tls.age;
+ };
+
+ services = {
+ dnsmasq = {
+ enable = true;
+
+ # Ref: https://thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html
+ settings = {
+ interface = [
+ "enp1s0"
+ "tailscale0"
+ ];
+ bind-dynamic = true;
+
+ server = upstreamServers;
+ cache-size = 4096;
+
+ no-resolv = true;
+ bogus-priv = true;
+ domain-needed = true;
+ localise-queries = true;
- # Ref: https://thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html
- settings = {
- interface = [ "enp1s0" "tailscale0" ];
- bind-dynamic = true;
+ conf-file = "${oisd}/dnsmasq2_big.txt";
- server = upstreamServers;
- cache-size = 4096;
+ log-queries = "extra";
+ };
+ };
- no-resolv = true;
- bogus-priv = true;
- domain-needed = true;
- localise-queries = true;
+ dnsproxy = {
+ enable = true;
+ settings = {
+ listen-addrs = [ "127.0.0.1" ];
+ listen-ports = [ dnsProxyPort ]; # just so that it doesn't bind to 53
+ upstream = [ "127.0.0.1:53" ];
+ cache = false;
- conf-file = "${oisd}/dnsmasq2_big.txt";
+ # NOTE: DoH only supports DNS Wireformat so far.
+ # JSON support has been requested.
+ # see issue: https://github.com/AdguardTeam/dnsproxy/issues/422
+ # NOTE(2): also, there's an open PR to avoid dealing with these
+ # certificates and expose dnsproxy through HTTP, to later
+ # reverse proxy Nginx to it, like I'm doing here.
+ # see: https://github.com/AdguardTeam/dnsproxy/pull/302
+ https-port = [ dohInternalPort ];
+ tls-port = [ dotInternalPort ];
- log-queries = "extra";
+ tls-crt = ../assets/internal-tls.crt;
+ };
+ flags = [ "--tls-key=\${CREDENTIALS_DIRECTORY}/internal-tls" ];
};
+
+ nginx = {
+ # DNS-over-HTTPS
+ virtualHosts."dns.rnrd.eu" = {
+ useACMEHost = "rnrd.eu";
+ forceSSL = true;
+
+ locations."/" = {
+ proxyPass = "https://127.0.0.1:${toString dohInternalPort}";
+ extraConfig = ''
+ proxy_ssl_trusted_certificate ${../assets/internal-tls.crt};
+ proxy_ssl_verify off;
+ '';
+ };
+
+ extraConfig = ''
+ access_log /var/log/nginx/dns.access.log json_combined;
+ '';
+ };
+
+ # DNS-over-TLS
+ streamConfig =
+ let
+ rnrdCertPath = config.security.acme.certs."rnrd.eu".directory;
+ in
+ ''
+ server {
+ listen [::]:${toString dotPort} ssl ipv6only=off;
+ ssl_certificate ${rnrdCertPath}/fullchain.pem;
+ ssl_certificate_key ${rnrdCertPath}/key.pem;
+ ssl_trusted_certificate ${rnrdCertPath}/chain.pem;
+
+ proxy_pass 127.0.0.1:${toString dotInternalPort};
+ proxy_ssl on;
+ proxy_ssl_trusted_certificate ${../assets/internal-tls.crt};
+ proxy_ssl_verify off;
+ }
+ '';
+ };
+ };
+
+ systemd.services.dnsproxy.serviceConfig = {
+ LoadCredential = "internal-tls:${secrets.internal-tls.path}";
};
}
diff --git a/secrets/internal-tls.age b/secrets/internal-tls.age
new file mode 100644
index 0000000..9739177
--- /dev/null
+++ b/secrets/internal-tls.age
@@ -0,0 +1,12 @@
+age-encryption.org/v1
+-> ssh-ed25519 QWV68w Zg5WaS3I4moNEdTVL4P2vOP3x167qcglRtcI+alpgik
+juZiGCS7mt69uYw+FPu48MJg6gPcUvkpIP8u75n7nFc
+-> ssh-ed25519 ztr2Fw gbBZeff8Le8yZjLK7FhRtXoSse/xLt3jXOv3EpOp7Hw
+yoq4YvmmLdXfkjKqcNB4RCFe09pFCYzhdAF1CH+hhGk
+-> ssh-ed25519 COVM9Q 3qjc1AURNkmokmwA1w4w65zoPb0HXPxMzq9qRWBd0Gk
+QmABFr6ETCE+nVgKQnFMdHaHj9x7iKdjc76V6hNI3LM
+-> ssh-ed25519 aV3pTQ MesVv49L93aUOkq29Dn8x8Qet2bJAtwJNdNgsWJdcXg
+qMy/C1oWQEt/xfwi0qqFiW5zOzTHtSF3Dtw8vcjjQBo
+--- oYdUWwxwhjtaCRtaSmcw0CfDcGpsBoFQ3gEPFinp+kU
+¥�hrë•~ϲٻþ¢Ò«×îcž¿w�R“F¯Ùí›n¯0-Ãï£Ø”‘‘6òCl£‹B5Þ¹Öcð Æ&<-}²ËôÌÊPÒŸƒ¯‹XzÈ5’Xq¶“µ¸,¿� ŸŽçôr´9çýÊ^0Ôä6¦–Ÿâ‚y Oï;IJ\H©PV™r«Âw÷`rñ%’�Ìϱ³ˆÝû[쑲Líƒt—Øpçݚݥ5 H uOœk£d•­ªÛó}:…+eÕò#�!©�ü€ØjÀP¯¹U¤ñýC\•ÿÓW96ƒp‰…®p0}íiK2²,ÿ•]éŸjÝøP¾œŒ^¥
+1yY,ƒÜ¦i•ßá¥ß¬Ô¦Ó&¹ „ì±sÌ®¥2HMYÙ±J{­Pƒ¿ —è{¸(6“ÿ±JàÃ@iÿpbRÃ@zFì-&»Æç�]ÍT΋ \ No newline at end of file
diff --git a/secrets/secrets.nix b/secrets/secrets.nix
index 1b768d4..704213e 100644
--- a/secrets/secrets.nix
+++ b/secrets/secrets.nix
@@ -23,5 +23,9 @@ in
corsac
] ++ allAdmins;
+ "internal-tls.age".publicKeys = [
+ corsac
+ ] ++ allAdmins;
+
"password.age".publicKeys = allSystems ++ allAdmins;
}