Files
infrastructure/docs/01-PHASE1-DNS-PORTABILITY.md
jazzymc 62a6267026
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Add infrastructure documentation
2026-01-18 16:57:25 +02:00

209 lines
7.9 KiB
Markdown

# Phase 1: Global DNS Portability
## Status: ✅ COMPLETED (2026-01-18)
Pi-hole ad-blocking works on all devices via Tailscale MagicDNS and DoH/DoT endpoints.
---
## Tailscale Configuration
| Parameter | Value |
|-----------|-------|
| Unraid Tailscale IP | 100.100.208.70 |
| Hostname | xtrm-unraid |
| Subnet Route | 192.168.31.0/24 (advertised & approved) |
| Global DNS | Pi-hole via MagicDNS |
| Override Local DNS | Enabled |
### Connected Devices
| Device | Tailscale IP | Status |
|--------|--------------|--------|
| xtrm-unraid | 100.100.208.70 | Online |
| kaloyans-macbook-air | 100.68.118.59 | Active |
| mikrotik-tailscale-1 | 100.75.93.123 | Online |
| samsung-sm-s938b | 100.111.64.56 | Offline |
---
## DNS Services
### Pi-hole Instances
| Instance | Location | IP | Web UI | Status |
|----------|----------|-----|--------|--------|
| Primary | MikroTik Container | 172.17.0.2 | ph2.xtrm-lab.org | ✅ Running |
| Secondary | Unraid (macvlan br0) | 192.168.31.4 | ph1.xtrm-lab.org | ✅ Running |
**Sync:** nebula-sync (healthy) syncs Unraid → MikroTik every 5 minutes
### Unbound Instances (Recursive DNS)
| Instance | Location | IP | Status |
|----------|----------|-----|--------|
| Primary | MikroTik Container | 172.17.0.3 | ✅ Running |
| Secondary | Unraid (macvlan br0) | 192.168.31.5 | ✅ Running |
### Pi-hole Upstream Configuration
**Unraid Pi-hole (192.168.31.4):**
```
upstreams = ["172.17.0.3#53", "192.168.31.5#53"]
```
---
## DoH Endpoint (DNS over HTTPS)
| Parameter | Value |
|-----------|-------|
| URL | `https://doh.xtrm-lab.org/dns-query` |
| Container | DoH-Server (ghcr.io/ich777/doh-server) |
| Listen Port | 8053 |
| Upstream DNS | udp:192.168.31.1:53 |
| Network | dockerproxy |
**Traefik Route (dynamic.yml):**
```yaml
doh-secure:
rule: "Host(`doh.xtrm-lab.org`)"
entryPoints: [https]
tls:
certResolver: cloudflare
service: doh # → http://DoH-Server:8053
```
**Test:**
```bash
curl -H 'accept: application/dns-json' 'https://doh.xtrm-lab.org/dns-query?name=google.com&type=A'
```
---
## DoT Endpoint (DNS over TLS)
| Parameter | Value |
|-----------|-------|
| Hostname | doh.xtrm-lab.org:853 |
| Container | stunnel-dot (dweomer/stunnel) |
| Accept Port | 853 |
| Forward To | 192.168.31.4:53 (Unraid Pi-hole) |
**MikroTik NAT:** WAN:853 → 192.168.31.2:853
**Android Private DNS:** Settings → Private DNS → `doh.xtrm-lab.org`
---
## DNS Architecture
```
┌─────────────────────────────────────┐
│ External Clients │
└──────────────┬──────────────────────┘
┌─────────────────────────┼─────────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Tailscale │ │ DoH │ │ DoT │
│ MagicDNS │ │ doh.xtrm-lab.org│ │ :853 │
│ 100.100.100.100 │ │ (Traefik→DoH) │ │ (stunnel) │
└────────┬────────┘ └────────┬────────┘ └────────┬────────┘
│ │ │
└────────────────────────┼────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ LAN (192.168.31.0/24) │
│ │
│ ┌─────────────────────────┐ ┌─────────────────────────┐ │
│ │ MikroTik Pi-hole │ │ Unraid Pi-hole │ │
│ │ 172.17.0.2 │ │ 192.168.31.4 │ │
│ │ (NAT forced for LAN) │ │ (Direct access allowed) │ │
│ └───────────┬─────────────┘ └───────────┬─────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────────┐ ┌─────────────────────────┐ │
│ │ MikroTik Unbound │ │ Unraid Unbound │ │
│ │ 172.17.0.3 (recursive) │ │ 192.168.31.5 (recursive)│ │
│ └─────────────────────────┘ └─────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
```
---
## DHCP DNS Servers (MikroTik)
| Priority | Server | Notes |
|----------|--------|-------|
| Primary | 192.168.31.1 | MikroTik (NAT forces to Pi-hole 172.17.0.2) |
| Secondary | 192.168.31.4 | Unraid Pi-hole (direct, for failover) |
---
## MikroTik DNS NAT Rules
| Rule | Action | Description |
|------|--------|-------------|
| 3 | ACCEPT | Traffic TO 192.168.31.4:53 (allows Unraid Pi-hole) |
| 7 | DST-NAT | Force LAN DNS to 172.17.0.2 (MikroTik Pi-hole) |
| 21 | DST-NAT | DoT WAN:853 → 192.168.31.2:853 |
---
## Failover Behavior
| Scenario | Behavior |
|----------|----------|
| MikroTik Pi-hole down | Clients use secondary DNS (192.168.31.4) |
| MikroTik Unbound down | Pi-holes use Unraid Unbound (192.168.31.5) |
| Unraid down | MikroTik services continue independently |
---
## Client Configuration
### macOS (DoH)
- Firefox/Chrome: Settings → Security → Custom DNS → `https://doh.xtrm-lab.org/dns-query`
- System-wide: Install DNS profile with DoH URL
### Android (DoT)
- Settings → Network → Private DNS → `doh.xtrm-lab.org`
### Tailscale Clients
- Automatic via MagicDNS (no configuration needed)
---
## Verification Commands
```bash
# Test DoH endpoint
curl -H 'accept: application/dns-json' 'https://doh.xtrm-lab.org/dns-query?name=google.com&type=A'
# Test ad-blocking via DoH
curl -H 'accept: application/dns-json' 'https://doh.xtrm-lab.org/dns-query?name=ads.google.com&type=A'
# Expected: 0.0.0.0
# Test Pi-holes directly
dig +short google.com @172.17.0.2 # MikroTik Pi-hole
dig +short google.com @192.168.31.4 # Unraid Pi-hole
# Test Unbound directly
dig +short google.com @172.17.0.3 # MikroTik Unbound
dig +short google.com @192.168.31.5 # Unraid Unbound
# Check Tailscale ad-blocking
dig +short ads.google.com @100.100.100.100
# Expected: 0.0.0.0
```
---
## Known Issues
| Issue | Status | Notes |
|-------|--------|-------|
| Certificate renewal failing | ⚠️ Open | Cloudflare API token needs Zone:DNS:Edit permission. Certs expire Feb 11, 2026. |