docs/configuration/dns.md
Rama main · réplica de lectura del repositorio original.
# DNS Configuration
Advanced DNS configuration options in WireBuddy.
## DNS Resolver Settings
### Upstream DNS Servers
Configure upstream DNS-over-TLS servers:
**Settings → DNS → DNS Resolver**
Format: `IP@PORT#HOSTNAME`
```
1.1.1.1@853#cloudflare-dns.com
9.9.9.9@853#dns.quad9.net
```
| Component | Description |
|-----------|-------------|
| `IP` | Server IP address (IPv4 or IPv6) |
| `PORT` | TLS port (typically 853) |
| `HOSTNAME` | TLS hostname for certificate verification |
### Popular Upstream Providers
??? example "Cloudflare DNS"
```
1.1.1.1@853#cloudflare-dns.com
1.0.0.1@853#cloudflare-dns.com
```
Privacy-focused, fast global network.
??? example "Quad9"
```
9.9.9.9@853#dns.quad9.net
149.112.112.112@853#dns.quad9.net
```
Security-focused with malware blocking.
??? example "AdGuard DNS"
```
94.140.14.14@853#dns.adguard.com
94.140.15.15@853#dns.adguard.com
```
Ad-blocking at the DNS level.
??? example "Google DNS"
```
8.8.8.8@853#dns.google
8.8.4.4@853#dns.google
```
High availability and performance.
### Validate Servers
Before saving, use the **Validate** button to test:
- TLS connectivity
- Certificate verification
- DNS response validation
## Blocklists
### Available Blocklists
WireBuddy includes four pre-configured blocklists:
| ID | Name | Level | Description |
|----|------|-------|-------------|
| `ads` | StevenBlack | Moderate | Unified hosts (ads, malware, trackers) |
| `adguard` | AdGuard DNS filter | Balanced | Curated filter (ads, trackers, phishing) |
| `hagezi` | HaGeZi Pro | Extreme | Aggressive blocking - may cause false positives |
| `porn` | StevenBlack Adult | 18+ | Adult content blocking |
### Default Configuration
- New installations have **StevenBlack** enabled by default
- Adult and Extreme blocklists are disabled by default
### Blocklist Sources
Blocklists are downloaded from trusted sources:
- StevenBlack: `github.com/StevenBlack/hosts`
- AdGuard: `adguardteam.github.io/HostlistsRegistry`
- HaGeZi: `github.com/hagezi/dns-blocklists`
## Custom Rules
### AdGuard Syntax
Custom rules use AdGuard filter syntax:
```adblock
! Block domain and subdomains
||example.com^
! Allow (whitelist) - overrides blocklists
@@||safe.example.com^
! Wildcard blocking
||ads*.example.com^
||tracking-*.cdn.com^
! Regex matching (substring, case-insensitive)
/analytics[0-9]+\.js/
! Comments
! This is a comment
# This is also a comment
```
### Per-Client Rules
Apply rules to specific clients by appending an IP/CIDR scope to each rule:
```adblock
! John's Phone
||facebook.com^$client=10.13.13.2/32
||instagram.com^$client=10.13.13.2/32
||tiktok.com^$client=10.13.13.2/32
! Work Laptop
@@||corporate-analytics.work.com^$client=10.13.13.3/32
```
### Rule Priority
1. **Allow rules always win** - `@@||domain^` overrides any block
2. Custom rules override blocklist entries
3. More specific rules (exact domain) don't override less specific (wildcard)
### Maximum Size
Custom rules text is limited to 100 KB.
## Dual-Stack Configuration
### IPv4 and IPv6 Support
WireBuddy's DNS resolver (Unbound) is fully dual-stack capable, supporting both IPv4 and IPv6 queries.
### Upstream Server Configuration
Specify both IPv4 and IPv6 upstream servers:
```
1.1.1.1@853#cloudflare-dns.com
2606:4700:4700::1111@853#cloudflare-dns.com
```
### Interface Dual-Stack
Configure WireGuard interfaces with both IPv4 and IPv6:
**Settings → WireGuard → Interfaces → [Interface Name]**
```text
IPv4 Address: 10.13.13.1/24
IPv6 Address: fd13:13:13::1/64
```
The resolver then listens on both gateway addresses of that interface.
### Client Dual-Stack
Peers on a dual-stack interface receive both addresses in the generated client
configuration — the tunnel addresses under `[Interface]`, the routes under
`[Peer]`:
```ini
[Interface]
Address = 10.13.13.2/32, fd13:13:13::2/128
DNS = 10.13.13.1, fd13:13:13::1
[Peer]
AllowedIPs = 0.0.0.0/0, ::/0
```
Leave the interface's IPv6 field empty if the host does not route IPv6; peers are
then IPv4-only.
## DNSSEC Configuration
### Enable DNSSEC
**Settings → DNS → DNS Resolver → DNSSEC Toggle**
DNSSEC validates DNS responses cryptographically, protecting against:
- DNS spoofing
- Cache poisoning
- Man-in-the-middle attacks
### Requirements
DNSSEC requires the root trust anchor file:
```
/var/lib/unbound/root.key
```
If this file is missing, the DNSSEC toggle will be disabled.
### Verification
Check if DNSSEC is working:
```bash
dig @10.13.13.1 dnssec.vs.uni-due.de +dnssec
```
Look for `ad` (Authenticated Data) flag in the response.
## Query Logging
### Log Retention
**Settings → Logs → DNS Log Retention**
Options are **No Logs**, 7, 30, 90, 180, or 365 days. The default is 7 days.
Raw query logs dominate the footprint and scale with query volume, not with time
alone, so the same retention window costs very differently across deployments.
**Settings → Logs** reports the actual size on disk for this instance — use that
figure rather than an estimate when sizing a volume. Per-peer query logging can be
switched off for high-volume devices, and the TSDB trend aggregates are small
regardless of raw-log retention.
### Purge Logs
**Settings → Logs → Purge DNS Logs**
Immediately delete all stored DNS query data.
### Storage Location
DNS data uses dual storage:
- **Raw query logs** in JSONL format for the log viewer and troubleshooting
- **Trend aggregates** in the TSDB for fast chart rendering
Raw query logs are stored at:
```
/app/data/dns/queries/
```
Aggregated DNS trend metrics are stored under the TSDB root in the `dns/` series directory:
- `queries_total.jsonl` — total DNS queries per minute bucket
- `queries_blocked.jsonl` — blocked DNS queries per minute bucket
The UI computes block rate from these raw counters, which is more precise than storing pre-computed ratios.
!!! note
The DNS trend chart prefers TSDB aggregates and only falls back to JSONL scans when filtered by client or when no TSDB data exists yet.
## Ad-Blocker Mode
### Temporary Disable
Programmatically disable the ad-blocker:
| Mode | Behavior |
|------|----------|
| `enable` | Enable immediately, clear any timer |
| `disable` | Disable indefinitely |
| `disable_1h` | Disable for 1 hour, then auto-enable |
| `disable_today` | Disable until midnight (server time) |
### Timer Behavior
- Timer runs on the server
- If WireBuddy restarts, the timer state is preserved
- Expired timers are cleaned up on next status check
## Per-Peer Blocklist Selection
### Configuration
Each peer can have custom blocklist selection:
**Peers → Add Peer / Edit Peer → DNS & Filtering**
| Option | Behavior |
|--------|----------|
| **Use Ad-blocking DNS (WireBuddy) enabled + all blocklists selected** | Use all globally enabled blocklists |
| **Use Ad-blocking DNS (WireBuddy) enabled + subset selected** | Apply only the selected blocklists to this peer |
| **Use Ad-blocking DNS (WireBuddy) enabled + no blocklists selected** | Keep WireBuddy DNS, but disable blocklist enforcement for this peer |
| **Use Ad-blocking DNS (WireBuddy) disabled** | Client falls back to Cloudflare (`1.1.1.1`) and Quad9 (`9.9.9.9`) |
### Use Cases
- **Children's devices:** Enable all blocklists including Adult
- **Work devices:** Use only Moderate blocklist
- **Gaming devices:** Disable ad-blocking to avoid issues
- **Guest devices:** Use Balanced blocklist
## Integration with WireGuard
### Automatic DNS Configuration
When creating or editing peers:
1. Enable **Use Ad-blocking DNS (WireBuddy)** to route DNS through the VPN
2. WireBuddy injects the interface gateway IP into the generated client configuration
3. Optionally select a per-peer blocklist profile in **Active Blocklists**
### DNS Server Binding
The DNS resolver binds to WireGuard interface IPs only:
- Prevents conflicts with host DNS (in Docker host network mode)
- Each interface's gateway IP becomes a DNS listening address
- Example: `10.13.13.1:53` for the `wg0` interface
## Troubleshooting
### Unbound Not Installed
Symptoms:
- All DNS controls are disabled
- Buttons show "Unbound not installed" tooltip
- API returns `503 Service Unavailable`
Solution:
- Use the Docker image which includes Unbound
- Or install Unbound manually: `apt install unbound`
### Config Reload Failed
If DNS settings don't apply:
1. Check Unbound logs:
```bash
docker compose --env-file .env -f docker/docker-compose.yml logs wirebuddy | grep -i unbound
```
2. Validate configuration:
```bash
unbound-checkconf /etc/unbound/unbound.conf
```
3. Restart DNS:
- Settings → DNS → Restart
### High Memory Usage
The blocklist file can be large (~10-50 MB). To reduce memory:
1. Disable aggressive blocklists (HaGeZi Pro)
2. Use fewer blocklists
3. Restart Unbound to clear stale cache
## API Reference
### Key Endpoints
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/dns/adblocker/status` | GET | Read current ad-blocker state and active disable timer |
| `/api/dns/status` | GET | DNS status and statistics |
| `/api/dns/config` | GET/POST | DNS configuration |
| `/api/dns/test-upstream` | POST | Validate upstream DNS-over-TLS server reachability |
| `/api/dns/blocklist/sources` | GET/POST | Blocklist selection |
| `/api/dns/blocklist/count` | GET | Get current blocklist domain count |
| `/api/dns/blocklist/update` | POST | Trigger a blocklist refresh |
| `/api/dns/custom-rules` | GET/PATCH | Custom rules management |
| `/api/dns/custom-rules/actions` | POST | Apply bulk custom-rule actions |
| `/api/dns/adblocker/mode` | POST | Change ad-blocker mode |
| `/api/dns/logs` | GET | Query log data |
| `/api/dns/logs` | DELETE | Purge stored DNS query logs |
| `/api/dns/storage` | GET | Inspect DNS log and TSDB storage usage |
| `/api/dns/selftest` | GET | Run DNS health checks |
| `/api/dns/restart` | POST | Restart the DNS service |
| `/api/dns/start` | POST | Start the DNS service |
| `/api/dns/stop` | POST | Stop the DNS service |
See [API Documentation](../api/endpoints.md#dns) for full details.
## Next Steps
- [DNS Features](../features/dns.md) - User guide
- [Security Configuration](security.md) - Security settings
- [Environment Variables](environment.md) - Server configuration