Skip to content

Tor and DNSCrypt Configuration for OpenWRT Privacy Infrastructure

Overview

This document consolidates the configuration of Tor and DNSCrypt-proxy on OpenWRT devices to create a privacy-focused DNS infrastructure that routes encrypted DNS queries through the Tor network for maximum anonymization.

Architecture

Client Device → Dnsmasq (53) → DNSCrypt-proxy (5353) → Tor SOCKS (9050) → Tor Network → DNS Provider

Key Components

  1. Tor: Provides anonymization layer via SOCKS proxy
  2. DNSCrypt-proxy2: Encrypts DNS queries and routes them through Tor
  3. Dnsmasq: Local DNS resolver that forwards to DNSCrypt

Directory Structure

Configuration Paths on OpenWRT Devices

/etc/tor/
├── torrc                         # Main Tor configuration
└── custom                        # Custom includes (if needed)

/etc/dnscrypt-proxy2/             # DNSCrypt v2 (preferred)
├── dnscrypt-proxy.toml          # Main configuration
└── blocked-names.txt            # Blocklist

/etc/dnscrypt-proxy/              # DNSCrypt v1 (legacy)
└── dnscrypt-proxy.toml

/etc/config/
├── tor                          # UCI tor configuration
└── dhcp                         # UCI dnsmasq configuration

Installation

1. Install Required Packages

opkg update
opkg install tor
opkg install dnscrypt-proxy2  # or dnscrypt-proxy for v1

Optional: Web Interface

opkg install luci-app-dnscrypt-proxy

Configuration Files

Tor Configuration (/etc/tor/torrc)

# Basic Tor configuration for DNS and SOCKS proxy
SocksPort 0.0.0.0:9050           # SOCKS proxy for DNSCrypt
DNSPort 9053                     # DNS resolution port (optional direct use)
AutomapHostsOnResolve 1          # Automatic hostname mapping

# For transparent proxy (if needed):
# TransPort 0.0.0.0:9040
# TransPort [::]:9040

# For DNS-only operation add:
# VirtualAddrNetworkIPv4 172.16.0.0/12
# VirtualAddrNetworkIPv6 [fc00::]/8

DNSCrypt-proxy2 Configuration (/etc/dnscrypt-proxy2/dnscrypt-proxy.toml)

# Enterprise-grade encrypted DNS through Tor
# Master configuration for VPN/Tor workers

# DNS Servers (use multiple for redundancy)
server_names = ['cloudflare', 'quad9-dnscrypt-ip4-filter-pri', 'cloudflare-security']

# Listen address for local queries
listen_addresses = ['0.0.0.0:5353']
max_clients = 250

# Protocol support
ipv4_servers = true
ipv6_servers = false
dnscrypt_servers = true
doh_servers = true      # DNS over HTTPS
odoh_servers = false    # Oblivious DoH

# Tor Integration - CRITICAL
force_tcp = true
proxy = 'socks5://127.0.0.1:9050'  # Route through Tor SOCKS

# Cache Configuration
cache = true
cache_size = 4096
cache_min_ttl = 2400    # 40 minutes
cache_max_ttl = 86400   # 24 hours
cache_neg_min_ttl = 60
cache_neg_max_ttl = 600

# Privacy & Security Settings
block_ipv6 = true       # Prevent IPv6 leaks
require_dnssec = true   # Enforce DNSSEC validation
require_nolog = true    # Only use no-log servers
require_nofilter = false # Allow servers with filtering (for malware protection)
tls_disable_session_tickets = true
tls_cipher_suite = [52392, 49199]  # TLS 1.3 ciphers

# Fallback (emergency only, bypasses Tor!)
fallback_resolvers = ['1.1.1.1:53', '1.0.0.1:53']
ignore_system_dns = true

# Timeout settings
timeout = 5000          # 5 seconds
keepalive = 30

# Query logging
[query_log]
  file = '/var/log/dnscrypt-query.log'
  format = 'tsv'
  ignored_qtypes = ['DNSKEY', 'NS']

[nx_log]
  file = '/var/log/dnscrypt-nx.log'
  format = 'tsv'

# Blocked queries
[blocked_names]
  blocked_names_file = '/etc/dnscrypt-proxy2/blocked-names.txt'

# IP blocking
[blocked_ips]
  blocked_ips_file = '/etc/dnscrypt-proxy2/blocked-ips.txt'

# Resolver sources
[sources]
  [sources.'public-resolvers']
    urls = [
      'https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/public-resolvers.md',
      'https://download.dnscrypt.info/resolvers-list/v3/public-resolvers.md'
    ]
    cache_file = '/var/cache/dnscrypt-proxy/public-resolvers.md'
    minisign_key = 'RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3'
    refresh_delay = 72
    prefix = ''

[anonymized_dns]
  routes = [
    { server_name = '*', via = ['anon-cs-fr', 'anon-cs-ireland'] }
  ]
  skip_incompatible = true

Dnsmasq Configuration

Configure via UCI commands:

# Disable external resolvers
uci set dhcp.@dnsmasq[0].noresolv="1"

# Forward to DNSCrypt-proxy
uci del dhcp.@dnsmasq[0].server 2>/dev/null
uci add_list dhcp.@dnsmasq[0].server="127.0.0.1#5353"

# Disable rebind protection (needed for Tor)
uci set dhcp.@dnsmasq[0].rebind_protection='0'

# Commit changes
uci commit dhcp
service dnsmasq restart

Firewall Rules

For DNS-Only Through Tor

# Redirect all DNS queries to DNSCrypt
iptables -t nat -A PREROUTING -i br-lan -p udp --dport 53 -j REDIRECT --to-port 5353
iptables -t nat -A PREROUTING -i br-lan -p tcp --dport 53 -j REDIRECT --to-port 5353

# Block direct DNS to prevent leaks
iptables -A FORWARD -i br-lan -p udp --dport 53 -j DROP
iptables -A FORWARD -i br-lan -p tcp --dport 53 -j DROP

For Full Transparent Proxy (Optional)

# Redirect TCP traffic to Tor (except DNS)
iptables -t nat -A PREROUTING -i br-lan -p tcp ! --dport 53 -j REDIRECT --to-port 9040

# Allow only Tor traffic out
iptables -A FORWARD -i br-lan -o wan -m owner --uid-owner tor -j ACCEPT
iptables -A FORWARD -i br-lan -o wan -j DROP

Service Management

Starting Services

# Start Tor
service tor enable
service tor start

# Start DNSCrypt-proxy2
service dnscrypt-proxy enable
service dnscrypt-proxy start

# Restart dnsmasq
service dnsmasq restart

Checking Status

# Check if services are running
ps | grep -E 'tor|dnscrypt'

# Check Tor connectivity
curl --socks5 127.0.0.1:9050 https://check.torproject.org/api/ip

# Test DNS resolution
nslookup example.com 127.0.0.1#5353

Security Considerations

DNS Leak Prevention

  1. Stream Isolation Issues: The DNSPort doesn't perform stream isolation like SocksPort, which could potentially allow correlation attacks across different circuits.

  2. Exit Node DNS Behavior: Multiple circuits may use the same DNS servers at exit nodes, creating patterns that sophisticated traffic analysis could exploit.

  3. Mitigation Strategies:

  4. Use multiple DNSCrypt servers for redundancy
  5. Enable DNSSEC validation
  6. Use servers with no-logging policies
  7. Consider anonymized DNS relays
  8. Implement cache randomization

Traffic Correlation Risks

  • Timing Analysis: DNS query patterns can reveal browsing behavior
  • Query Size Patterns: Unique query combinations can fingerprint users
  • Mitigation: Use DNSCrypt's padding and implement query batching

Testing for Leaks

Test your configuration with: - https://check.torproject.org - https://browserleaks.com/dns - https://dnsleaktest.com - https://ipleak.net - https://mullvad.net/en/check

Expected Behavior: You should see Tor exit node IPs and their associated DNS servers, NOT your real IP or ISP's DNS.

Advanced Configuration

Multiple DNSCrypt Instances

For redundancy, configure multiple DNSCrypt instances:

# Instance A
uci set dnscrypt-proxy.dnsa.resolver="dnscrypt.eu-dk"
uci set dnscrypt-proxy.dnsa.address="127.0.0.2"
uci set dnscrypt-proxy.dnsa.port="5354"

# Instance B
uci set dnscrypt-proxy.dnsb.resolver="dnscrypt.eu-nl"
uci set dnscrypt-proxy.dnsb.address="127.0.0.3"
uci set dnscrypt-proxy.dnsb.port="5355"

# Configure dnsmasq with multiple upstreams
uci add_list dhcp.@dnsmasq[0].server="127.0.0.2#5354"
uci add_list dhcp.@dnsmasq[0].server="127.0.0.3#5355"

DNS-over-HTTPS (DoH) Alternative

If preferring DoH over DNSCrypt:

# In dnscrypt-proxy.toml
doh_servers = true
dnscrypt_servers = false
server_names = ['cloudflare-doh', 'quad9-doh']

Anonymized DNS Relays

Use relays to hide your server choice from the resolver:

[anonymized_dns]
routes = [
  { server_name = 'cloudflare', via = ['anon-cs-fr', 'anon-cs-ireland'] },
  { server_name = 'quad9-dnscrypt-ip4-filter-pri', via = ['anon-tiarap', 'anon-saldns01'] }
]
skip_incompatible = true

Troubleshooting

Common Issues

  1. DNSCrypt not starting:

    logread | grep dnscrypt
    dnscrypt-proxy -check -config /etc/dnscrypt-proxy2/dnscrypt-proxy.toml
    

  2. Tor connection issues:

    logread | grep tor
    tor --verify-config -f /etc/tor/torrc
    

  3. DNS resolution failing:

    # Test each component
    dig @127.0.0.1 -p 5353 example.com  # Test DNSCrypt
    dig @127.0.0.1 -p 9053 example.com  # Test Tor DNS
    

Performance Tuning

  1. Increase Tor circuits: Add to torrc:

    NumEntryGuards 3
    

  2. Optimize DNSCrypt cache:

    cache_size = 8192  # Increase for busy networks
    

  3. Reduce latency: Use geographically closer Tor entry guards

Monitoring

Logging Configuration

# Enable query logging (privacy warning!)
uci set dnscrypt-proxy.@dnscrypt-proxy[0].query_log='/var/log/dnscrypt-queries.log'

# Monitor in real-time
tail -f /var/log/dnscrypt-queries.log

Statistics

# DNSCrypt statistics
kill -USR1 $(pidof dnscrypt-proxy)

# Tor bandwidth usage
cat /proc/net/dev | grep -E 'tor|lo'

Deployment Script

Create deployment script at ./v1/scripts/deploy-dns-config.sh:

#!/bin/bash

MASTER_CONFIG="/home/bisenbek/projects/tinymachines/llarp/v1/configs"
TARGET_HOST="$1"

if [ -z "$TARGET_HOST" ]; then
    echo "Usage: $0 <hostname>"
    exit 1
fi

# Deploy Tor config
scp "$MASTER_CONFIG/tor/torrc" "root@$TARGET_HOST.lan:/etc/tor/torrc"

# Deploy DNSCrypt config
scp "$MASTER_CONFIG/dnscrypt/dnscrypt-proxy.toml" "root@$TARGET_HOST.lan:/etc/dnscrypt-proxy2/"

# Restart services
ssh "root@$TARGET_HOST.lan" "service tor restart; service dnscrypt-proxy restart; service dnsmasq restart"

echo "Configuration deployed to $TARGET_HOST"

References

Security Notes

⚠️ Important: While this configuration provides strong DNS privacy, remember: - Tor DNS doesn't provide perfect stream isolation - Traffic correlation attacks remain possible - This protects DNS queries only, not all traffic - For complete protection, use full transparent proxy or VPN - Regular security audits are essential - Monitor for DNS leaks regularly