Homelab Rebuild Part 10: Turning Networks Into Boundaries
What this is about Link to heading
Since part 9, every device automatically lands in the right VLAN. That completes the separation at layer 2 โ and it is not yet a security boundary. A network of its own only means that traffic now passes the firewall. Whether the firewall lets it through is a different question.
In part 5 I did this once for a single VLAN, the one for telephony. By now there are twelve networks, and the temptation is strong to build one pattern and copy it everywhere.
That works for most devices and for some it doesn’t. This part is the pattern, the cases where it doesn’t fit, and a television that taught me why you look at the log before building a fix.
Where a rule belongs Link to heading
Two principles up front, because nearly every beginner’s mistake traces back to one of them.
The rule belongs on the interface where the packet arrives. That is the source VLAN, not the destination. If you want to allow access to the printer, the rule doesn’t go on the printer’s interface but on the workstation’s.
The firewall is stateful. There is no rule for the return path, and none is needed. If a connection is allowed, the reply packets are allowed with it.
Two flows, two directions โ and both rules sit on the side that initiates the connection.
This sounds trivial and it is, right up until you’re tired. The second most common mistake is related: the port goes in the destination port field, not the source port field. A client picks its source port at random from the high range; put 631 there and you’ve built a rule that practically never matches.
The pattern for devices whose job is the internet Link to heading
For the receiver, the console and guests, the rules look the same. Four of them, and the order is the whole trick.
Four rules. The third one is what this is actually about.
OPNsense evaluates top to bottom and the first matching rule wins. Everything else follows from that:
Rule 3 is the actual win. It catches everything internal. The device can’t reach the NAS, the workstation, the Proxmox host, or any of the other device VLANs.
Rule 4 has to sit below it. It passes whatever is left, wholesale. Put it on top and rule 3 becomes unreachable.
Rules 1 and 2 go right at the top, because the firewall itself has a private address. Without them, rule 3 would block DNS and time synchronisation too โ and a device without DNS looks exactly like a device without internet.
The aliases behind this are quickly explained: RFC1918 is the three private
ranges 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16. The exclamation mark
in front is negation, so “everything except”.
Any additional rule has to be sorted in above rule 4.
The case I did not build a shared VLAN for Link to heading
In part 1 the plan was to put the media player and the light controller in the same VLAN, because the ambient lighting feeds off the picture. Part 9 explains how that became two networks instead. Here is the rule that makes the difference:
| Protocol | Source | Destination | Port | Purpose |
|---|---|---|---|---|
| UDP | HTPC network | WLED address | 4048 | ambilight via DDP |
One line, above the internet rule, exactly one port to exactly one address.
The protocol choice is part of the story: 177 LEDs means 531 channels. E1.31 would need two universes for that plus the addressing arithmetic, while DDP fits it into a single packet โ and Hyperion’s “WLED” device type speaks DDP anyway.
The media player needs a few more exceptions than a pure consumption device:
| Protocol | Destination | Port | Purpose |
|---|---|---|---|
| UDP | WLED address | 4048 | ambilight |
| TCP | 10.0.1.2 |
4022 | IPTV via udpxy |
| TCP/UDP | HTPC address | domain | DNS to the firewall |
| UDP | !RFC1918 | ntp | time sync |
| TCP | any | 4070 | Spotify backend |
| TCP | !RFC1918 | 80, 443 | internet |
The first two rules point at private addresses and therefore have to sit
above the internet rule โ that one excludes everything private via the
negated RFC1918 and would otherwise never let them come into play.
Where the pattern doesn’t fit Link to heading
Consoles and guests: no port filter Link to heading
With rule 4 the temptation is to restrict it to 80 and 443. Better not.
Games consoles and phones need QUIC, push connections and shifting UDP ports. And
after connecting, Android checks over HTTP against connectivitycheck.gstatic.com
whether the network really reaches the internet. If that fails, the device
reports “no internet” โ and in many cases switches back to mobile data or another
WLAN by itself.
That is the most unpleasant failure mode there is: the rule is too tight, the device appears to work anyway, and the symptom presents as “the wifi is bad in here”.
So for those networks rule 4 stays open. The security isn’t in the port filter, it’s in rule 3.
The phone: the last rule inverts Link to heading
And then the case that shows the pattern is not a law.
The DECT phone in VLAN 31 has exactly one job: register with the phone system and carry calls. The trunks live on the system, not on the handset. So it needs no internet at all โ and the closing pass rule becomes a block.
Same scaffold, different last rule. The question is never “which pattern”, it’s “where does this device need to go”.
The nice part is the contrast with the neighbouring network. VLAN 30 with the phone system does need internet, that’s where the two SIP trunks live. VLAN 31 with the handset does not. Two adjacent networks, opposite final rule, and the reason lies not in the device type but in the job.
One detail I tripped over along the way: the phone showed up in the log every
second with requests on port 123. Its configuration held pool.ntp.org and
time.windows.com โ both outbound, both blocked. And a device that retries once
a second is a device that isn’t getting an answer.
Rather than building an exception outbound, it went the other way: point DHCP option 42 at the firewall, switch the phone to “time via DHCP”, and add a rule for UDP 123 to the firewall address. Now the phone has a time source and still has no internet.
The lesson: the repeat rate in the log is a diagnostic tool. A single block is an attempt; a block per second is a device that needs something.
The printer: the direction reverses Link to heading
The printer is the counterpart to everything above. It doesn’t initiate connections, it accepts them. Most of its rule set therefore doesn’t belong on its own interface at all:
- VLAN 20 โ printer: IPP on 631/tcp only, optionally 9100/tcp for raw printing and 161/udp for SNMP status queries
- Printer โ NAS: 445/tcp only if scan-to-share is wanted
- Printer โ internet: blocked
No mDNS reflector. The printer is added manually by IP, and that isn’t a compromise but the simpler solution: mDNS isn’t routed, and anyone wanting to carry it across VLAN boundaries builds themselves another service that also has to work.
That is the state of the plan, not of the implementation. Right now the printer interface carries an mDNS rule and nothing else โ which is precisely the thing that doesn’t work across VLAN boundaries anyway. Fixing that is busywork for a quiet evening, and I’m writing it down here so I don’t forget.
Ports you don’t know Link to heading
There is no list of ports for my receiver’s room-calibration software. For many devices there isn’t one.
The procedure is always the same:
- Create a broad rule โ source VLAN to the target address, all ports โ and switch on logging
- Run the application through completely, touching every function
- Read the ports actually used off the log
- Boil the rule down to those and remove the broad one
Step 2 is the important one: don’t just start it, play it to the end. Whatever you didn’t touch won’t be in the log, and that is exactly where the rule ends up too tight.
One detail that nearly sent me the wrong way: apps like this look for their device via SSDP, which is a broadcast. Broadcasts are not routed. Across a VLAN boundary the app finds nothing, no matter how open the rules are. The solution isn’t an SSDP relay, it’s the “enter address manually” field that almost every one of these apps has.
And one more consequence of the split: I need two rules for this. One app runs on the phone and therefore in the phone VLAN, the other on the workstation in VLAN 20. Two sources, two interfaces, two rules. In a catch-all VLAN it would have been one โ the price of the finer split, and a low one.
The fault I first looked for somewhere else Link to heading
My TV took the VLAN move without complaint. Since then its firmware updates didn’t work.
My theory was immediate, because the pattern is common: the device brings its
own DNS server. Plenty of consumer devices have 8.8.8.8 hardcoded and ignore
whatever they get over DHCP. I already had the fix in mind โ a NAT redirect
bending everything on port 53 back to my own firewall.
Then I looked at the log, filtered on port 53. Nothing. Not a single DNS attempt, not to 8.8.8.8, not anywhere.
What was there instead were dozens of blocked connections a minute, all on TCP 443: a handful of Google addresses and about a dozen AWS hosts in Ireland, with ever-changing source ports. The TV was hammering away once a second.
The cause was my own rule. It wasn’t restricted by port but by an alias of known update hosts. You assemble something like that once from a list you found online, and it works right up until the vendor moves. Binding cloud endpoints to an IP list doesn’t hold โ AWS addresses rotate, and a TV doesn’t only talk to its manufacturer.
The correction was one line: change the destination from the alias list to
!RFC1918, keep the ports at 80 and 443, set the protocol to TCP. Plus the
missing NTP rule, because without a roughly correct clock TLS handshakes fail โ
and that, again, looks like a network problem. The update then ran on the first
try.
I deliberately kept port 80. Certificate checks over OCSP and CRL run there, and unencrypted for good reason, or the check would be circular. Block 80 and, depending on the implementation, you hang in a timeout rather than failing cleanly. The security gain is essentially zero โ anyone allowed out on 443 can do the same things there.
The lesson, and it’s the most important one in this part: I had a plausible diagnosis, a matching fix and every value ready for the configuration. None of it was right. Two minutes of log would have saved me half an hour of configuring the wrong thing. It’s the same lesson as the end of part 8, just the other way round: there it was about checking what actually arrives. Here it’s about checking what actually goes out โ before you build.
What’s allowed to be in the log Link to heading
Once the rules are switched on, the block list fills up, and most of it isn’t a fault.
mDNS on 5353 to 224.0.0.251 and NetBIOS on 138 to the broadcast address.
Multicast and broadcast aren’t routed; that is the firewall correctly doing
nothing. I need neither, because everything has a fixed address.
“Default deny / state violation” straight after an apply. Those are lost states of running connections. Applying the rules drops parts of the state table, and packets from the middle of an existing connection then match no entry any more. Have the client reconnect, done. For me this showed up with internet radio on the media player, and I spent fifteen minutes hunting the wrong rule.
The entire “Automatically generated rules” block. Default deny, IPv6-ICMP per RFC 4890, anti-lockout for SSH and the web interface, the DHCP passes. OPNsense creates these on every interface. They look like far too much the first time you expand them, and they belong there.
Where I stand now Link to heading
The pattern is in place for the receiver, the console and guests. The media player has its own set with four exceptions. The TV has four rules instead of two since today and gets its updates again. The phone has DNS, time, the path to the phone system and nothing else.
What stays open, named rather than left out:
The printer. See above โ the plan exists, the rules don’t.
The rule from the phone to the phone system is still set to protocol * and
the whole of VLAN 30. It should be UDP to the system’s address, with SIP and the
RTP port range from its configuration. It works, it’s just wider than necessary โ
and that is exactly the kind of open item you never find, because nothing is
broken. I’ve never checked the reverse direction from 30 to 31 either.
The port filter on the receiver and the console. On the TV, restricting to 80 and 443 is defensible because the device has a clear job. On a games console it isn’t, see further up. That needs rethinking before the result catches up with me in six months as “the wifi is bad”.
Next step Link to heading
With the rules in place, the segmentation stands. The next building block is the one that comes in from outside: WireGuard on the firewall, so I don’t have to trust someone else’s wifi.
And it is deliberately only due now. A VPN client is just another device on a network โ and only now is there an answer to the question of which one.
Part of a series about rebuilding my home network. Status: September 2026. Questions, corrections and your own experiences are welcome in the comments.