Guide: how I isolated my Imou / Dahua (chinese) cameras to avoid them calling home
Disclaimer: non native english speaker here, so I asked an AI to summarize what I found and writte the post. seems I have to specify that, some people think that as it has been written by an ai, it's not relevant...
TL;DR: Cheap Chinese cloud cameras (IMOU / Dahua OEM, and others) often go into a reboot loop every few seconds the moment you block their internet access. Everyone assumes the camera "needs the cloud." In my case it didn't. It needed the time. Blocking the internet also blocked NTP, the camera couldn't get a clock, and that was what made it reboot. Serve NTP locally (and transparently intercept it), then firewall the camera off the internet, and it runs happily offline forever while your local NVR keeps recording. Here's the full debugging story and the fix.
The setup
- A hypervisor running a router/firewall VM (OPNsense) as the LAN gateway.
- A separate box doing DNS ad-blocking + DHCP.
- Home Assistant + Frigate recording the cameras over local RTSP.
- A handful of IMOU / Dahua-based IP cameras (plus some YI/Kami ones), all on the LAN.
Everything is private-range IPv4. I'll use these throughout:
10.0.0.100= OPNsense (gateway)10.0.0.94= my test PC10.0.0.232= the camera under test (a Dahua-based IMOU unit)
The problem
I wanted the cameras off the internet for privacy (no telemetry or images to the vendor cloud) while keeping local recording in Frigate. Frigate pulls RTSP over the LAN, so in theory it doesn't need the internet at all.
But every time I cut a camera off (by IP, by rule, by VLAN, didn't matter how), it would reboot every few seconds, tearing down the RTSP stream Frigate was reading. So "local only" was effectively unusable. Classic Chinese-cam behavior: if it can't call home, it panics.
First realization: Frigate isn't the problem, the camera's tantrum is
Frigate pulls RTSP on the LAN. That traffic doesn't even traverse the gateway, so the camera being offline should be invisible to Frigate. The only reason cutting the internet broke recording was the camera rebooting itself and dropping the stream. The real task wasn't "keep the cloud", it was "stop the camera from rebooting when the cloud is gone."
Hypotheses for the reboot
Cheap cameras reboot-on-no-internet for one of a few reasons, easiest to hardest:
- NTP / time sync fails at boot, firmware bails and restarts. Very common, easy to fix.
- DNS fails, interpreted as "no network."
- Cloud handshake fails: the firmware requires a successful connection to the vendor P2P servers.
The right move isn't to guess. It's to watch what the camera actually does and find the minimum that keeps it alive. Time to break out packet captures on the gateway.
Fixing candidate #1: serve time locally
OPNsense has a built-in NTP server (Services → Network Time). Enable it, pick the LAN interface, leave upstream pools so the firewall itself has correct time. Done, the gateway now answers NTP.
But that's only half of it. The camera won't magically ask my server; it targets hardcoded time servers on the internet. Since I couldn't reconfigure the camera, I transparently intercepted all NTP with a NAT redirect:
Firewall → NAT → Port Forward
Interface: LAN
Protocol: UDP
Destination: any
Destination port: 123 (NTP)
Redirect target IP: 10.0.0.100 (OPNsense itself)
Redirect target port: 123
Now any NTP query from any device, aimed anywhere, gets answered locally by the firewall.
Neat trick: how to prove the interception works
When you redirect like this, the reply reaches the client with the original destination IP spoofed back (so the client accepts it). Looking at the source IP is useless, it still says "Google" or "Ubuntu." The tell is the NTP payload's Reference-ID field, which identifies the responder's upstream.
I queried two different public NTP servers and captured the replies. Both came back with the exact same Reference-ID. That's impossible for two genuinely different servers, so both were really being answered by my firewall. Interception confirmed, and it was catching every subnet on the LAN.
The decisive test: cut the internet, watch the camera
Rule of thumb: block the camera from the internet but allow it to reach local/private networks (so Frigate/RTSP and local NTP still work).
Alias RFC1918 = 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
Firewall → Rules → LAN (order matters, both above the default allow):
1) PASS proto any source 10.0.0.232/32 dest RFC1918 (quick)
2) BLOCK proto any source 10.0.0.232/32 dest any (quick)
Then a continuous ping 10.0.0.232 in one window and a packet capture in another.
Gotcha #1: stateful firewall
At first the block "didn't work". The camera's keepalive to the cloud kept getting replies. The reason: pf is stateful, and the camera already had established connections open before I added the rule. New rules don't tear down existing states. The giveaway in the capture was subtle but clear: new connections were being dropped and retransmitted, while the old keepalive sailed through on its grandfathered state.
Fix: Firewall → Diagnostics → States, filter the camera IP, and kill the states (or reset the state table). Now every packet is re-evaluated against the new rules. Always do this after changing rules mid-connection.
The result
With states cleared, the cut was total. In the capture the camera was frantically trying to reach its cloud, rotating through a whole catalog of P2P/relay servers and ports, and getting nothing back. All of it died at the firewall. Nothing left toward the WAN. Zero telemetry.
And the camera... just kept running. No reboot. Ping rock-steady.
Gotcha #2: how to prove it didn't reboot (without touching it)
You don't need console access to know whether an appliance restarted. Two forensic signals in a capture:
- TCP
TS val(timestamp option) is a monotonic counter tied to uptime. Across several minutes of the block it kept climbing steadily. A reboot would reset it to a low value. It never did, so the device stayed up. - A reboot also produces an ARP burst + DHCP DISCOVER + boot sequence. I saw only lone periodic
who-has gatewayARPs (normal cache refreshes), never a boot storm.
So the camera was demonstrably alive the whole time. It just couldn't reach the cloud, and didn't care enough to restart. The missing piece all along was the clock: previously, cutting the internet also cut NTP, the camera couldn't get time and rebooted. With NTP served locally, it gets time even while fully firewalled, and stays up.
Bonus findings worth knowing
- These cameras ignore your DNS. Under stress mine issued DNS queries straight to hardcoded
8.8.8.8, not the DNS server handed out by DHCP. So domain-based blocking (Pi-hole/AdGuard blocklists) is useless here, the camera never asks your resolver. Firewall by IP is the only thing that works. - It is not streaming your video to the cloud 24/7. At rest the traffic was tiny: a lightweight keepalive every ~20s, a few hundred bytes. Actual video seems to only leave on demand, when you open the vendor app remotely. Still worth cutting (the keepalive is identity/online telemetry, and some firmwares upload event thumbnails), but it recalibrates the panic. It's not firehosing your living room to the far side of the world around the clock.
- Your local NVR doesn't need the internet at all. Frigate pulls RTSP over the LAN; that path never touches the gateway. Kill the reboot loop and it records with the camera 100% offline.
The recipe, condensed
- Enable an NTP server on your router/firewall.
- Transparently redirect all outbound UDP/123 to it (so cameras get time regardless of their hardcoded servers).
- Firewall the camera off the internet but allow RFC1918 (LAN/local) so RTSP + local NTP keep working.
- Reset firewall states after adding the rules.
- Verify: capture shows cloud attempts dying at the firewall;
TS valclimbing = no reboot; ping steady; NVR still recording.
Caveats / things I'm still chasing
- Firmware varies. Some units reboot on cloud loss regardless of time. If NTP-local isn't enough, the next levers are: try Reject instead of Block (a fast RST/ICMP unreachable is sometimes handled more gracefully than a silent timeout), or, worst case, fake the cloud handshake with a local listener (hard, proprietary protocol).
- Other brands differ. My YI/Kami cameras use a different cloud entirely; their reboot trigger may not be NTP. Test one at a time, don't assume the Dahua fix generalizes.
- This is WAN-blocking, not true isolation. If your LAN is flat (multiple subnets sharing one L2 segment), IP ranges alone don't isolate anything. A compromised cam can still talk to your trusted devices at layer 2. For real containment you want a dedicated IoT VLAN on a managed switch, with the firewall enforcing the boundary.
Hope this saves someone the two hours I spent staring at tcpdump. The headline lesson: when a cheap camera reboots on "no internet," suspect the clock before the cloud.
Disclaimer: non native english speaker here, post aided by AI.