# ─────────────────────────────────────────────────────────────────────────────
# Runbound — High-security / military-grade configuration
#
# Use-case : Air-gapped network, classified environment, or any deployment
# where strict access control and minimal exposure are required.
#
# Security posture:
# - Strict ACL: only known subnets allowed, everything else refused
# - No public DNS forwarding (self-contained recursive resolver)
# - DoT only (no plaintext DNS)
# - Rate limit tuned to subnet scale
# - REST API key hardened via environment variable (never in config file)
# ─────────────────────────────────────────────────────────────────────────────
server:
interface: 10.0.0.1 # bind to internal NIC only — not exposed externally
port: 853
do-ip4: yes
do-ip6: no # disable IPv6 if not used in this network
do-udp: no
do-tcp: yes
# ── Strict access control ─────────────────────────────────────────────────
# Allow only explicitly listed subnets; refuse (not deny) unrecognised IPs
# so they receive an explicit REFUSED and aren't left wondering.
access-control: 127.0.0.0/8 allow # localhost
access-control: 10.0.0.0/8 allow # internal network
access-control: 172.16.0.0/12 allow # management VLAN
access-control: 0.0.0.0/0 refuse # secure default
# ── Conservative rate limit ───────────────────────────────────────────────
# 500 q/s is ample for <1000 hosts; reduce if you want tighter control.
rate-limit: 500
cache-max-ttl: 900 # 15 min — short TTL enforces fast propagation of changes
# ── DNS rebinding protection ─────────────────────────────────────────────
private-address: 10.0.0.0/8
private-address: 172.16.0.0/12
private-address: 192.168.0.0/16
private-address: 127.0.0.0/8
private-address: ::1/128
private-address: fd00::/8
# ── Internal authoritative zones ─────────────────────────────────────────
local-zone: "internal." static
local-data: "ns1.internal. 300 IN A 10.0.0.1"
local-data: "ns2.internal. 300 IN A 10.0.0.2"
local-data: "ca.internal. 300 IN A 10.0.0.10"
local-data: "ntp.internal. 300 IN A 10.0.0.11"
local-data: "siem.internal. 300 IN A 10.0.0.20"
local-data: "bastion.internal. 300 IN A 10.0.0.50"
# Block common data-exfiltration channels at DNS level
local-zone: "pastbin.com." always_nxdomain
local-zone: "pastebin.com." always_nxdomain
local-zone: "hastebin.com." always_nxdomain
local-zone: "transfer.sh." always_nxdomain
local-zone: "ngrok.io." always_nxdomain
local-zone: "ngrok.com." always_nxdomain
# ── Memory guard (always active — no config needed) ─────────────────────
# At ≥ 80 % system RAM: rate-limiter + resolver cache purged automatically.
# Inflight semaphore: max 4 096 concurrent requests → REFUSED if exceeded.
# ── TLS (required — no plaintext DNS) ────────────────────────────────────
# Internal CA-signed certificate; clients must trust your internal CA.
tls-service-pem: /etc/runbound/cert.pem
tls-service-key: /etc/runbound/key.pem
# IMPORTANT: API key must be set via RUNBOUND_API_KEY env var.
# Never write secrets in config files checked into version control.
# ── Internal recursive resolver (no external forwarding) ─────────────────────
# If the network has no internet access, remove this forward-zone entirely.
# Runbound will return SERVFAIL for names not found locally, which is correct.
# Uncomment only if internet access is available via a controlled egress proxy:
# forward-zone:
# name: "."
# forward-addr: <egress-resolver-ip>@53