I run a FreeBSD router at home with pf providing firewalling and NAT for IPv4 internet access. It has two physical interfaces, one is connected to my vDSL modem and has been renamed wan0, while the other one has been renamed lan0 and is connected to a managed switch. I have two VLANs configured on the switch, numbered 1 and 128. The router-to-switch link carries both VLANs, 1 as untagged and 128 as tagged. The router has a vlan128 interface configured, and routes traffic between the two VLANs. It also provides DHCP service for the subnets on those VLANs. To make my pf configuration simpler, it includes '
Today I added a couple of new VLANs to my network, 32 and 64, configured their interfaces on the router and added the new subnets to the DHCP server configuration. To start with, devices connected to the new subnets were unable to connect to anything outside their own subnet or even to the router itself. Then I realised I had forgotten to add the new vlan32 and vlan64 interfaces to the '
But, I then also realised that although the hosts couldn't connect to anything outside their own subnets, they had somehow successfully obtained a DHCP lease from the router system, and I can't work out how.
My pf.conf is as follows. Can anyone see why these rules seem to be allowing DHCP to work, while everything else is blocked?
Update: I'm running the ISC Kea DHCP server and found the following in the documentation:
Update2: Also found this in the Kea docs:
set skip on { lo0, lan0, vlan128 }' so that packet filtering is not performed on those internal interfaces at all.Today I added a couple of new VLANs to my network, 32 and 64, configured their interfaces on the router and added the new subnets to the DHCP server configuration. To start with, devices connected to the new subnets were unable to connect to anything outside their own subnet or even to the router itself. Then I realised I had forgotten to add the new vlan32 and vlan64 interfaces to the '
set skip on { }' list, so everything was being blocked by the default "block all' rule in pf.But, I then also realised that although the hosts couldn't connect to anything outside their own subnets, they had somehow successfully obtained a DHCP lease from the router system, and I can't work out how.
My pf.conf is as follows. Can anyone see why these rules seem to be allowing DHCP to work, while everything else is blocked?
Code:
#### Tables ####
table <rfc1918> const { 10/8, 172.16/12, 192.168/16 }
#### Options ####
set block-policy drop
set loginterface wan0
set ruleset-optimization basic
set skip on { lo0, lan0, vlan128 }
set state-policy if-bound
#### Traffic Normalisation ####
scrub all fragment reassemble
#### Translation ####
# NAT LAN subnets behind public IP
nat on wan0 inet from (lan0:network) to any -> (wan0:0)
nat on wan0 inet from (vlan32:network) to any -> (wan0:0)
nat on wan0 inet from (vlan64:network) to any -> (wan0:0)
nat on wan0 inet from (vlan128:network) to any -> (wan0:0)
#### Packet Filtering ####
# Default block rule
block log all label "Default block rule"
# Block with return on WAN
block return in on wan0 label "Block incoming on WAN"
block return out log on wan0 label "Block outgoing on WAN"
# Block DrayTek modem chatter on WAN interface without logging it
block in quick on wan0 inet proto udp from 0.0.0.0 to 255.255.255.255 port 4944 label "Block status broadcasts from DrayTek modem"
block in quick on wan0 inet proto igmp from 192.168.2.1 to 224.0.0.1 label "Block IGMP from DrayTek modem"
# Allow connecting to DrayTek modem's web interface, must be placed before RFC1918 WAN block
pass out quick on wan0 inet proto tcp from 192.168.2.2 to 192.168.2.1 port 80
# Block RFC1918 on WAN
block quick on wan0 inet from <rfc1918> to any label "Block RFC1918 on WAN"
block quick on wan0 inet from any to <rfc1918> label "Block RFC1918 on WAN"
# Block localhost on any interface other than lo0
block log quick on ! lo0 inet from 127.0.0.0/8 to any
block log quick on ! lo0 inet from any to 127.0.0.0/8
# Block all IPv4 link-local
block quick inet from 169.254.0.0/16 to any label "Block IPv4 link-local"
block quick inet from any to 169.254.0.0/16 label "Block IPv4 link-local"
# Block TCP/UDP port 0
block quick inet proto {tcp,udp} from any port = 0 to any label "Block from tcp/udp port 0"
block quick inet proto {tcp,udp} from any to any port = 0 label "Block to tcp/udp port 0"
# Don't allow plain DNS out - hosts should be using local DNS server which uses DNS-over-TLS for upstream
block out log quick on wan0 proto {tcp,udp} from any to any port = 53 label "Block DNS queries direct to the Internet"
# Permit anything outbound from the firewall
pass out inet all flags S/SA keep state allow-opts label "Allow anything outbound from firewall on any interface"
Update: I'm running the ISC Kea DHCP server and found the following in the documentation:
Could this have anything to do with pf not blocking DHCP?On Linux and BSD system families the DHCP messages are sent and received over the raw sockets (using LPF and BPF) and all packet headers (including data link layer, IP, and UDP headers) are created and parsed by Kea, rather than by the system kernel.
Update2: Also found this in the Kea docs:
Case closed.Kea supports responding to directly connected clients which don’t have an address configured. This requires the server to inject the hardware address of the destination into the data link layer of the packet being sent to the client. The DHCPv4 server uses raw sockets to achieve this, and builds the entire IP/UDP stack for the outgoing packets. The downside of raw socket use, however, is that incoming and outgoing packets bypass the firewalls (e.g. iptables).