> ## Content Index
> Fetch the complete content index at: https://blog.bajonczak.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Watching YouTube Anonymously: How I Route Media Traffic over Mullvad VPN with OPNsense
- URL: https://blog.bajonczak.com/watching-youtube-anonymously-how-i-route-media-traffic-over-mullvad-vpn-with-opnsense/
- Published: 2025-10-02T17:38:22.000Z
- Updated: 2026-08-13T04:03:43.000Z
- Description: Learn how to route only YouTube traffic through Mullvad VPN using OPNsense. With policy-based routing, clean DNS setup, and a Protectli Vault as reliable hardware, you can enjoy media anonymously without slowing down your entire network.
- Author: Sascha Bajonczak
- Tags: Security

I don’t want YouTube to know who I am or where I watch from. I want to enjoy videos without feeding the profile machine. Full-tunnel VPN for everything? Overkill. The smarter move is **policy-based routing**: only YouTube traffic goes through Mullvad; everything else goes out normally.

This guide shows exactly how I built that on **OPNsense** with **Mullvad (WireGuard)**. It’s practical, fast, and honest about the trade-offs (dynamic CDNs, DNS leaks, and “smart” TVs that hardcode DNS).

---

## My network in a nutshell

- **OPNsense** as the edge device (between ISP modem and my LAN) running on my protectli.
- **VLANs** for separation:
  - `LAN` → everyday clients
  - `MEDIA` → TV, streaming box, media PC (the targets for YouTube policy routing)
  - (optional) `GUEST` / `IOT`, etc.
- **WireGuard** client on OPNsense, connected to **Mullvad** → creates a VPN gateway I can use in rules.
- **Unbound DNS** on OPNsense as the central resolver. Client devices are forced to use OPNsense for DNS (to avoid leaks).

> You can apply the YouTube rule to all clients, or just the `MEDIA` VLAN. I prefer the VLAN approach: fewer surprises, easy to test.

---

## Why I Use a Protectli Box for OPNsense

Running OPNsense on consumer hardware is fine for testing, but if you’re serious about routing, VLANs, VPN, and policy-based routing, you’ll want something more reliable. I’ve been using a **Protectli Vault** as my OPNsense box — and honestly, it’s one of the best decisions I’ve made for my homelab.

It’s fanless (so completely silent), runs cool, and is built specifically for firewall/router use cases. WireGuard performance is excellent, and even with multiple VLANs, intrusion detection, and VPN tunnels, it doesn’t break a sweat.

👉 If you’re looking for a rock-solid device to run OPNsense or pfSense on, check out the [Protectli Vault on Amazon](https://amzn.to/4nuOnQ1?ref=blog.bajonczak.com) (affiliate link).

With this, you don’t have to worry about your firewall being the bottleneck when you push YouTube traffic through Mullvad or when you start segmenting your home network further.

---

## Prerequisites

- OPNsense installed and working.
- A Mullvad account and a WireGuard config (keys + endpoint).
- Admin access to OPNsense.
- Basic comfort with Firewall rules and NAT.

---

## Step-by-step setup

### 0) Housekeeping (worth the 2 minutes)

- **Update** OPNsense to a current release.
- **Backup**: `System → Configuration → Backups → Download configuration`.

---

### 1) Set up Mullvad (WireGuard) on OPNsense

1. **Install WireGuard plugin** if not present.
2. **Create a Local instance**:  
`VPN → WireGuard`
  - Add a **Local** with your private/public key pair (from Mullvad).
  - Set a **Tunnel Address**, e.g. `10.64.0.2/32` (Mullvad examples vary; follow the config Mullvad generated).
3. **Add Peer (Mullvad)**:
  - Public key = from Mullvad
  - Endpoint address/port = from Mullvad
  - Allowed IPs: `0.0.0.0/0` (we’ll steer only selected traffic with firewall rules later).
4. **Enable** the instance.
5. **Assign interface**:  
`Interfaces → Assignments` → add the WireGuard device (e.g. `wg0`) as an OPT interface; enable it, give it a name like `WG_MULLVAD`.
6. **Gateway**: OPNsense usually auto-creates it. If not, create one under  
`System → Routing → Gateways`, name it **`WG_MULLVAD_GW`**.
  - Tip: if the gateway monitor flaps, either set a stable monitor IP reachable via the tunnel or **disable monitoring** for this gateway.

---

### 2) Outbound NAT for the tunnel

Policy-based routing still needs NAT out the tunnel.

- Go to `Firewall → NAT → Outbound`.
- Switch to **Hybrid** (or **Manual**) mode.
- Add a rule:
  - **Interface:** `WG_MULLVAD`
  - **Source:** your `MEDIA` network (or `LAN` if you’ll apply policy there)
  - **Translation / Address:** **Interface address** (the WG interface)
- Save & Apply.

> If you already use automatic outbound NAT, Hybrid is safer: you add only what you need for WG while keeping defaults.

---

### 3) DNS hygiene (no leaks)

YouTube policy routing is pointless if your clients leak DNS to the ISP or public resolvers.

1. **Force clients to use OPNsense DNS**:
  - DHCP: hand out OPNsense’s IP as DNS server.
  - Then **block/redirect** any direct DNS (port 53) from clients to the internet.
    - Easiest: **NAT Port Forward** on `LAN`/`MEDIA`:
      - From: `LAN net` (or `MEDIA net`)
      - To: `any`, Port: `53 (TCP/UDP)`
      - **Redirect target IP:** Firewall / This firewall
      - **Redirect target port:** `53`  
            This silently hairpins rogue DNS to Unbound.
2. **Run Unbound** (`Services → Unbound DNS`) as your central resolver.
  - Optional: enable DNS-over-TLS upstreams or Mullvad DNS if you want **all** DNS to egress via the tunnel.
  - Minimal viable setup: keep Unbound local; the key is simply “no direct DNS from clients to WAN”.

> Smart TVs often hardcode DNS (8.8.8.8, etc.). The redirect above neutralizes that.

---

### 4) Build a YouTube destination alias

We’ll match on destination **domains** (OPNsense resolves them to IPs for the firewall table). Start small; you can extend later.

- `Firewall → Aliases → +`
  - **Type:** FQDN (or Host(s), depending on UI)
  - **Name:** `YOUTUBE_DEST`
  - **Entries (one per line):**youtube.com  
  www.youtube.com  
  m.youtube.com  
  youtubei.googleapis.com  
  ytimg.com  
  s.ytimg.com  
  r.youtube.com  
  googlevideo.com
  - Save.

> **Reality check:** YouTube/CDNs shift a lot. The key domains are **`googlevideo.com`** (actual media streams) and **`ytimg.com`** (assets). You may need to add more over time.

---

### 5) Policy rule: send YouTube to Mullvad

On the interface where the clients live (I use `MEDIA`):

- `Firewall → Rules → MEDIA` (or `LAN`)
- Add a **Pass** rule **above** your general allow rule:
  - **Source:** `MEDIA net` (or specific hosts)
  - **Destination:** **`YOUTUBE_DEST`** (the alias)
  - **Protocol:** any
  - **Advanced → Gateway:** **`WG_MULLVAD_GW`**
  - Description: `Route YouTube via Mullvad`
- Save & Apply.
- Make sure your default “allow to any” rule stays **below** this new rule.

> Order matters. pf evaluates top-down. If your generic allow fires first, your policy route won’t.

---

### 6) (Optional) A quick sanity blocker for DNS

On `MEDIA`, add a rule **above** everything that **blocks** dest port **53** to `! This Firewall` (negate “This Firewall”), so only the NAT-redirect to Unbound works. It’s belt-and-suspenders against weird client behavior.

---

### 7) Test & verify

- **Traceroute** from a client to `googlevideo.com`
  - Windows: `tracert googlevideo.com`
  - Linux/macOS: `traceroute googlevideo.com`  
  The path should go out through the Mullvad tunnel (you’ll typically see an extra hop consistent with WG egress).
- **OPNsense Live View**:  
`Firewall → Log Files → Live View` → filter by your rule description or by destination hostnames. You should see matches tagged with the WG gateway.
- **Packet Capture**:  
`Interfaces → Diagnostics → Packet Capture` on `WG_MULLVAD` → filter `host googlevideo.com` → start a YouTube stream and confirm you see packets.
- **Reality test**: start a video, then check your visible IP on a separate tab that loads media from YouTube (ads/CDN checks can help). For deeper checks, inspect connections on the client (e.g., `netstat`, `tcpdump`).

---

## How it works (under the hood)

- **Policy-based routing (pf “route-to”)**  
OPNsense uses FreeBSD’s `pf`. When a rule matches and you set a **Gateway**, pf adds a **route-to** directive for that state. That means: packets in this state are **pinned** to the specified gateway/interface — here, the WireGuard tunnel. Replies follow the same state, so back-and-forth stays in the tunnel.
- **FQDN aliases → IP tables**  
Your `YOUTUBE_DEST` alias is **not** “DNS at runtime per packet”. OPNsense **resolves** the FQDNs on a schedule and builds an IP table. If YouTube/CDN IPs move, the alias refresh must catch up. That’s why YouTube routing is “mostly right”, not perfect.
- **NAT on WG**  
Outbound NAT on the WG interface ensures your internal client IPs translate to the WG interface address when going out the tunnel. Without this, upstream would drop or misroute your traffic.
- **DNS leaks**  
If clients send DNS directly to the internet, YouTube (and others) can still see your real network location via DNS logs — even if the media stream rides the VPN. The NAT redirect (or explicit block) forces all client DNS to Unbound on OPNsense, which you control.
- **Why `googlevideo.com` matters**  
The actual video segments are almost always served from `*.googlevideo.com` CDN names. If you only route `youtube.com` and skip `googlevideo.com`, the watch page might go via VPN but the **video** won’t.

---

## Maintenance & gotchas

- **CDN churn**: Expect to occasionally add hostnames. Start with the list above; add regional variations if you see misses in logs.
- **Smart TV DNS**: Many TVs hardcode 8.8.8.8 or vendor DNS. The NAT redirect fixes this. If a TV also uses DoH/DoT, you may need additional blocks or force it into the `MEDIA` VLAN where egress is tightly controlled.
- **Gateway monitoring**: If the WG gateway shows as “down” but traffic still works, it’s just a monitor problem. Either set a known, reachable monitor via the tunnel or disable monitor for that gateway.
- **Performance**: WireGuard on OPNsense is fast enough for 4K on decent hardware. If things stutter, try a nearer Mullvad exit or different port.

```
youtube.com
www.youtube.com
m.youtube.com
youtubei.googleapis.com
ytimg.com
s.ytimg.com
r.youtube.com
googlevideo.com
```

Add more as you observe them in logs (regional edges, `*.c.youtube.com`, etc.).

---

## TL;DR

- Set up Mullvad (WireGuard) on OPNsense and get a `WG_MULLVAD_GW`.
- Force all client DNS to Unbound on OPNsense (block/redirect port 53).
- Create a `YOUTUBE_DEST` alias (FQDNs above).
- Add a top-ordered firewall rule on your client network that **routes** `Destination: YOUTUBE_DEST` via `WG_MULLVAD_GW`.
- Test with traceroute, Live View, and packet capture.

YouTube now plays over Mullvad. Everything else stays normal. Clean, targeted, and under your control.

*I keep a short overview of the practical posts that still get the most use here:* [*Technical Field Notes*](https://blog.bajonczak.com/technical-field-notes/)*.*