DNS Server Configuration
Configure and use Wiretastix's built-in authoritative DNS server for VPN peer name resolution.
Wiretastix includes a built-in authoritative DNS server that provides automatic name resolution for VPN peers. This guide covers DNS configuration, integration with existing DNS infrastructure, and troubleshooting.
Overview
What the DNS Server Provides
Forward DNS (A/AAAA records):
- Resolve peer names to their VPN IP addresses
- Example:
john-laptop.vpn.local→10.0.100.5
Reverse DNS (PTR records):
- Resolve VPN IP addresses to peer names
- Example:
10.0.100.5→john-laptop.vpn.local
Automatic updates:
- Records automatically created/updated when peers connect
- No manual DNS management required
- Synchronized with peer database
Use Cases
Internal service discovery:
- Reference peers by name instead of IP
- SSH to peers:
ssh john-laptop.vpn.local - Application configuration with stable names
Logging and monitoring:
- Log entries show peer names, not just IPs
- Easier troubleshooting and auditing
- Human-readable connection logs
Network diagnostics:
- Ping peers by name:
ping jane-phone.vpn.local - Traceroute with names
- DNS-based service discovery
Architecture
┌─────────────────────────────────────────────────────────┐
│ VPN Client │
│ → Queries: john-laptop.vpn.local │
└──────────────┬──────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Corporate DNS Server (Bind, dnsmasq, etc.) │
│ → Checks: Is it *.vpn.local? │
│ Yes: Forward to Wiretastix DNS (10.0.1.10:5353) │
│ No: Handle normally or forward to internet │
└──────────────┬──────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Wiretastix DNS Server │
│ → Queries database for peer "john-laptop" │
│ → Returns: 10.0.100.5 (A) and fd00::5 (AAAA) │
└─────────────────────────────────────────────────────────┘
Configuration
Basic Setup
Configure DNS in wiretastix.yaml:
resolver:
enabled: true
# Bind address and port
binding: 0.0.0.0:5353
# Number of concurrent query handlers
concurrency: 5
# DNS domain for VPN peers
domain: vpn.local
Configuration options:
| Parameter | Default | Description |
|---|---|---|
enabled | false | The resolver is off unless explicitly enabled. Anyone who can reach it can enumerate every peer’s nickname and VPN IP via PTR queries, so it stays disabled until you turn it on. |
binding | 0.0.0.0:5353 | IP:port to bind DNS server |
concurrency | 5 | Max concurrent DNS queries |
domain | vpn.local | DNS suffix for peer names |
acls | [] (empty) | List of CIDR blocks (IPv4/IPv6) allowed to query the resolver. Empty means any source that can reach it may query – see Access Control below. |
Binding Options
Bind to All Interfaces
resolver:
enabled: true
binding: 0.0.0.0:5353
Accessible from any network interface. Use firewall to restrict access.
Bind to Specific Interface
resolver:
enabled: true
binding: 10.0.1.10:5353
Only accessible from 10.0.1.10 interface.
Bind to Localhost Only
resolver:
enabled: true
binding: 127.0.0.1:5353
Only accessible from Wiretastix server (for testing or SSH tunnel access).
Bind to VPN Interface
resolver:
enabled: true
binding: 10.0.100.1:5353 # VPN server IP
Only accessible from VPN clients.
Port Selection
Default: Port 5353
Standard DNS uses port 53, but Wiretastix uses 5353 to:
- Avoid conflicts with system DNS resolvers
- Allow running without root (ports < 1024 require privileges)
- Enable forwarding from primary DNS server
Using port 53 (requires root or capabilities):
resolver:
enabled: true
binding: 0.0.0.0:53
Then run with CAP_NET_BIND_SERVICE:
sudo setcap 'cap_net_bind_service=+ep' /usr/bin/wiretastix-daemon
Domain Configuration
Choose a domain that:
- Doesn’t conflict with internet domains (avoid .com, .net, etc.)
- Is easy to type and remember
- Follows DNS naming conventions
Recommended domains:
vpn.local(default)vpn.internalvpn.corp.example.comwg.example.com
Avoid:
- Public TLDs (.com, .org)
- Reserved TLDs (.localhost, .onion)
- Very long names
resolver:
enabled: true
domain: vpn.corp.example.com
Peers will resolve as:
john-laptop.vpn.corp.example.comjane-phone.vpn.corp.example.com
Concurrency Tuning
Adjust based on query load:
resolver:
enabled: true
concurrency: 10 # Higher for busy networks
Guidelines:
- Small networks (< 50 peers):
concurrency: 5 - Medium networks (50-200 peers):
concurrency: 10 - Large networks (200+ peers):
concurrency: 20
A query that can’t get a free concurrency slot within 2 seconds is dropped rather than queued forever, so a sustained flood of queries from an allowed source is bounded – it just starts losing queries once the resolver is saturated, instead of piling up unbounded work.
Monitor with:
# Check DNS query load
sudo journalctl -u wiretastix | grep -i "dns\|resolver"
Access Control
If you widen binding beyond loopback – for example, to let a real resolver on your internal network or VPN interface forward the zone to Wiretastix – restrict who can query it with acls:
resolver:
enabled: true
binding: 10.0.1.10:5353
acls:
- 10.0.1.0/24
- fd00::/64
acls is a list of CIDR blocks (IPv4 or IPv6). A source outside all listed blocks gets a standard DNS REFUSED response rather than being silently dropped, and that check happens before the query enters the concurrency queue, so a flood from a disallowed source can’t starve legitimate queries. Leaving acls empty (the default) allows queries from any source that can reach the resolver – the same behavior as before this option existed. A malformed CIDR entry fails config validation at daemon startup rather than being silently ignored.
This restricts who may reach the resolver, not what they can look up once allowed. Any source that passes the ACL check can still query any peer’s nickname and IP, not just its own – PTR queries carry an arbitrary IP chosen by the querier, and the resolver answers whichever one is asked. Use acls to gate access to the peer roster as a whole; it isn’t per-peer isolation.
Firewall Configuration
Allow DNS Queries
Using UFW
# From specific network
sudo ufw allow from 10.0.0.0/8 to any port 5353 proto udp
# From corporate DNS server
sudo ufw allow from 10.0.1.50 to any port 5353 proto udp
Using nftables
Add to /etc/nftables.conf:
define wiretastix_dns_if = ens192 # Internal interface
define wiretastix_dns_port = 5353
chain input {
type filter hook input priority 0; policy drop;
# ... other rules ...
# Allow DNS from internal network
iifname $wiretastix_dns_if udp dport $wiretastix_dns_port accept
# Or from specific DNS server
# ip saddr 10.0.1.50 udp dport $wiretastix_dns_port accept
}
Apply:
sudo nft -f /etc/nftables.conf
Security Considerations
Leave it disabled unless you need it: the resolver ships with enabled: false by design. Only turn it on if you’re actually using the DNS integration.
Use acls before reaching for firewall rules: if you need to widen binding past loopback, set acls to the source networks that should be allowed (see Access Control above) – this is enforced by the resolver itself, not by whatever else you have configured at the network layer.
Bind to internal interface only:
resolver:
enabled: true
binding: 10.0.1.10:5353 # Internal network only
Don’t expose to internet:
- DNS amplification attacks
- Information disclosure (peer names/IPs)
- Unauthorized access
Rate limiting (via firewall):
# Limit DNS queries per source
table inet wiretastix {
chain input {
udp dport 5353 limit rate 100/minute burst 50 packets accept
udp dport 5353 drop
}
}
DNS Forwarder Integration
Concept
Wiretastix DNS is authoritative for VPN peer names only. For full DNS functionality:
- Primary DNS server handles all queries
- Forwards
*.vpn.localqueries to Wiretastix - Resolves other queries normally (internet domains, corporate domains)
Client Query: github.com
→ Corporate DNS → Internet DNS → Returns IP
Client Query: john-laptop.vpn.local
→ Corporate DNS → Wiretastix DNS → Returns VPN IP
Bind9 Configuration
Edit /etc/bind/named.conf.local:
# Forward vpn.local zone to Wiretastix
zone "vpn.local" {
type forward;
forward only;
forwarders { 10.0.1.10 port 5353; };
};
# Reverse DNS for VPN network (10.0.100.0/24)
zone "100.0.10.in-addr.arpa" {
type forward;
forward only;
forwarders { 10.0.1.10 port 5353; };
};
# Reverse DNS for IPv6 VPN (fd00::/64 example)
# zone "0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f.ip6.arpa" {
# type forward;
# forward only;
# forwarders { 10.0.1.10 port 5353; };
# };
Reload Bind:
sudo systemctl reload bind9
# Or
sudo rndc reload
dnsmasq Configuration
Edit /etc/dnsmasq.conf:
# Forward vpn.local to Wiretastix
server=/vpn.local/10.0.1.10#5353
# Reverse DNS for 10.0.100.0/24
server=/100.0.10.in-addr.arpa/10.0.1.10#5353
# Reverse DNS for IPv6 (fd00::/64)
# server=/0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f.ip6.arpa/10.0.1.10#5353
Restart dnsmasq:
sudo systemctl restart dnsmasq
Unbound Configuration
Edit /etc/unbound/unbound.conf.d/wiretastix.conf:
server:
# ... other settings ...
forward-zone:
name: "vpn.local"
forward-addr: 10.0.1.10@5353
forward-zone:
name: "100.0.10.in-addr.arpa"
forward-addr: 10.0.1.10@5353
Reload Unbound:
sudo unbound-control reload
systemd-resolved Configuration
Create /etc/systemd/resolved.conf.d/wiretastix.conf:
[Resolve]
# Forward vpn.local to Wiretastix
DNS=10.0.1.10:5353
Domains=~vpn.local
Restart resolved:
sudo systemctl restart systemd-resolved
Windows DNS Server
- Open DNS Manager
- Right-click Conditional Forwarders → New Conditional Forwarder
- Domain:
vpn.local - IP address:
10.0.1.10(port must be 53, so Wiretastix needs to bind to port 53)
Note: Windows DNS doesn’t support custom ports. Wiretastix must use port 53.
Docker Internal DNS
If running in Docker, you can’t easily forward from host. Options:
Option 1: Expose Wiretastix DNS on host port 53:
# docker-compose.yml
services:
wiretastix:
ports:
- "53:53/udp" # Requires root or capabilities
Option 2: Use host DNS and configure forwarding there.
Option 3: Manual DNS entries in /etc/hosts on clients (not scalable).
Testing DNS Resolution
Test from Wiretastix Server
# Test A record (forward DNS)
dig @localhost -p 5353 john-laptop.vpn.local
# Expected output:
# ;; ANSWER SECTION:
# john-laptop.vpn.local. 5 IN A 10.0.100.5
# Test AAAA record (IPv6)
dig @localhost -p 5353 john-laptop.vpn.local AAAA
# Test PTR record (reverse DNS)
dig @localhost -p 5353 -x 10.0.100.5
# Expected output:
# ;; ANSWER SECTION:
# 5.100.0.10.in-addr.arpa. 5 IN PTR john-laptop.vpn.local.
Test from Client
After configuring DNS forwarder:
# Test A record (should go through forwarder)
dig john-laptop.vpn.local
# Test reverse DNS
dig -x 10.0.100.5
# Simple ping test
ping john-laptop.vpn.local
# Verify DNS server used
nslookup john-laptop.vpn.local
Using nslookup
# Query Wiretastix directly
nslookup john-laptop.vpn.local 10.0.1.10 -port=5353
# Query through forwarder
nslookup john-laptop.vpn.local
Using host
# A record
host john-laptop.vpn.local
# PTR record
host 10.0.100.5
Client Configuration
Linux Clients
Option 1: systemd-resolved
# Configure DNS for VPN interface
sudo resolvectl dns wg0 10.0.100.1
sudo resolvectl domain wg0 '~vpn.local'
# Verify
resolvectl status wg0
Add to WireGuard client config:
[Interface]
PrivateKey = ...
Address = 10.0.100.5/32
DNS = 10.0.100.1
# Or DNS = 10.0.1.10 (if accessible)
Option 2: /etc/resolv.conf
# Add nameserver (backup original first)
echo "nameserver 10.0.100.1" | sudo tee -a /etc/resolv.conf
echo "search vpn.local" | sudo tee -a /etc/resolv.conf
Warning: May be overwritten by DHCP. Use resolvconf or systemd-resolved instead.
macOS Clients
WireGuard client config:
[Interface]
PrivateKey = ...
Address = 10.0.100.5/32
DNS = 10.0.100.1, 8.8.8.8
# First DNS is Wiretastix (via VPN gateway)
# Second is fallback
Or use Network Preferences:
- System Preferences → Network
- Select VPN interface
- Advanced → DNS
- Add
10.0.100.1or10.0.1.10 - Add search domain:
vpn.local
Windows Clients
WireGuard client config:
[Interface]
PrivateKey = ...
Address = 10.0.100.5/32
DNS = 10.0.100.1
Or manually:
- Control Panel → Network → VPN adapter properties
- IPv4 Properties → Advanced → DNS
- Add
10.0.100.1or10.0.1.10 - DNS suffix:
vpn.local
iOS/Android Clients
In WireGuard app config:
[Interface]
PrivateKey = ...
Address = 10.0.100.5/32
DNS = 10.0.100.1
DNS settings applied automatically when VPN connects.
How DNS Records Are Generated
Peer Name to FQDN
Wiretastix constructs DNS names from peer names in the database:
Peer name: john-laptop (from database)
Domain: vpn.local (from config)
FQDN: john-laptop.vpn.local
Name sanitization:
- Spaces replaced with hyphens
- Special characters removed
- Lowercase conversion
- Max 63 characters per label
A/AAAA Record Resolution
When query received for john-laptop.vpn.local:
- Strip domain suffix →
john-laptop - Query database for peer with name
john-laptop - Return peer’s VPN IP addresses:
- A record: IPv4 address (10.0.100.5)
- AAAA record: IPv6 address (fd00::5)
- TTL: 5 seconds (short TTL for quick updates)
Multiple IPs:
- If peer has both IPv4 and IPv6, both records returned
- Client chooses which to use (typically IPv4 preferred)
PTR Record Resolution
When query received for 10.0.100.5:
- Receive query:
5.100.0.10.in-addr.arpa(reverse notation) - Convert to IP:
10.0.100.5 - Query database for peer with that IP
- Return peer name as PTR:
john-laptop.vpn.local
IPv6 PTR:
Query for fd00::5:
- Format:
5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f.ip6.arpa - Returns:
john-laptop.vpn.local
Advanced Configuration
DNS for Specific Groups
Currently, all peers resolve via DNS, and access control is source-network based (acls, see Access Control) rather than group-aware – there’s no way to say “only group X may query.” If a plain CIDR restriction via acls is enough (e.g., only the VPN subnet or a specific internal network may query), prefer that over nftables since it’s enforced natively by the resolver.
If you need actual per-group restriction, you need nftables to filter at the network layer instead, matching on the group’s peer IP set:
Option 1: Use nftables to filter DNS queries:
# Only allow group_engineering to query DNS
chain forward {
ip saddr @set_peers4_group_engineering ip daddr 10.0.1.10 udp dport 5353 accept
ip daddr 10.0.1.10 udp dport 5353 drop
}
Option 2: Run multiple Wiretastix instances with separate DNS servers.
Split-Horizon DNS
Provide different answers based on query source:
Not natively supported. Use external DNS server with views:
# Bind9 with views
view "internal" {
match-clients { 10.0.0.0/8; };
zone "example.com" {
file "/etc/bind/zones/example.com.internal";
};
};
view "external" {
match-clients { any; };
zone "example.com" {
file "/etc/bind/zones/example.com.external";
};
};
DNS Over TLS/HTTPS
Wiretastix DNS doesn’t support DoT/DoH. To add:
Use dnsdist as proxy:
# dnsdist forwards DoH/DoT to Wiretastix plain DNS
apt install dnsdist
# Configure dnsdist
# newServer({address="10.0.1.10:5353", name="wiretastix"})
Custom TTL
Currently hardcoded to 5 seconds. To change, modify source code:
// libs/gores/resolver.go
Hdr: dns.RR_Header{
Name: r.Question[0].Name,
Rrtype: r.Question[0].Qtype,
Class: dns.ClassINET,
Ttl: 300, // Change from 5 to 300 (5 minutes)
}
Rebuild and reinstall.
Monitoring and Logging
DNS Query Logging
Wiretastix logs DNS queries at debug level:
# Enable debug logging
# In wiretastix.yaml (if supported) or via environment
export LOG_LEVEL=debug
# View DNS logs
sudo journalctl -u wiretastix -f | grep -i dns
Look for:
Binding resolver to 0.0.0.0:5353Unhandled DNS request for #1/example.com(queries for non-VPN domains)- Error messages
Monitoring with Prometheus
Currently, Wiretastix doesn’t expose DNS-specific metrics. Future versions may include:
- Query count
- Query latency
- Cache hit rate
- Error rate
Performance Testing
# Benchmark DNS queries
for i in {1..100}; do
dig @localhost -p 5353 john-laptop.vpn.local +short
done
# Measure average latency
time dig @localhost -p 5353 john-laptop.vpn.local +short
Expected latency: < 10ms (local network)
Troubleshooting
DNS Not Responding
Symptom: DNS queries timeout.
Diagnosis:
# Test direct connection
dig @10.0.1.10 -p 5353 john-laptop.vpn.local
# Check if DNS server running
sudo ss -ulnp | grep 5353
# Check Wiretastix logs
sudo journalctl -u wiretastix | grep -i "resolver\|dns"
Common causes:
- Firewall blocking port 5353
- DNS not bound to accessible interface
- Wiretastix not running
- Wrong binding address
bindingwas invalid (empty, missing a port, or unparseable) and got silently forced back to127.0.0.1:5353– check the logs for aresolver.bindingwarning if queries from a non-loopback source stopped working after a config change
Solutions:
# Check binding in config
grep -A5 "resolver:" /etc/wiretastix/wiretastix.yaml
# Test firewall
sudo ufw allow 5353/udp
# Restart Wiretastix
sudo systemctl restart wiretastix
Name Resolution Fails
Symptom: Query returns NXDOMAIN (name not found).
Diagnosis:
# Verify peer exists in database
wiretastix-cli peer list | grep john-laptop
# Test query with exact name
dig @localhost -p 5353 john-laptop.vpn.local
Common causes:
- Peer name mismatch (spaces, case, special chars)
- Wrong domain in query
- Peer not in database
Solutions:
# Check exact peer name
wiretastix-cli peer show <peer-id>
# Verify domain config
grep "domain:" /etc/wiretastix/wiretastix.yaml
# Test with correct FQDN
dig @localhost -p 5353 <exact-peer-name>.<configured-domain>
Reverse DNS Not Working
Symptom: PTR queries return no results.
Diagnosis:
# Test PTR query
dig @localhost -p 5353 -x 10.0.100.5
# Check peer has that IP
wiretastix-cli peer list | grep 10.0.100.5
Common causes:
- IP not assigned to any peer
- Wrong reverse zone format in forwarder
Solutions:
# Verify peer IP
wiretastix-cli peer show <peer-id>
# Test direct PTR query
dig @localhost -p 5353 5.100.0.10.in-addr.arpa PTR
Forwarder Not Working
Symptom: Queries work directly to Wiretastix but not through forwarder.
Diagnosis:
# Test direct
dig @10.0.1.10 -p 5353 john-laptop.vpn.local
# Test through forwarder
dig @10.0.1.50 john-laptop.vpn.local
# Check forwarder logs
sudo journalctl -u bind9 -f
Common causes:
- Forwarder config error
- Firewall between forwarder and Wiretastix
- Wrong port in forwarder config (must use 5353)
Solutions:
# Verify forwarder config
sudo named-checkconf
# Test connectivity from forwarder
dig @10.0.1.10 -p 5353 john-laptop.vpn.local
# Check forwarder can reach Wiretastix
telnet 10.0.1.10 5353
Slow DNS Responses
Symptom: High latency on DNS queries.
Diagnosis:
# Time queries
time dig @localhost -p 5353 john-laptop.vpn.local
# Check database query performance
# (requires database monitoring)
Common causes:
- Database slow (many peers)
- Low concurrency setting
- Network latency
Solutions:
# Increase concurrency
resolver:
enabled: true
concurrency: 20 # Higher for busy networks
Multiple A/AAAA Records
Symptom: Query returns multiple IPs for one name.
Cause: Multiple peers with same name (shouldn’t happen in Wiretastix).
Diagnosis:
# Check for duplicate names
wiretastix-cli peer list | sort -k2 | uniq -d -f1
Solution: Rename duplicate peers.
Best Practices
1. Use Descriptive Peer Names
# Good names
john-laptop
jane-phone
webserver-prod
# Avoid
peer1
device
test
2. Configure DNS Forwarder
Don’t configure clients to query Wiretastix directly. Use forwarder:
- Centralized DNS management
- Caching
- Fallback for non-VPN queries
- Consistent behavior
3. Short TTL for Dynamic IPs
Wiretastix uses 5-second TTL. This ensures:
- IP changes reflected quickly
- Peer reconnections detected fast
- Minimal stale cache issues
4. Monitor DNS Health
# Regular health check
dig @10.0.1.10 -p 5353 health.vpn.local
# Create dummy peer "health" for monitoring
5. Secure DNS Access
- Leave
enabled: falseunless you actually use the DNS integration - Set
aclsto the source networks that should be allowed, once enabled - Bind to internal interface only
- Firewall rules to restrict access
- Don’t expose to internet
- Consider DNSSEC (external DNS) for validation
- Remember
aclsgates who can reach the resolver, not which peers’ records they can see – see Access Control
6. Document DNS Layout
Maintain documentation:
- VPN network ranges
- DNS domain
- Forwarder IPs
- Reverse zones
Example:
VPN Network: 10.0.100.0/24
DNS Domain: vpn.local
Wiretastix DNS: 10.0.1.10:5353
Forwarder: 10.0.1.50:53
Reverse Zone: 100.0.10.in-addr.arpa
7. Test After Changes
# After configuration changes, test:
dig @localhost -p 5353 test-peer.vpn.local
dig @forwarder test-peer.vpn.local
ping test-peer.vpn.local
Integration Examples
Example 1: Corporate Network
Setup:
- Corporate DNS: 10.0.1.50 (Bind9)
- Wiretastix: 10.0.1.10
- VPN Domain: vpn.corp.example.com
Bind9 Config:
zone "vpn.corp.example.com" {
type forward;
forward only;
forwarders { 10.0.1.10 port 5353; };
};
Client Config: DNS server 10.0.1.50 (automatically via DHCP)
Result: Clients resolve john-laptop.vpn.corp.example.com automatically.
Example 2: Home Lab
Setup:
- Wiretastix on 192.168.1.10
- Router (dnsmasq) at 192.168.1.1
dnsmasq Config:
server=/vpn.local/192.168.1.10#5353
Client Config: DNS from DHCP (router)
Result: Phones and laptops on VPN resolve peer names.
Example 3: Cloud Deployment
Setup:
- Wiretastix in cloud (10.50.0.10)
- No existing DNS infrastructure
- Direct client configuration
Wiretastix Config:
resolver:
enabled: true
binding: 10.50.0.10:53 # Port 53 for direct client use
domain: vpn.cloud
Client Config:
[Interface]
DNS = 10.50.0.10, 8.8.8.8
Result: Clients query Wiretastix directly, fallback to 8.8.8.8.
Summary
Wiretastix’s built-in DNS server provides automatic name resolution for VPN peers:
Key features:
- Automatic A/AAAA and PTR records
- Low TTL for dynamic updates
- Lightweight and fast
- Database-backed (always current)
Setup steps:
- Configure
resolverinwiretastix.yaml - Open firewall for DNS port
- Configure DNS forwarder (Bind, dnsmasq, Unbound)
- Test resolution
- Configure clients
Best practices:
- Use DNS forwarder, not direct queries
- Bind to internal interface
- Use descriptive peer names
- Monitor DNS health
- Document DNS layout
For related topics, see:
- Security Best Practices - DNS security
- NFTables Integration - Restrict DNS access by group
- FAQ & Troubleshooting - DNS issues