From cfa7a50cb51902f0e9f758ea13c1d728536e8ba4 Mon Sep 17 00:00:00 2001 From: Viktor Barzin Date: Wed, 8 Apr 2026 17:49:33 +0000 Subject: [PATCH] docs: update networking architecture for DNS consolidation - Technitium DNS now at dedicated MetalLB IP 10.0.20.201 (was shared 10.0.20.200) - Document LAN DNS path: pfSense NAT redirect preserves client IPs for Technitium logging - Document pfSense dnsmasq role (K8s VLAN + localhost only, not WAN) - Document pfSense aliases (technitium_dns, k8s_shared_lb) for NAT rule maintainability - Update MetalLB table with per-service IP assignments - Add ClusterIP (10.96.0.53) for CoreDNS internal forwarding [ci skip] Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/architecture/networking.md | 60 ++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/docs/architecture/networking.md b/docs/architecture/networking.md index d3293aa2..34f2424a 100644 --- a/docs/architecture/networking.md +++ b/docs/architecture/networking.md @@ -1,6 +1,6 @@ # Networking Architecture -Last updated: 2026-03-24 +Last updated: 2026-04-08 ## Overview @@ -35,7 +35,7 @@ graph TB subgraph "VLAN 20 - Kubernetes
10.0.20.0/24" pfSense[pfSense
10.0.20.1
Gateway/NAT/DHCP] - Tech[Technitium DNS
10.0.20.101
viktorbarzin.lan] + Tech[Technitium DNS
10.0.20.201 LB / 10.96.0.53 ClusterIP
viktorbarzin.lan] MLB[MetalLB Pool
10.0.20.200-10.0.20.220] subgraph "K8s Nodes" @@ -79,7 +79,7 @@ graph TB | pfSense | 2.7.x | 10.0.20.1 | Gateway, NAT, firewall, DHCP for VLAN 20 | | vmbr0 | Linux bridge | 192.168.1.127/24 | Physical bridge on eno1, uplink to LAN | | vmbr1 | Linux bridge (VLAN-aware) | Internal | VLAN trunk for VM isolation | -| Technitium DNS | Container | 10.0.20.101 | Internal DNS (viktorbarzin.lan) | +| Technitium DNS | Container | 10.0.20.201 (LB) / 10.96.0.53 (ClusterIP) | Internal DNS (viktorbarzin.lan) + full recursive resolver | | Cloudflare DNS | SaaS | External | ~50 public domains under viktorbarzin.me | | Cloudflared | Container | K8s (3 replicas) | Tunnel ingress, replaces port forwarding | | Traefik | Helm chart | K8s (3 replicas + PDB) | Ingress controller, HTTP/3 enabled | @@ -103,9 +103,27 @@ VMs tag traffic on vmbr1 to isolate workloads. pfSense bridges VLAN 20 to the up ### DNS Resolution **Internal (Technitium)**: -- Runs at 10.0.20.101, serves `.viktorbarzin.lan` zone -- Handles internal service discovery (k8s-master.viktorbarzin.lan, truenas.viktorbarzin.lan, etc.) -- All K8s nodes and cluster services use this as primary DNS +- K8s LoadBalancer at **10.0.20.201** (dedicated MetalLB IP), ClusterIP at **10.96.0.53** +- Serves `.viktorbarzin.lan` zone with 30+ internal A/CNAME records +- Also acts as full recursive resolver for public domains +- `externalTrafficPolicy: Local` preserves client source IPs for query logging +- HA: primary + secondary + tertiary pods with anti-affinity, PDB minAvailable=1 + +**LAN client DNS path (192.168.1.0/24)**: +- TP-Link DHCP gives DNS=192.168.1.2 (pfSense WAN) +- pfSense NAT redirect (`rdr`) forwards UDP 53 on WAN directly to Technitium (10.0.20.201) +- Client source IPs are preserved (no SNAT on 192.168.1.x → 10.0.20.x path) +- Technitium logs show real per-device IPs for analytics + +**K8s cluster DNS path**: +- CoreDNS forwards `.viktorbarzin.lan` to Technitium ClusterIP (10.96.0.53) +- CoreDNS forwards public queries to pfSense (10.0.20.1), 8.8.8.8, 1.1.1.1 + +**pfSense dnsmasq (DNS Forwarder)**: +- Listens on LAN (10.0.10.1), OPT1 (10.0.20.1), localhost only — NOT on WAN (192.168.1.2) +- Forwards `.viktorbarzin.lan` to Technitium (10.0.20.201), public queries to 1.1.1.1 +- Serves K8s VLAN clients and pfSense's own DNS needs +- Aliases: `technitium_dns` (10.0.20.201), `k8s_shared_lb` (10.0.20.200) **External (Cloudflare)**: - Manages ~50 public domains, all under `viktorbarzin.me` @@ -165,21 +183,23 @@ Additional middleware: ### MetalLB & Load Balancing -MetalLB v0.15.3 allocates IPs from the range 10.0.20.200-10.0.20.220 in **Layer 2 mode**. All 11 LoadBalancer services share a single IP (**10.0.20.200**) using the `metallb.io/allow-shared-ip: shared` annotation. Services sharing an IP must use the same `externalTrafficPolicy` (standardized to `Cluster`). +MetalLB v0.15.3 allocates IPs from the range 10.0.20.200-10.0.20.220 in **Layer 2 mode**. Most LoadBalancer services share **10.0.20.200** using the `metallb.io/allow-shared-ip: shared` annotation. Technitium DNS has a **dedicated IP (10.0.20.201)** with `externalTrafficPolicy: Local` to preserve client source IPs for query logging. -| Service | Namespace | Ports | -|---------|-----------|-------| -| coturn | coturn | 3478/UDP (STUN/TURN), 49152-49252/UDP (relay) | -| headscale | headscale | 41641/UDP, 3479/UDP | -| windows-kms | kms | 1688/TCP | -| qbittorrent | servarr | 6881/TCP+UDP | -| shadowsocks | shadowsocks | 8388/TCP+UDP | -| torrserver-bt | tor-proxy | 5665/TCP | -| wireguard | wireguard | 51820/UDP | -| mailserver | mailserver | 25, 465, 587, 993/TCP | -| traefik | traefik | 80, 443, 443/UDP (HTTP/3), 10200, 10300, 11434/TCP | -| xray-reality | xray | 7443/TCP | -| technitium-dns | technitium | 53/UDP | +| Service | Namespace | IP | Ports | +|---------|-----------|-----|-------| +| traefik | traefik | 10.0.20.200 (shared) | 80, 443, 443/UDP (HTTP/3), 10200, 10300, 11434/TCP | +| coturn | coturn | 10.0.20.200 (shared) | 3478/UDP (STUN/TURN), 49152-49252/UDP (relay) | +| headscale | headscale | 10.0.20.200 (shared) | 41641/UDP, 3479/UDP | +| windows-kms | kms | 10.0.20.200 (shared) | 1688/TCP | +| qbittorrent | servarr | 10.0.20.200 (shared) | 50000/TCP+UDP | +| shadowsocks | shadowsocks | 10.0.20.200 (shared) | 8388/TCP+UDP | +| torrserver-bt | tor-proxy | 10.0.20.200 (shared) | 5665/TCP | +| wireguard | wireguard | 10.0.20.200 (shared) | 51820/UDP | +| mailserver | mailserver | 10.0.20.200 (shared) | 25, 465, 587, 993/TCP | +| xray-reality | xray | 10.0.20.200 (shared) | 7443/TCP | +| **technitium-dns** | **technitium** | **10.0.20.201 (dedicated)** | **53/UDP+TCP** | + +pfSense aliases reference these IPs: `k8s_shared_lb` (10.0.20.200), `technitium_dns` (10.0.20.201). NAT rules use aliases for maintainability. Critical services are scaled to **3 replicas**: - Traefik (PDB: minAvailable=2)