Policy
Everything is blocked and logged unless a rule says otherwise. Each network may reach the internet; no network may reach another, except for a handful of named exceptions.
Principles#
- Default deny, logged. The first rule drops everything and logs it, so every surprise shows up in the SIEM.
- Every rule has a label. Logs say
allow_trusted_kodiordrop_all, not "rule 214", and the name survives when rules are renumbered. - Names, not addresses. Rules refer to tables such as
<admin_hosts>and<kodi>; an address changes in one place. - Allowed connections are logged too, so the SIEM can answer who talked to what. Rules that only produce heartbeat noise are the exception.
- Known noise is dropped quietly. Broadcast discovery and late TCP packets would otherwise bury the events that matter.
What may cross between networks#
| From | To | Ports | Why |
|---|---|---|---|
| Admin hosts | Cluster nodes, controller, access point, media server | 22/tcp | SSH management |
| Admin hosts | Controller | 11443/tcp, WebRTC | Controller web interface |
| Admin hosts | Kubernetes API | 6443/tcp | kubectl and Flux |
| Admin hosts | Ingress | 443/tcp | Web interfaces |
| Trusted Wi-Fi | Home Assistant | 8123/tcp | The phone app |
| Trusted Wi-Fi | Media server | 18080, 9090/tcp | Remote control |
| Home Assistant | IoT | any | Controlling devices |
| Access point | Controller | 8080/tcp, 3478, 5514/udp | Inform, STUN, device logs |
| Firewall | SIEM | 6514/tcp | Logs over TLS |
Guests appear in no row on purpose: they get an address, DNS and the internet, and nothing else.
In the configuration#
set block-policy drop
set skip on lo
trusted = "vlan10"
table <internal_nets> const { 192.168.1.0/24 192.168.2.0/24 192.168.3.0/24 \
192.168.4.0/24 192.168.5.0/24 192.168.10.0/24 \
192.168.20.0/24 192.168.30.0/24 }
table <kodi> const { 192.168.4.10 }
# Everything not allowed below is dropped and logged
block log all label "drop_all"
# Discovery chatter: dropped without logging, so alerts stay meaningful
block in quick on $internal to { 255.255.255.255 224.0.0.0/4 } \
label "drop_broadcast_multicast"
# Phones may use the media server's remote control
pass in log quick on $trusted inet proto tcp from $trusted:network \
to <kodi> port { 18080 9090 } label "allow_trusted_kodi"
# Each network may reach the internet, never another network
pass in log quick on $trusted inet from $trusted:network \
to ! <internal_nets> label "allow_trusted_internet"quickstops evaluation at the first match, so the order reads top to bottom like a checklist.to ! <internal_nets>is how "internet only" is expressed: anywhere except the home networks.