Outbound Mullvad — deployment and operations
Deployed 2026-10-25; router: flint2 (OpenWrt 23.05.5); tunnel: wg_mullvad; WAN: eth1. This is separate from the VPS-relayed inbound wg_homelab tunnel. No secret WireGuard key, bot token, or private configuration backup belongs in this repository.
Scope and topology
flowchart LR
WAN[University WAN / eth1]
FW[Flint 2 / fw4 + PBR]
MV[wg_mullvad / Mullvad]
NAS[NAS CT 105 / 192.168.10.170]
TG[Telegram proxy CT 107 / 192.168.10.171]
MON[Uptime Kuma / monitor-01 192.168.10.158]
TR[Trusted VLAN 20 / 192.168.20.0/24]
MON -->|HTTPS CONNECT :3128| TG
NAS --> FW
TG --> FW
TR --> FW
FW -->|selective VPN egress| MV
FW -->|WAN mode for VLAN 20; default for other allowed traffic| WAN
| Source | VPN policy | Local exceptions / notes |
|---|---|---|
NAS 192.168.10.170 |
Always Mullvad | pbr.nas_local then pbr.nas_mullvad; eth1 guard |
Telegram proxy 192.168.10.171 |
Always Mullvad | pbr.telegram_local then pbr.telegram_mullvad; eth1 guard |
Trusted 192.168.20.0/24 |
Operator selectable | pbr.trusted_local then pbr.trusted_mullvad; VPN-mode eth1 guard and DNS DNAT |
| Other devices / router-generated traffic | Unchanged | WAN remains router's default; inbound wg_homelab independent |
pbr 1.1.6-22 uses fw4 nft-file mode and resolver_set=none, IPv6 PBR is disabled. Source-specific ignore exceptions cover 192.168.1.0/24, 192.168.10.0/24, 192.168.20.0/24, 192.168.30.0/24, 10.100.0.0/24 before the source-wide Mullvad route. The WireGuard public endpoint observed was 45.134.140.130:51820 and the verified Mullvad exit IPv4 was 45.134.140.138; addresses can change. Router university WAN address was 10.19.13.231 with public exit 158.93.6.19.
Trusted VLAN toggle
/usr/bin/trusted-vpn on Flint 2 operates only on Trusted VLAN 20:
trusted-vpn status
trusted-vpn on # requires Mullvad interface UP
trusted-vpn off # restore normal WAN routing and DNS
VPN mode: install /etc/nftables.d/40-trusted-mullvad-guard.nft from /root/trusted-mullvad-guard.template, validate/reload fw4, enable firewall.trusted_vpn_dns (DNAT TCP/UDP 53 to 192.168.10.171), then enable pbr.trusted_local and pbr.trusted_mullvad and restart PBR. Verify the effective guard exists before enabling PBR.
WAN mode: disable only the two Trusted PBR entries and restart PBR; disable Trusted DNS DNAT, reload fw4; remove the Trusted guard file and reload fw4; flush and delete any leftover inet fw4 trusted_mullvad_guard chain. The last cleanup is required in this deployment: removing an include file/reloading fw4 left a stale independently hooked chain. trusted-vpn status checks UCI and the live chain and reports INCONSISTENT when they disagree. If a transition fails, inspect/repair it before re-running; script has no atomic transaction/automatic rollback. Do not use a blanket nft flush ruleset or delete the entire inet fw4 table.
The guard currently blocks IPv4 from br-lan.20 / 192.168.20.0/24 out eth1, and IPv6 from br-lan.20 out eth1. This is not a general-purpose all-interface leak-proof policy: audit additional WAN interfaces, flow offloading, direct encrypted DNS, and startup ordering before claiming that. Router locally originated traffic is not protected by this forwarded-traffic guard.
# On Flint 2 — read-only state checks
trusted-vpn status
uci get pbr.trusted_mullvad.enabled
uci get firewall.trusted_vpn_dns.enabled
nft list chain inet fw4 trusted_mullvad_guard # expected only in VPN mode
nft list chain inet fw4 nas_mullvad_guard
nft list chain inet fw4 telegram_mullvad_guard
/etc/init.d/pbr status | grep -E 'Trusted VLAN|NAS Internet|Telegram Proxy Internet'
fw4 check
Trusted DNS path
The Trusted clients continue using router DHCP-advertised DNS 192.168.20.1; in VPN mode firewall.trusted_vpn_dns intercepts IPv4 TCP and UDP port 53 to DNS server 192.168.10.171, hosted in CT 107. The resolver forwards public DNS to Mullvad 10.64.0.1 and sends home.arpa to 192.168.10.1; local service names continue working. In WAN mode that DNAT is disabled and router dnsmasq uses university upstreams (10.127.10.25, 10.127.10.26 observed). See Telegram proxy and DNS. DoH/DoT, client DNS caches, and applications using proprietary DNS aren't comprehensively controlled by this port-53 redirect.
Deployment evidence and operational tests (2026-10-25)
| Test from Trusted VLAN XPS | Observed |
|---|---|
trusted-vpn on → public IPv4 |
45.134.140.138 (Mullvad) |
VPN-mode dig api.telegram.org, dig @192.168.20.1, dig @1.1.1.1 |
149.154.166.110 (correct Telegram IP, conventional DNS interception verified) |
getent ahostsv4 pve.home.arpa |
192.168.10.10 |
| Proxmox HTTPS | HTTP 200 |
IPv6 Internet via curl -6 |
Connection failed; not exhaustive IPv6 validation |
With ifdown wg_mullvad |
External HTTPS timed out; internal DNS and Proxmox HTTP 200 remained working |
After ifup wg_mullvad |
Mullvad exit 45.134.140.138 restored; immediate wg show may precede asynchronous device creation |
trusted-vpn off → public IPv4 |
158.93.6.19 (university WAN); router DNS again returned Umbrella sinkhole for Telegram |
trusted-vpn on then off after stale-chain fix |
Both routes verified, status in WAN mode showed guard INACTIVE, PBR=0, DNS DNAT=0 |
The manual outage test passed for the observed paths, but router cold-boot ordering and a complete WAN-path/flow-offload audit remain open. Leave those as outstanding work; no router reboot test was supplied.
Recovery and safeguards
- Preserve physical/local router access before modifying firewall, PBR or routing. Config backups from 2026-10-25 include
/root/vlan20-pre-mullvad-20261025-180009/and later firewall/PBR snapshots; these are router-local, not committed, and may contain sensitive material. - In VPN mode, if external DNS fails, test
dig @192.168.10.171 example.comfrom a Trusted client. Confirm CT 107dnsmasq, its DNS guard, and routerfirewall.trusted_telegram_dns(trusted→lab, TCP/UDP 53). - If public IP does not switch, inspect both Trusted policies (
enabled=1), PBR status andip -4 route show table pbr_wg_mullvad; never remove the kill switch to make a broken VPN appear to work. - If
trusted-vpn offsaysINCONSISTENT, check for the staleinet fw4 trusted_mullvad_guardchain. Only when WAN mode and guard-file removal are confirmed, selectivelynft flush chain inet fw4 trusted_mullvad_guardfollowed bynft delete chain inet fw4 trusted_mullvad_guard. - Never delete NAS/Telegram guards or disable
pbr.nas_mullvad/pbr.telegram_mullvadwhile operating the Trusted toggle.
Follow-ups
- [ ] Test router reboot in both modes, including transient WAN exposure during boot, startup ordering and PBR/firewall restoration.
- [ ] Audit firewall flow offloading and all possible WAN interfaces, rather than only
eth1. - [ ] Verify DNS privacy beyond classic UDP/TCP 53, and assess DoH/DoT bypass and IPv6 if upstream connectivity changes.
- [ ] Validate NAS and Telegram services again after a router reboot.