Skip to content

Latest commit

 

History

History
639 lines (467 loc) · 18.3 KB

File metadata and controls

639 lines (467 loc) · 18.3 KB

Deployment Guide

Step-by-step instructions for deploying the privacy router stack.

Prerequisites

Hardware Requirements

Component Minimum Recommended
CPU 1 core 2+ cores
RAM 512 MB 1 GB
Storage 1 GB 4+ GB
Network 2 interfaces 2 interfaces

Supported Platforms:

  • Raspberry Pi 4/5
  • x86/x64 mini PC
  • Virtual machine (any hypervisor)

Software Requirements

  • OpenWrt 23.05 or later (or compatible Linux)
  • AmneziaWG packages (kmod-amneziawg, amneziawg-tools)
  • AdGuard Home (latest)

Network Requirements

  • Internet connection via modem/ONT
  • Existing WiFi router (to convert to AP mode)
  • VPN provider account with WireGuard/AmneziaWG support

Deployment Options

Choose your deployment path:

Option Architecture Best For
A. Dedicated Hardware Router replacement Recommended - Network-wide protection, dedicated device
B. Virtual Machine Router replacement Homelab with existing hypervisor, 2 NICs available
C. Docker Container VPN gateway add-on Existing infrastructure, opt-in device protection

All options provide the same core protection: AmneziaWG obfuscation, AdGuard DNS filtering, kill switch, and watchdog recovery. The choice is about deployment architecture:

Options A & B (OpenWrt): Full router replacement. OpenWrt becomes your network's router - handles routing, DHCP, firewall, VPN. Existing router becomes WiFi access point only. All devices protected automatically.

Option C (Docker): VPN gateway add-on. Runs on existing Docker host (NAS, server, VM). Existing router keeps all functions. Devices opt-in by pointing gateway/DNS at container.

A/B: Modem → [OpenWrt Privacy Router] → WiFi AP → All Devices Protected
C:   Modem → [Existing Router] → Devices (some point to Docker container)

Default recommendation: OpenWrt (A or B) for most users - simpler architecture, network-wide protection. Docker (C) is appropriate when you want to add VPN capability alongside existing infrastructure without replacing your router.


Option A: Dedicated Hardware

A1. Install OpenWrt

For Raspberry Pi:

# Download OpenWrt image for your device
# https://openwrt.org/toh/raspberry_pi_foundation/raspberry_pi

# Write to SD card (Linux/macOS)
sudo dd if=openwrt-*.img of=/dev/sdX bs=4M status=progress

# Boot the Pi, connect via ethernet
ssh root@192.168.1.1

For x86 Mini PC:

# Download x86/64 image from openwrt.org
# Write to USB/SSD and boot

A2. Configure Network Interfaces

Edit /etc/config/network:

uci set network.lan=interface
uci set network.lan.device='br-lan'
uci set network.lan.proto='static'
uci set network.lan.ipaddr='192.168.1.1'  # Your gateway IP
uci set network.lan.netmask='255.255.255.0'

uci set network.wan=interface
uci set network.wan.device='eth0'  # Your WAN interface
uci set network.wan.proto='dhcp'

uci commit network

A3. Install AmneziaWG

Method 1: Pre-built packages (recommended)

# Check your OpenWrt version
cat /etc/openwrt_release

# Download packages from:
# https://github.com/amnezia-vpn/amneziawg-openwrt/releases

# Install dependencies
opkg update
opkg install kmod-crypto-lib-chacha20 kmod-crypto-lib-chacha20poly1305 \
             kmod-crypto-lib-curve25519 kmod-udptunnel4 kmod-udptunnel6

# Install AmneziaWG (adjust filename for your version)
opkg install /tmp/kmod-amneziawg_*.ipk
opkg install /tmp/amneziawg-tools_*.ipk

Method 2: Build from source

See: https://github.com/amnezia-vpn/amneziawg-openwrt

A4. Configure VPN Tunnel

Create config directory:

mkdir -p /etc/amneziawg

Create /etc/amneziawg/awg0.conf:

[Interface]
PrivateKey = YOUR_PRIVATE_KEY_HERE

# AmneziaWG obfuscation parameters
# These add CLIENT-SIDE obfuscation - servers don't need to support AmneziaWG.
# The defaults below work with ANY standard WireGuard server (Mullvad, IVPN, etc.)
# Source: wgtunnel compatibility mode (https://github.com/zaneschepke/wgtunnel)
Jc = 4
Jmin = 40
Jmax = 70
S1 = 0
S2 = 0
H1 = 1
H2 = 2
H3 = 3
H4 = 4

[Peer]
PublicKey = VPN_SERVER_PUBLIC_KEY
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = VPN_SERVER_IP:51820
PersistentKeepalive = 25

Set permissions:

chmod 600 /etc/amneziawg/awg0.conf

A5. Configure Firewall

Create VPN zone and kill switch:

# Create VPN zone
uci set firewall.vpn=zone
uci set firewall.vpn.name='vpn'
uci set firewall.vpn.device='awg0'
uci set firewall.vpn.input='REJECT'
uci set firewall.vpn.output='ACCEPT'
uci set firewall.vpn.forward='REJECT'
uci set firewall.vpn.masq='1'
uci set firewall.vpn.mtu_fix='1'

# Allow LAN to VPN forwarding ONLY (kill switch)
uci set firewall.lan_vpn=forwarding
uci set firewall.lan_vpn.src='lan'
uci set firewall.lan_vpn.dest='vpn'

# Ensure NO lan->wan forwarding exists (verify kill switch)
# This should already be the default - no lan->wan rule

uci commit firewall

A6. Install Obfuscation Profiles (Optional)

For environments with deep packet inspection, install the profile library:

# Copy profile library
cp scripts/awg-profiles.sh /etc/amneziawg/awg-profiles.sh
chmod +x /etc/amneziawg/awg-profiles.sh

Available profiles:

Profile DPI Resistance Use Case
basic Medium Home ISP, light censorship (default)
quic High Moderate DPI, traffic appears as HTTP/3
dns Medium Environments where DNS traffic is allowed
sip Medium Environments where VoIP traffic is common
stealth Maximum Heavy censorship, aggressive DPI

Set the profile in your scripts (watchdog and hotplug):

AWG_PROFILE="quic"  # or dns, sip, stealth

A7. Install Startup Scripts and Server Failover

Create server failover config:

# Create server list for watchdog failover
cat > /etc/amneziawg/servers.conf << 'EOF'
# Format: NAME  ENDPOINT_IP  PORT  PUBLIC_KEY
# Each server has its OWN public key (Mullvad keys are unique per server, even same-city) —
# specify a real key for every server. "-" only reuses the base awg0.conf key; do NOT use it
# for failover servers (the endpoint switches but the key doesn't, so the handshake silently
# fails). Get each server's IP + key from your provider.

# Example (each server its own key; RFC 5737 doc IPs — replace with real values):
# us-lax-wg-001   198.51.100.10   51820   LAX_001_PUBLIC_KEY
# us-sjc-wg-001   198.51.100.12   51820   SJC_001_PUBLIC_KEY
# us-sea-wg-001   198.51.100.14   51820   SEA_001_PUBLIC_KEY

# Add your servers here:
EOF

# Edit with your provider's servers:
vi /etc/amneziawg/servers.conf

Tip: Use 3-5 servers, ideally spread across a few cities for resilience (a single-city/provider outage still has a path out). The watchdog tries the same server first on failure, then cycles through the list. Give each server its own public key in servers.conf — see openwrt/amneziawg/servers.conf.example.

Copy startup scripts:

# Copy watchdog script
cp openwrt/amneziawg/awg-watchdog.sh /etc/awg-watchdog.sh
chmod +x /etc/awg-watchdog.sh

# Edit watchdog with your values (REQUIRED):
vi /etc/awg-watchdog.sh
# Set: VPN_IP (must match Address in your provider's WireGuard config)

# Copy hotplug script (auto-starts VPN on WAN up)
mkdir -p /etc/hotplug.d/iface
cp openwrt/amneziawg/99-awg.hotplug /etc/hotplug.d/iface/99-awg
chmod +x /etc/hotplug.d/iface/99-awg

# Edit hotplug script with same VPN_IP:
vi /etc/hotplug.d/iface/99-awg
# Set: VPN_IP

For OpenWrt (init.d):

# Install init script for boot persistence
cp scripts/awg-watchdog.init /etc/init.d/awg-watchdog
chmod +x /etc/init.d/awg-watchdog

# Enable at boot
/etc/init.d/awg-watchdog enable

# Start now
/etc/init.d/awg-watchdog start

# Verify running
ps | grep awg-watchdog

For standard Linux (systemd):

# Copy systemd service files
sudo cp scripts/awg-watchdog.service /etc/systemd/system/
sudo cp scripts/adguardhome.service /etc/systemd/system/

# Reload systemd
sudo systemctl daemon-reload

# Enable and start services
sudo systemctl enable awg-watchdog adguardhome
sudo systemctl start awg-watchdog adguardhome

# Verify running
sudo systemctl status awg-watchdog
sudo systemctl status adguardhome

Configuration values you need:

Variable Description Where to Find
VPN_IP Your VPN internal IP (e.g., 10.64.x.x) Provider's WireGuard config (Address field)
servers.conf Server endpoints for failover Provider's server list page

IMPORTANT: VPN_IP must exactly match the Address from your provider's WireGuard config. A mismatch is the #1 cause of watchdog crash-loops — the tunnel starts but connectivity checks fail, triggering infinite restarts. The WAN gateway is auto-detected.

A8. Test VPN Manually

# Create interface
ip link add dev awg0 type amneziawg

# Apply config (command is "awg" on OpenWrt, "amneziawg" if built from source)
awg setconf awg0 /etc/amneziawg/awg0.conf

# Add address (use your VPN internal IP)
ip address add 10.x.x.x/32 dev awg0

# Bring up
ip link set up dev awg0

# Add routes (use your VPN server IP and WAN gateway)
ip route add VPN_SERVER_IP via WAN_GATEWAY
ip route del default 2>/dev/null
ip route add default dev awg0

# Test
curl https://am.i.mullvad.net/ip
# Should show VPN exit IP, not your real IP

A9. Deploy AdGuard Home

Option 1: On OpenWrt (limited resources)

# Download AdGuard Home binary
cd /tmp
wget https://static.adguard.com/adguardhome/release/AdGuardHome_linux_arm64.tar.gz
tar xzf AdGuardHome_linux_arm64.tar.gz
mv AdGuardHome/AdGuardHome /usr/bin/

# Run setup
AdGuardHome -s install

# Access web UI at http://router-ip:3000

Option 2: Separate device/container (recommended)

Deploy AdGuard Home on a separate LXC container, VM, or device:

# On Debian/Ubuntu
curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -v

# Configure at http://adguard-ip:3000

A10. Configure DHCP to Push AdGuard DNS

On OpenWrt:

# Push AdGuard as DNS server to clients
uci add_list dhcp.lan.dhcp_option='6,ADGUARD_IP'
uci commit dhcp
/etc/init.d/dnsmasq restart

A11. Configure AdGuard Upstream DNS

In AdGuard web UI (Settings → DNS Settings → Upstream DNS):

# Use DNS-over-HTTPS to your VPN provider
# Mullvad: https://adblock.dns.mullvad.net/dns-query
# IVPN: https://dns.ivpn.net/dns-query
# Proton: https://dns.protonvpn.net/dns-query
https://YOUR_PROVIDER_DOH_URL/dns-query

# Or use VPN provider's plain DNS (if inside VPN tunnel)
# Mullvad: 100.64.0.4 | IVPN: 10.0.254.1 | Proton: 10.2.0.1
VPN_PROVIDER_DNS_IP

Enable:

  • DNSSEC
  • Parallel requests
  • Cache enabled

A12. Security Hardening

# Disable IPv6 (prevents leaks)
uci set network.wan.ipv6='0'
uci set network.lan.ipv6='0'
uci delete network.wan6 2>/dev/null
uci commit network

# Disable IPv6 in kernel
echo 'net.ipv6.conf.all.disable_ipv6=1' >> /etc/sysctl.conf
echo 'net.ipv6.conf.default.disable_ipv6=1' >> /etc/sysctl.conf
sysctl -p

# Restrict SSH to LAN only
uci set dropbear.@dropbear[0].Interface='lan'
uci commit dropbear
/etc/init.d/dropbear restart

# Enable HTTPS for web UI (optional)
opkg update
opkg install luci-ssl
uci set uhttpd.main.redirect_https='1'
uci commit uhttpd
/etc/init.d/uhttpd restart

A12b. TCP Buffer Tuning (High-Latency Links)

If your VPN server is geographically distant (>100ms latency), tune TCP buffers to avoid single-stream speed bottlenecks:

cat >> /etc/sysctl.conf << 'EOF'
# TCP buffer tuning for high-latency VPN links
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 131072 16777216
net.ipv4.tcp_wmem = 4096 16384 16777216
EOF
sysctl -p

Skip this if your VPN server is nearby (<50ms) or WAN is <50 Mbps. See CONFIGURATION.md for details.

A13. Final Cutover

  1. Set existing router to AP mode

    • Disable DHCP
    • Disable routing/NAT
    • Set to bridge mode
    • Assign static IP (e.g., 192.168.1.4)
  2. Connect cables

    • Modem → OpenWrt WAN port
    • OpenWrt LAN port → WiFi AP
  3. Verify

    # Check VPN
    curl https://am.i.mullvad.net/ip
    
    # Check DNS (should return 0.0.0.0)
    nslookup doubleclick.net
    
    # Check kill switch (disconnect VPN, verify no internet)
    ip link set awg0 down
    curl google.com  # Should fail
    ip link set awg0 up

Option B: Virtual Machine

For homelab users with existing hypervisors (Proxmox, ESXi, Hyper-V, etc.).

B1. Create OpenWrt VM

General requirements:

  • 512MB+ RAM, 1-2 vCPUs
  • Two virtual network interfaces (WAN and LAN)
  • Download OpenWrt x86/64 image from openwrt.org

Network configuration:

  • NIC 1 → Bridge to WAN network (connected to modem)
  • NIC 2 → Bridge to LAN network (connected to your devices)

Steps:

  1. Download OpenWrt x86/64 combined image
  2. Create VM with 2 NICs bridged appropriately
  3. Import/attach the OpenWrt disk image
  4. Boot and continue from A2

B2. Deploy AdGuard

Deploy AdGuard Home in a separate VM or container on the same hypervisor:

# On Debian/Ubuntu VM or container
curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -v

Ensure the AdGuard VM/container is on the LAN bridge so it can serve DNS to clients.

Boot sequencing (important): AdGuard must start AFTER OpenWrt's DHCP server is ready. Without this, AdGuard may fail to get an IP on boot, silently breaking DNS for the entire network.

Recommended: Use static IP for AdGuard (eliminates DHCP race condition):

# Inside the AdGuard VM/container
cat > /etc/systemd/network/eth0.network << 'EOF'
[Match]
Name=eth0

[Network]
Address=192.168.1.5/24
Gateway=192.168.1.1
DNS=127.0.0.1
EOF

systemctl restart systemd-networkd

If using DHCP: Add a startup delay so OpenWrt's dnsmasq is ready first:

  • Proxmox: pct set <CTID> -startup order=2,up=30 (container starts 30s after OpenWrt)
  • Other hypervisors: Configure equivalent boot ordering with delay

B3. Continue Setup

Continue from A4 onwards - the configuration is identical to dedicated hardware once OpenWrt is running.


Option C: Docker Container

VPN gateway add-on for users with existing Docker infrastructure who want to add VPN capability without replacing their router.

When to choose Docker:

  • You have an existing Docker host (NAS, server, VM)
  • You want to keep your current router's functions
  • You only need some devices protected (opt-in model)
  • You're adding VPN to an existing infrastructure

When to choose OpenWrt instead:

  • You want network-wide automatic protection
  • You have dedicated hardware available (Pi, mini-PC)
  • You prefer a simpler single-device architecture

AI-assisted setup: If using an AI assistant (Claude, GPT, etc.), give it access to the docker/ folder - it can guide you through macvlan networking and container configuration.

C1. Overview

The Docker deployment provides:

  • AmneziaWG VPN client with kill switch
  • AdGuard Home for DNS filtering
  • macvlan networking for LAN gateway mode
  • Auto-recovery watchdog and health checks
  • Comprehensive test suite (10 tests including kill switch verification)
┌────────────────────────────────────────────────────┐
│              Docker Host (Linux)                   │
│  ┌──────────────────────────────────────────────┐  │
│  │         privacy-router container             │  │
│  │   AmneziaWG + AdGuard Home + Kill Switch     │  │
│  └──────────────────┬───────────────────────────┘  │
│                     │ macvlan (192.168.1.250)      │
└─────────────────────┼──────────────────────────────┘
                      │
           LAN: 192.168.1.0/24

C2. Prerequisites

  • Docker Engine 24.0+ with Compose V2
  • Linux host with kernel 5.6+ (for WireGuard)
  • LAN interface available for macvlan
  • VPN subscription with WireGuard/AmneziaWG support

C3. Quick Start

cd docker/

# Copy templates
cp .env.example .env
cp config/awg0.conf.example config/awg0.conf

# Edit with your values
nano .env                    # Set VPN_IP, VPN_ENDPOINT_IP, network config
nano config/awg0.conf        # Set PrivateKey, PublicKey

# Deploy
docker compose up -d

# Verify (quick check)
docker exec privacy-router /opt/scripts/quick-test.sh

# Full validation (includes kill switch test)
docker exec privacy-router /opt/scripts/test-suite.sh

C4. Configure LAN Clients

Point devices to use the container as gateway and DNS:

Setting Value
Gateway 192.168.1.250 (CONTAINER_LAN_IP)
DNS 192.168.1.250

Or configure your router's DHCP to distribute these settings.

C5. Full Documentation

See docker/README.md for:

  • Complete configuration reference
  • Environment variables
  • Troubleshooting guide
  • Security notes

Post-Deployment Checklist

  • VPN connected (check exit IP matches VPN provider)
  • Kill switch working (no internet when VPN down)
  • DNS resolving through AdGuard
  • Ads blocked (nslookup doubleclick.net returns 0.0.0.0)
  • No DNS leak (bootstrap_dns uses VPN provider DNS, not public)
  • IPv6 disabled (no AAAA records returned)
  • SSH restricted to LAN
  • All services start on boot (power cycle and verify)
  • Watchdog running and servers.conf populated
  • VPN_IP in scripts matches provider config Address field
  • Scripts not corrupted (head -1 shows #!/bin/sh, no \!)
  • Bypass rules use option proto 'all' (if using bypass)
  • Existing router in AP mode
  • TCP buffers tuned (if VPN latency >100ms)

Next Steps