Securing IoT Devices at Home and in Your HomeLab: VLAN Segmentation, Firmware Monitoring, and Blocking Suspicious Connections

Security tutorial - IT technology blog
Security tutorial - IT technology blog

When Your Smart Bulb Becomes the Weakest Link

After my server got hit by SSH brute-force attacks at midnight, I started auditing everything on my network. I expected the threat to come from outside. It was already inside.

My home network had a smart TV, three IP cameras, a couple of smart plugs, and a NAS — all sitting on the same subnet as my workstation and HomeLab servers. Every one of them was a potential pivot point. One compromised camera hub, and an attacker scanning from inside could reach everything. No firewall to stop them.

If you run a HomeLab or just have a few smart home gadgets, this is a gap you probably haven’t closed yet. Here’s how to actually fix it.

Why IoT Devices Get Compromised So Easily

The root cause is surprisingly mundane. IoT devices are built for low cost and fast shipping — security is what gets cut when margins are thin and the deadline moves up.

  • Default credentials nobody changes: A quick Shodan search shows tens of thousands of cameras still running admin:admin years after purchase. Some brands hardcode credentials entirely.
  • Firmware that never gets updated: Most users never revisit the admin panel after initial setup. Patches exist — nobody installs them.
  • No outbound filtering: A compromised device can call home to a command-and-control server, exfiltrate data, or scan your internal network. Default router configurations won’t block any of it.
  • Flat network architecture: When every device shares the same subnet, lateral movement is trivial. One breach equals full internal access.

The worst part: you won’t notice. The 2016 Mirai botnet quietly infected 600,000+ devices and conscripted them into a DDoS army — owners had no idea until their ISP flagged the traffic. Modern variants do the same, running crypto miners or credential stealers silently in the background.

Three Approaches — And Why Two Fall Short

Option 1: Just Change the Default Password

Necessary, but not sufficient. It stops the most basic credential-stuffing attacks. Firmware vulnerabilities, lateral movement, and unauthorized outbound connections remain completely unaddressed. You’re locking the front door while leaving every window open.

Option 2: Firewall Rules Without Segmentation

Mid-range routers often let you create ACL rules between devices on a flat network. You can block your smart TV from reaching your NAS directly — better than nothing. But managing per-device rules on a shared subnet gets messy fast. One misconfigured rule silently breaks isolation, and you lose visibility into cross-device traffic patterns entirely.

Option 3: VLAN Segmentation + Outbound Filtering + Firmware Monitoring

This approach combines all three controls. Isolate IoT devices into their own VLAN, restrict outbound traffic to only what those devices actually need, and automate firmware version checks. You need a managed switch and a router with VLAN support — pfSense, OPNsense, or something like a UniFi gateway. The payoff: you know exactly what’s talking to what, and anything that breaks through one layer still hits another.

Option 3 wins on every metric — isolation, visibility, and scalability. Here’s how to build it.

The Layered IoT Defense Setup

Step 1: Create and Isolate an IoT VLAN

Using pfSense (or OPNsense — same concept), create a new VLAN for IoT traffic. I use VLAN tag 20 and subnet 192.168.20.0/24.

# pfSense: Interfaces → Assignments → VLANs → Add
# VLAN Tag: 20
# Parent Interface: your LAN port (e.g., igb1)
# Description: IoT_VLAN

Assign the interface, configure DHCP for 192.168.20.0/24, then add firewall rules. Two rules do the work:

# pfSense Firewall Rules — IoT_VLAN interface
# Rule 1: Block IoT → LAN (your main 192.168.1.0/24)
# Action: Block | Source: IoT_VLAN net | Destination: LAN net

# Rule 2: Allow IoT → Internet only
# Action: Pass | Source: IoT_VLAN net | Destination: !RFC1918
# pfSense's built-in RFC1918 alias covers 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16

On your managed switch, tag IoT device ports to VLAN 20:

# Managed switch CLI (Cisco IOS style — syntax varies by vendor)
vlan database
  vlan 20 name IoT
interface range GigabitEthernet0/5-8
  switchport mode access
  switchport access vlan 20

For Wi-Fi, create a separate SSID mapped to VLAN 20. On UniFi, that’s Networks → Create New Network → VLAN Only, then assign it to a new wireless network. IoT devices connect to that SSID and never see your main LAN.

Step 2: Automate Firmware Version Monitoring

Manual checks don’t work — you’ll forget within a week. A script that polls device APIs for version info and alerts on any change costs an hour to set up and runs forever after.

import requests
import smtplib
from email.mime.text import MIMEText

# Update this dict whenever you deliberately apply a firmware update
KNOWN_VERSIONS = {
    "camera_livingroom": "2.4.1",
    "smart_tv": "1.8.0",
}

def check_firmware(device_name, device_url, known_version):
    try:
        # verify=False is intentional — LAN devices often use self-signed certs
        resp = requests.get(device_url, timeout=5, verify=False)
        data = resp.json()
        live_version = data.get("firmware_version", "unknown")
        if live_version != known_version:
            return f"[ALERT] {device_name}: {known_version} → {live_version}"
        return None
    except Exception as e:
        return f"[ERROR] {device_name}: check failed ({e})"

def send_email_alert(alerts, smtp_host, smtp_port, username, password, to_addr):
    body = "\n".join(alerts)
    msg = MIMEText(body)
    msg["Subject"] = "Firmware version change detected"
    msg["From"] = username
    msg["To"] = to_addr
    with smtplib.SMTP_SSL(smtp_host, smtp_port) as server:
        server.login(username, password)
        server.sendmail(username, to_addr, msg.as_string())

if __name__ == "__main__":
    # Adjust endpoints to match your devices' actual API paths
    devices = [
        ("camera_livingroom", "http://192.168.20.5/api/version", KNOWN_VERSIONS["camera_livingroom"]),
        ("smart_tv", "http://192.168.20.10/status", KNOWN_VERSIONS["smart_tv"]),
    ]
    alerts = [check_firmware(n, u, v) for n, u, v in devices]
    alerts = [a for a in alerts if a]
    if alerts:
        print("\n".join(alerts))
        # Uncomment to enable email alerts:
        # send_email_alert(alerts, "smtp.gmail.com", 465, "[email protected]", "app_password", "[email protected]")

Schedule it as a daily cron job:

crontab -e
# Add this line:
0 8 * * * /usr/bin/python3 /home/user/scripts/check_firmware.py >> /var/log/firmware_check.log 2>&1

Not every device exposes a clean API — some require scraping the web UI, others need the manufacturer’s release page checked manually. Annoying to configure once. Automatic from then on.

Step 3: Catch Unusual Outbound Connections

VLAN isolation stops lateral movement, but IoT devices still reach the internet. A compromised device might beacon to a C2 server on port 4444, exfiltrate to an unfamiliar cloud IP, or run DNS queries at 3am that look nothing like legitimate traffic. Two methods catch this.

Method A — DNS sinkhole with Pi-hole: Point the IoT VLAN’s DHCP DNS at a Pi-hole instance. Any device querying a known malicious domain gets blocked and logged automatically.

# In pfSense, for the IoT_VLAN DHCP server:
# DNS Server 1: 192.168.20.2  (your Pi-hole IP on the IoT segment)

# On Pi-hole, tail the query log to watch live DNS requests from IoT devices:
pihole -t

# Or open the stats dashboard:
pihole -c

Method B — Packet capture baseline: Run tcpdump on a monitoring host for 24–48 hours after adding a new device. This builds a picture of what the device normally contacts. Future anomalies stand out clearly against that baseline.

# Capture outbound IoT traffic (covers all three RFC1918 ranges)
sudo tcpdump -i eth0 -nn \
  'src net 192.168.20.0/24 and dst net not (192.168.0.0/16 or 10.0.0.0/8 or 172.16.0.0/12)' \
  -w /tmp/iot_baseline.pcap

# After capture, summarize destination IPs by frequency:
# In tcpdump -nn output, field 5 is the destination IP:port
tcpdump -r /tmp/iot_baseline.pcap -nn \
  | awk '{print $5}' | cut -d. -f1-4 \
  | sort | uniq -c | sort -rn | head -20

A camera pinging an unknown IP on port 4444 at 3am isn’t checking for firmware updates. Cross-reference anything suspicious against VirusTotal or AbuseIPDB before deciding whether to block it.

The Checklist I Use for Every New IoT Device

Once the infrastructure is in place, adding a new device takes under ten minutes:

  1. Change default credentials before connecting to any network — offline if possible.
  2. Connect to the IoT SSID (VLAN 20) — never the main LAN.
  3. Add the device’s current firmware version to the monitoring script.
  4. Watch Pi-hole logs for 24 hours and block any suspicious domains immediately.
  5. Tighten outbound rules: most devices only need ports 80 and 443. Lock everything else at the VLAN firewall level.

Initial setup takes a few hours. After that, each new device costs minutes — the work compounds as your gadget collection grows.

After that midnight SSH incident, I’d rather put in those hours upfront than deal with an active breach at 2am.

The real takeaway: IoT security isn’t about trusting every device to behave. You can’t fix a manufacturer’s firmware decisions. It’s about designing your network so that when one device fails, the damage stays inside a single VLAN instead of spreading across your entire HomeLab. That’s what segmentation actually buys you.

Share: