mirror of
https://github.com/ryan4yin/nix-config.git
synced 2026-11-13 12:13:46 +01:00
Hosts used to trust the router as the only boundary (servers ran with the firewall off; service ports were opened globally), so any LAN device could reach every host service. Move filtering to the hosts as defence in depth behind the router, which keeps its firewall on and uses a port mapping for the few ports we actually need. - base: nftables backend; deny inbound by default; trust the home LAN by source and the tailnet by interface (restrict the tailnet with ACLs); suppress per-service `openFirewall` global ports; allow node_exporter only from the monitoring host. The local podman bridge, the tailnet and the pod CIDRs are accepted only after the node_exporter drop. - servers: stop disabling the firewall; drop redundant global port opens (caddy 80/443, NFS 2049, Jellyfin, localsend/test ports); delete the redundant desktop firewall module; aarch64/riscv64 import the firewall explicitly (akane was missing it). - k3s: Cilium pods (10.0.0.0/8, fd00::/8) may reach host services; drop the flannel-era cni0/flannel.1 trust. - youko: postgres listens on localhost + the LAN with pg_hba limited to the LAN; the NFS export stays LAN-scoped; remove the unauthenticated v2ray proxy. - tests: `security-firewall` asserts every host runs the shared firewall, has the LAN CIDR rule and no global ports.
222 lines
6.1 KiB
Nix
222 lines
6.1 KiB
Nix
{ lib }:
|
|
rec {
|
|
mainGateway = "192.168.5.1"; # main router
|
|
mainGateway6 = "fe80::5"; # main router's link-local address
|
|
# The trusted home LAN; the shared host firewall trusts this by source.
|
|
lanCidr = "192.168.5.0/24";
|
|
# use suzi as the default gateway
|
|
# it's a subrouter with a transparent proxy
|
|
proxyGateway = "192.168.5.178";
|
|
proxyGateway6 = "fe80::8";
|
|
nameservers = [
|
|
# IPv4
|
|
"119.29.29.29" # DNSPod https://www.dnspod.cn/Products/publicdns
|
|
"223.5.5.5" # AliDNS
|
|
"1.1.1.1" # Cloudflare https://one.one.one.one/dns/
|
|
# IPv6
|
|
"2402:4e00::" # DNSPod
|
|
"2400:3200::1" # Alidns
|
|
"2606:4700:4700::1111" # Cloudflare
|
|
];
|
|
prefixLength = 24;
|
|
|
|
# Dedicated VIP block for the k3s clusters, outside the router's DHCP pool
|
|
# (.2-.99). One /29 per cluster, handed to kube-vip: the first usable address
|
|
# is the control-plane API VIP, the rest are LoadBalancer service VIPs.
|
|
k8sVip = {
|
|
cidr = "192.168.5.192/27";
|
|
clusters = {
|
|
k3s-test-1 = {
|
|
cidr = "192.168.5.192/29";
|
|
apiVip = "192.168.5.193";
|
|
};
|
|
# Reserved for future clusters:
|
|
# .200/29 apiVip .201
|
|
# .208/29 apiVip .209
|
|
# .216/29 apiVip .217
|
|
};
|
|
};
|
|
|
|
hostsAddr = {
|
|
# ============================================
|
|
# Homelab's Physical Machines (VM hosts)
|
|
# ============================================
|
|
shoryu = {
|
|
iface = "eno1";
|
|
ipv4 = "192.168.5.181";
|
|
};
|
|
shushou = {
|
|
iface = "eno1";
|
|
ipv4 = "192.168.5.182";
|
|
};
|
|
youko = {
|
|
iface = "eno1";
|
|
ipv4 = "192.168.5.183";
|
|
};
|
|
|
|
# ============================================
|
|
# Other VMs and Physical Machines
|
|
# ============================================
|
|
ai = {
|
|
# Desktop PC
|
|
iface = "enp130s0";
|
|
ipv4 = "192.168.5.100";
|
|
ipv6 = "fe80::10"; # Link-local Address
|
|
};
|
|
# akane = {
|
|
# # VM (running in macOS's UTM App), using DHCP instead of static ip.
|
|
# iface = "enp0s1";
|
|
# ipv4 = "192.168.64.2";
|
|
# };
|
|
aquamarine = {
|
|
# VM
|
|
iface = "enp2s0";
|
|
ipv4 = "192.168.5.101";
|
|
};
|
|
ruby = {
|
|
# VM
|
|
iface = "enp2s0";
|
|
ipv4 = "192.168.5.102";
|
|
};
|
|
kana = {
|
|
# VM
|
|
iface = "enp2s0";
|
|
ipv4 = "192.168.5.103";
|
|
};
|
|
nozomi = {
|
|
# LicheePi 4A's wireless interface - RISC-V
|
|
iface = "wlan0";
|
|
ipv4 = "192.168.5.104";
|
|
};
|
|
yukina = {
|
|
# LicheePi 4A's wireless interface - RISC-V
|
|
iface = "wlan0";
|
|
ipv4 = "192.168.5.105";
|
|
};
|
|
chiaya = {
|
|
# VM
|
|
iface = "enp2s0";
|
|
ipv4 = "192.168.5.106";
|
|
};
|
|
suzu = {
|
|
# Orange Pi 5 - ARM
|
|
iface = "end1";
|
|
ipv4 = "192.168.5.107";
|
|
};
|
|
rakushun = {
|
|
# Orange Pi 5 - ARM
|
|
# RJ45 port 1 - enP4p65s0
|
|
# RJ45 port 2 - enP3p49s0
|
|
iface = "enP4p65s0";
|
|
ipv4 = "192.168.5.179";
|
|
};
|
|
suzi = {
|
|
iface = "enp2s0"; # fake iface, it's not used by the host
|
|
ipv4 = "192.168.5.178";
|
|
ipv6 = "fe80::8"; # Link-local Address, can be used as default gateway
|
|
};
|
|
mitsuha = {
|
|
iface = "enp2s0"; # fake iface, it's not used by the host
|
|
ipv4 = "192.168.5.177";
|
|
};
|
|
|
|
# ============================================
|
|
# Kubernetes Clusters
|
|
# ============================================
|
|
k3s-test-1-master-1 = {
|
|
# VM
|
|
iface = "enp2s0";
|
|
ipv4 = "192.168.5.114";
|
|
};
|
|
k3s-test-1-master-2 = {
|
|
# VM
|
|
iface = "enp2s0";
|
|
ipv4 = "192.168.5.115";
|
|
};
|
|
k3s-test-1-master-3 = {
|
|
# VM
|
|
iface = "enp2s0";
|
|
ipv4 = "192.168.5.116";
|
|
};
|
|
k3s-test-1-worker-1 = {
|
|
# VM
|
|
iface = "enp2s0";
|
|
ipv4 = "192.168.5.111";
|
|
};
|
|
k3s-test-1-worker-2 = {
|
|
# VM
|
|
iface = "enp2s0";
|
|
ipv4 = "192.168.5.112";
|
|
};
|
|
k3s-test-1-worker-3 = {
|
|
# VM
|
|
iface = "enp2s0";
|
|
ipv4 = "192.168.5.113";
|
|
};
|
|
};
|
|
|
|
hostsInterface = lib.attrsets.mapAttrs (key: val: {
|
|
interfaces."${val.iface}" = {
|
|
useDHCP = false;
|
|
ipv4.addresses = [
|
|
{
|
|
inherit prefixLength;
|
|
address = val.ipv4;
|
|
}
|
|
];
|
|
};
|
|
}) hostsAddr;
|
|
|
|
ssh = {
|
|
# define the host alias for remote builders
|
|
# this config will be written to /etc/ssh/ssh_config
|
|
#
|
|
# Config format:
|
|
# Host — given the pattern used to match against the host name given on the command line.
|
|
# HostName — specify nickname or abbreviation for host
|
|
# IdentityFile — the location of your SSH key authentication file for the account.
|
|
# Format in details:
|
|
# https://www.ssh.com/academy/ssh/config
|
|
extraConfig = (
|
|
lib.attrsets.foldlAttrs (
|
|
acc: host: val:
|
|
acc
|
|
+ ''
|
|
Host ${host}
|
|
HostName ${val.ipv4}
|
|
Port 22
|
|
''
|
|
) "" hostsAddr
|
|
);
|
|
|
|
# this config will be written to /etc/ssh/ssh_known_hosts
|
|
knownHosts =
|
|
# Update only the values of the given attribute set.
|
|
#
|
|
# mapAttrs
|
|
# (name: value: ("bar-" + value))
|
|
# { x = "a"; y = "b"; }
|
|
# => { x = "bar-a"; y = "bar-b"; }
|
|
lib.attrsets.mapAttrs
|
|
(host: value: {
|
|
hostNames = [ host ] ++ (lib.optional (hostsAddr ? host) hostsAddr.${host}.ipv4);
|
|
publicKey = value.publicKey;
|
|
})
|
|
{
|
|
# Define the root user's host key for remote builders, so that nix can verify all the remote builders
|
|
|
|
aquamarine.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEOXFhFu9Duzp6ZBE288gDZ6VLrNaeWL4kDrFUh9Neic root@aquamarine";
|
|
# the restic backup server
|
|
youko.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEs8b3CmxM+utXZVKvJBssXBupBXvvzjHP40HcY7PSyZ root@youko";
|
|
# ruby.publicKey = "";
|
|
# kana.publicKey = "";
|
|
|
|
# ==================================== Other SSH Service's Public Key =======================================
|
|
|
|
# https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/githubs-ssh-key-fingerprints
|
|
"github.com".publicKey =
|
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl";
|
|
};
|
|
};
|
|
}
|