feat: move to own dns

This commit is contained in:
kp2pml30 2026-02-17 19:56:50 +09:00
parent 96e942d8ac
commit eaccf45596
Signed by: kp2pml30
GPG key ID: CD6528BAC23E3E34
15 changed files with 138 additions and 202 deletions

View file

@ -40,10 +40,14 @@ in {
./nix-cache.nix
./xray.nix
./secrets.nix
./firewall.nix
];
config = {
security.pam.enableSSHAgentAuth = true;
users.groups.certreaders = {};
users.users.nginx.extraGroups = [ "certreaders" ];
security.pam.sshAgentAuth.enable = true;
users.users."${cfg.username}" = {
isNormalUser = true;

View file

@ -11,25 +11,65 @@
let
cfg = config.kp2pml30.server;
ports = config.kp2pml30.server.ports;
ips = import ./ips.nix;
hostname = cfg.hostname;
relName = fullAddr:
let stripped = lib.removeSuffix ".${hostname}" fullAddr;
in if stripped == fullAddr then "@" else stripped;
domainEntries = lib.mapAttrsToList (_: v: {
name = relName v.full-address;
ip = v.ip;
ipv6 = v.ipv6;
}) ips.addresses;
zoneRecords = lib.concatMapStringsSep "\n" (e:
"${e.name} IN A ${e.ip}\n"
+ "${e.name} IN AAAA ${e.ipv6}\n"
+ "${e.name} IN HTTPS 1 . alpn=h2,http/1.1 ipv4hint=${e.ip} ipv6hint=${e.ipv6}"
) domainEntries;
zoneFile = pkgs.writeText "${hostname}.zone" ''
$ORIGIN ${hostname}.
$TTL 300
@ IN SOA dns.${hostname}. admin.${hostname}. ( 1 3600 600 604800 300 )
@ IN NS dns.${hostname}.
@ IN NS dns2.${hostname}.
www IN CNAME ${hostname}.
${zoneRecords}
'';
in lib.mkIf cfg.nginx {
users.users.coredns = {
isSystemUser = true;
group = "coredns";
extraGroups = [ "certreaders" ];
};
users.groups.coredns = {};
services.coredns.enable = true;
services.coredns.config = ''
dns://.:53 {
forward . tls://1.1.1.1 {
tls
tls_servername cloudflare-dns.com
}
cache
${hostname} {
file ${zoneFile}
}
https://.:${toString ports.coredns-https} {
forward . dns://127.0.0.1:53 {
tls
dns://.:53 {
forward . tls://1.1.1.1 tls://1.0.0.1 {
tls_servername cloudflare-dns.com
policy random
}
cache
}
tls://.:853 {
tls /var/lib/acme/${hostname}/fullchain.pem /var/lib/acme/${hostname}/key.pem
forward . dns://127.0.0.1:53
}
https://.:${toString ports.coredns-https} {
forward . dns://127.0.0.1:53
}
'';
# networking.networkmanager.insertNameservers = [ "127.0.0.1" ];
}

12
nix/server/firewall.nix Normal file
View file

@ -0,0 +1,12 @@
{ ... }:
let
dnsPort = 53;
httpPort = 80;
httpsPort = 443;
dnsOverTlsPort = 853;
in {
networking.firewall = {
allowedTCPPorts = [ dnsPort httpPort httpsPort dnsOverTlsPort ];
allowedUDPPorts = [ dnsPort ];
};
}

16
nix/server/ips.nix Normal file
View file

@ -0,0 +1,16 @@
rec {
machines = {
vdsina = "146.103.126.11";
vdsina-v6 = "2a14:1e00:3:44d::1";
};
addresses = {
forgejo = { ip = machines.vdsina; ipv6 = machines.vdsina-v6; full-address = "git.kp2pml30.moe"; };
www = { ip = machines.vdsina; ipv6 = machines.vdsina-v6; full-address = "kp2pml30.moe"; };
xray = { ip = machines.vdsina; ipv6 = machines.vdsina-v6; full-address = "x.kp2pml30.moe"; };
dns = { ip = machines.vdsina; ipv6 = machines.vdsina-v6; full-address = "dns.kp2pml30.moe"; };
dns2 = { ip = machines.vdsina; ipv6 = machines.vdsina-v6; full-address = "dns2.kp2pml30.moe"; };
signal-proxy = { ip = machines.vdsina; ipv6 = machines.vdsina-v6; full-address = "pr.kp2pml30.moe"; };
nix-cache = { ip = machines.vdsina; ipv6 = machines.vdsina-v6; full-address = "cache.nix.kp2pml30.moe"; };
backend = { ip = machines.vdsina; ipv6 = machines.vdsina-v6; full-address = "backend.kp2pml30.moe"; };
};
}

View file

@ -6,6 +6,7 @@
let
cfg = config.kp2pml30.server;
ports = config.kp2pml30.server.ports;
ips = import ./ips.nix;
acmeRoot = "/var/lib/acme/acme-challenge";
pref = "kp2";
in lib.mkIf cfg.nginx {
@ -15,9 +16,9 @@ in lib.mkIf cfg.nginx {
defaults.email = "kp2pml30@gmail.com";
#defaults.server = "https://acme-staging-v02.api.letsencrypt.org/directory";
certs."${cfg.hostname}" = {
extraDomainNames = [ "pr.${cfg.hostname}" "www.${cfg.hostname}" "git.${cfg.hostname}" "backend.${cfg.hostname}" "dns.${cfg.hostname}" "cache.nix.${cfg.hostname}" "x.${cfg.hostname}" ];
extraDomainNames = lib.mapAttrsToList (_: v: v.full-address) ips.addresses;
webroot = acmeRoot;
group = "nginx";
group = "certreaders";
};
};
@ -34,6 +35,7 @@ in lib.mkIf cfg.nginx {
listen = [
{ addr = "0.0.0.0"; port = 80; }
{ addr = "[::]"; port = 80; }
];
locations."/" = {
@ -47,6 +49,7 @@ in lib.mkIf cfg.nginx {
listen = [
{ addr = "0.0.0.0"; port = 80; }
{ addr = "[::]"; port = 80; }
];
locations."/" = {
@ -60,6 +63,7 @@ in lib.mkIf cfg.nginx {
listen = [
{ addr = "0.0.0.0"; port = 80; }
{ addr = "[::]"; port = 80; }
];
locations."/" = {
@ -73,6 +77,7 @@ in lib.mkIf cfg.nginx {
listen = [
{ addr = "0.0.0.0"; port = 80; }
{ addr = "[::]"; port = 80; }
];
locations."/" = {
@ -98,7 +103,7 @@ in lib.mkIf cfg.nginx {
proxy_send_timeout 60s;
proxy_read_timeout 60s;
resolver 1.1.1.1;
resolver 127.0.0.1;
'';
};
};
@ -112,6 +117,7 @@ in lib.mkIf cfg.nginx {
listen = [
{ addr = "0.0.0.0"; port = 80; }
{ addr = "[::]"; port = 80; }
];
locations."/" = {
@ -149,7 +155,7 @@ in lib.mkIf cfg.nginx {
proxy_send_timeout 60s;
proxy_read_timeout 60s;
resolver 1.1.1.1;
resolver 127.0.0.1;
'';
};
};
@ -182,7 +188,7 @@ in lib.mkIf cfg.nginx {
proxy_send_timeout 60s;
proxy_read_timeout 60s;
resolver 1.1.1.1;
resolver 127.0.0.1;
'';
};
};
@ -192,6 +198,7 @@ in lib.mkIf cfg.nginx {
acmeRoot = acmeRoot;
listen = [
{ addr = "0.0.0.0"; port = 80; }
{ addr = "[::]"; port = 80; }
];
locations."/" = {
proxyPass = "http://${config.services.nix-serve.bindAddress}:${toString config.services.nix-serve.port}";
@ -199,6 +206,9 @@ in lib.mkIf cfg.nginx {
};
} else {});
streamConfig = (builtins.readFile ./stream.nginx);
streamConfig = builtins.replaceStrings
["@SIGNAL_PROXY_PORT@"]
["${toString ports.signal-proxy-port}"]
(builtins.readFile ./stream.nginx);
};
}

View file

@ -41,5 +41,11 @@
default = 8012;
description = "Xray websocket fallback port";
};
signal-proxy-port = lib.mkOption {
type = lib.types.int;
default = 8444;
description = "Signal proxy TLS termination port";
};
};
}

View file

@ -26,7 +26,12 @@ let
${pkgs.openssl}/bin/openssl enc -aes-256-cbc -pbkdf2 -iter 1000000 -base64 -d -k "$KP2_DOTFILES_SECRET_KEY" -in "${./secrets.yaml}" | ${pkgs.yq}/bin/yq '.XRAY_UIDS[]' -r
'';
xray-config-base = builtins.toFile "xray.json" (builtins.readFile ./xray.json);
xray-config-base = builtins.toFile "xray.json" (builtins.toJSON (
let base = builtins.fromJSON (builtins.readFile ./xray.json);
in base // {
inbounds = map (ib: ib // { port = config.kp2pml30.server.ports.xray-main; }) base.inbounds;
}
));
# Script to generate complete xray configuration
generateXrayConfig = pkgs.writeShellScript "generate-xray-config" ''

View file

@ -31,6 +31,7 @@ in lib.mkIf cfg.nginx {
systemd.services.kp2pml30-moe-backend-service = {
enable = true;
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];

View file

@ -12,7 +12,6 @@ map $ssl_preread_server_name $name {
updates.signal.org updates;
updates2.signal.org updates2;
www.microsoft.com xray-entrypoint;
x.kp2pml30.moe xray-entrypoint;
pr.kp2pml30.moe signal-proxy;
@ -86,11 +85,12 @@ upstream ssl-terminator {
}
upstream signal-proxy {
server 127.0.0.1:8444;
server 127.0.0.1:@SIGNAL_PROXY_PORT@;
}
server {
listen 443;
listen [::]:443;
ssl_preread on;
proxy_pass $name;
}
@ -106,7 +106,7 @@ server {
}
server {
listen 8444 ssl;
listen @SIGNAL_PROXY_PORT@ ssl;
server_name pr.kp2pml30.moe;
ssl_preread on;
proxy_pass $name;

View file

@ -1,81 +0,0 @@
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"port": 1080,
"listen": "127.0.0.1",
"protocol": "socks",
"settings": {
"udp": true
}
},
{
"port": 1081,
"listen": "127.0.0.1",
"protocol": "http"
}
],
"outbounds": [
{
"tag": "proxy",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "x.kp2pml30.moe",
"port": 443,
"users": [
{
"id": "YOUR-UUID-HERE",
"encryption": "none",
"flow": "xtls-rprx-vision"
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"show": false,
"fingerprint": "chrome",
"serverName": "www.microsoft.com",
"publicKey": "dRvlorHTupOukJ7aFZNPx-wXUMYJt3GQNrtSjMm9lAg",
"shortId": "deadbabe",
"spiderX": "/"
}
}
},
{
"tag": "direct",
"protocol": "freedom"
},
{
"tag": "block",
"protocol": "blackhole"
}
],
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"domain": [
"regexp:\\.ru$",
"geosite:category-ru",
"regexp:\\.рф$",
"regexp:(^|\\.)vk\\.com$"
],
"outboundTag": "block"
},
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "proxy"
}
]
}
}

View file

@ -1,90 +0,0 @@
{
"log": {
"loglevel": "debug"
},
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"domain": [
"regexp:\\.ru$",
"regexp:\\.рф$",
"domain:vk.com"
],
"outboundTag": "block"
},
{
"type": "field",
"ip": [
"geoip:cn",
"geoip:ru"
],
"outboundTag": "block"
},
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "direct"
}
]
},
"inbounds": [
{
"listen": "127.0.0.1",
"port": 8010,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "YOUR-UUID-HERE",
"flow": "xtls-rprx-vision"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"show": true,
"dest": "www.microsoft.com:443",
"xver": 0,
"serverNames": [
"www.microsoft.com"
],
"privateKey": "",
"shortIds": [
"deadbabe"
],
"debug": true
}
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls"
]
}
}
],
"outbounds": [
{
"protocol": "freedom",
"tag": "direct"
},
{
"protocol": "blackhole",
"tag": "block"
}
],
"policy": {
"levels": {
"0": {
"handshake": 3,
"connIdle": 127
}
}
}
}