tutorials8 min read
Camera VLAN With No Internet Route: The Firewall Rules That Let Cameras Call Nobody
Your cameras can't phone home or leak creds to the internet, and only your NVR can reach them — with four firewall rules on OPNsense (or UniFi) that take an afternoon. Verified against current docs, 2026-09-16.
Put IP cameras on a dedicated VLAN with exactly one allowed flow — the NVR pulling RTSP — and deny everything else, including egress to the internet. Four rules in order (allow NVR→cams 554/tcp, block cams→LAN, block cams→WAN, default-deny), static IPs instead of discovery, verified with a ping that should fail.
Your cameras can't phone home or leak credentials to the internet, and only your NVR can reach them — for the price of one VLAN and four firewall rules. That's it. Two CISA advisories this week (Digital Watchdog VMAX and CareCam CM2507) make the case for why: one hands your NVR's admin password in plaintext to anyone who can reach it, the other streams live video with no login at all. Both boxes were sitting on flat LANs where "anyone who can reach it" means your NAS.
Full transparency: if you built Frigate with Home Assistant last week, the Frigate build guide already did a simplified version of the VLAN step. This is the standalone deep-dive on the firewall rules themselves — for any NVR or camera setup, Frigate or not — and it's where the actual security lives.
Before you start//
- A VLAN-capable firewall/router — an OPNsense box (this guide's primary path) or a UniFi Network gateway (alternate paths noted).
- A managed switch with trunk ports (or UniFi switches), plus your IP cameras and an NVR/Frigate host.
- Skill floor: basic subnetting — you know what
192.168.50.0/24means and where to find your router's config UI. - Time: ~2–4 hours including camera re-homing. More if you have a lot of cameras or a messy switch.
- Blast radius: one new VLAN, some switch port changes, and four new firewall rules (three on the camera interface, one allow rule on your LAN). Your LAN keeps working throughout — but the cameras' streams will drop while their ports move and their IPs change, so do it when nobody's watching the door cam live. Snapshot first: OPNsense →
System → Configuration → Backups(export a config backup, per the backups doc), or at minimum write down your existing rule set on the interfaces you'll touch. Rollback is deleting the new rules — but a snapshot makes "delete exactly what I added" trivial instead of archaeological. - Verified against: OPNsense docs, current as of 2026-09-16 on the 26.7 release line, and UniFi Network Application 10.6.x (current release line at time of writing; the VLAN UI paths below are stable across recent versions).
Step 1: Create the camera VLAN + subnet//
Give the cameras their own Layer 2 network with its own address space, so the firewall can talk about "the camera subnet" as a thing.
OPNsense path:
Interfaces → Devices → VLAN (add one entry)
Device: vlan0.<tag> e.g. vlan0.50
Parent: <your LAN uplink interface, e.g. igb0 or lagg0>
VLAN tag: 50 (pick an unused ID; embed it in the subnet below)
Interfaces → Assignments (assign vlan0.50 to a free interface slot)
Then create the network on it — per the VLAN and LAGG setup guide, each VLAN interface needs its own unique IPv4 network:
Interfaces → <camera interface> (edit)
IPv4 Configuration Type: Static IPv4
IPv4 Address: 192.168.50.1/24 (VLAN ID embedded in the third octet — good practice per the docs)
On the switch side, the trunk up to OPNsense carries VLAN 50 tagged, and each camera port becomes an access port with VLAN 50 untagged. The OPNsense guide has the exact port-mode table, and one warning worth stealing verbatim: don't mix tagged and untagged frames on the trunk between switch and firewall — you'll leak DHCP and broadcasts between VLANs.
UniFi path: in UniFi Network, Settings → Networks, create a new virtual network (per Ubiquiti's VLAN guide): name it cameras, set the VLAN ID and subnet (192.168.50.0/24), let UniFi run DHCP for it, then set each camera's switch port to that network as its native VLAN in Devices → [your switch] → Ports (Port Manager).
Why: a VLAN is just a boundary you can point at with firewall rules. Everything from here on references "the camera subnet" — without this step, every rule below has nowhere to live.
Step 2: Move the cameras onto it (and stop relying on discovery)//
- Wired cams: re-home each camera's switch port to the access/VLAN-50 config above. One at a time is fine; streams will drop and come back with new IPs.
- Wi-Fi cams: give them a dedicated SSID mapped to the camera network — UniFi: assign the
camerasnetwork to that SSID inSettings → Wi-Fi; on OPNsense-side APs, the OPNsense guide's port table shows the mixed-mode trunk (untagged management VLAN + tagged camera VLAN) access points expect.
Then do the part everyone skips: static DHCP reservations for every camera, and hard-code each RTSP URL in your NVR/Frigate config against those fixed IPs.
Why: ONVIF auto-discovery and most camera apps lean on multicast/mDNS, which do not cross VLAN boundaries by default — that's working as designed, since the whole point is isolation. If you don't pin static IPs, your cameras "disappear" from the NVR after the move and you'll chase ghosts. Static reservations + fixed RTSP URLs mean no discovery needed at all (this is also how Frigate's setup keeps working across the boundary).
Step 3: The four rules (the heart of this piece)//
Firewalls evaluate rules top to bottom and act on the first match — so order is the security. Get it wrong and a permissive rule higher up silently defeats every block below it. On OPNsense these live under Firewall → Rules, split across two tabs (which one goes where, right after the list):
Rule 1 ALLOW source: <NVR IP> dest: 192.168.50.0/24 tcp/554 (RTSP — the one flow that must work)
Rule 2 BLOCK source: 192.168.50.0/24 dest: LAN subnets (no lateral movement to your real devices)
Rule 3 BLOCK source: 192.168.50.0/24 dest: WAN / any (the no-egress rule — cameras can't phone home)
Rule 4 (default deny already catches the rest — OPNsense's inter-VLAN default is drop on a new interface; verify it in your rule list)
Now for the placement gotcha that kills this setup more often than any other: OPNsense filters traffic on the interface it arrives at (inbound direction, first match wins). Rule 1's traffic (NVR → camera RTSP) enters through your LAN interface, so put it in Firewall → Rules on the LAN tab. Rules 2 and 3 catch camera-originated traffic entering on the camera interface, so those live on the camera tab. All four rules together are what makes the cage; one rule on the wrong interface is the classic "RTSP allow exists but streams still die" bug.
Add management ports to Rule 1 only if you need them (e.g. tcp/80 for flashing firmware from the NVR host) and scope them to that one source IP — every extra port is a door. The mechanics of building these rules are in the OPNsense firewall docs; on UniFi, the same policy lives as gateway firewall rules / per-network isolation for the cameras network.
Why: notice what's not here — no rule lets a camera initiate anything that gets anywhere. The NVR reaches into the camera VLAN to pull streams; the cameras never originate outbound traffic that survives. That asymmetry is the entire design: a compromised camera can't reach your NAS, and it can't reach the vendor's update server either (manual firmware updates via LAN still work — you download the file on a workstation and flash through the web UI).
Step 4: Carve-outs, logged (optional but real)//
Some cameras misbehave without DNS or NTP — streams drift, timestamps go sideways. When one does, add one specific rule for that camera's IP to your resolver/NTP host on port 53/123, and write down why it exists. One rule per exception, never a blanket "allow cameras → LAN DNS" — the moment carve-outs start being lazy, you've rebuilt the flat network with extra steps.
Step 5: Verify it worked (non-negotiable)//
A rule set that looks right on screen but has one stale permissive rule above the blocks is worse than no rules — it gives false confidence. Prove the cage holds before calling this done:
- From a test laptop plugged into the camera VLAN (or a spare cam's web UI):
ping 8.8.8.8It should fail — no route to the internet. Meanwhileping 192.168.50.1works and the NVR pulls streams normally. - Watch the rule counters live. OPNsense shows per-rule hit counts in
Firewall → Rules; while recording is happening, check both tabs: on the LAN tab, Rule 1 (RTSP allow) should be climbing; on the camera tab, the WAN-egress block at zero hits and — the money shot — no camera traffic reaching anything else. - Let it record for a day. Check the NVR log overnight for "stream timeout" entries; any camera that dropped is either a discovery problem (Step 2) or needs a carve-out (Step 4).
Then document: which ports are on the camera VLAN, what each rule does, and the static IP table. Future-you will thank present-you during the first outage.
When it breaks//
- Cams lose NTP/cloud and drop streams — tell: "stream timeout" / intermittent gaps in NVR logs while pings to
.1work fine. Fix: add that camera's specific DNS/NTP carve-out (Step 4) and log it. Don't open the subnet up wholesale. - NVR can reach cameras on ping but no video — classic port/direction bug: you allowed the web UI port instead of RTSP
tcp/554, scoped Rule 1 to the wrong source IP, wrote it camera→NVR instead of NVR→camera, or parked Rule 1 on the camera tab (it has to be on LAN — see Step 3's placement note). Fix the rule's destination port and source; confirm it sits above Rules 2–3 in processing order. - Cameras still have internet — you've got a stale permissive rule above the blocks (a leftover "allow camera VLAN → any" from testing is the usual culprit). Find it in the live log, delete or demote it, and re-run the
ping 8.8.8.8check until it fails.
Rollback: disable/delete Rules 1–3 (or restore your pre-change config snapshot) — cameras fall back to LAN default-allow, streams resume on their old IPs if you also moved the switch ports back. Nothing in this tutorial modifies camera firmware or your LAN's core routing, so rollback is fast and boring by design.