Stuck configuring pf

Hello all, I have a FreeBSD box being used as a router. My network is relatively simple. Just between the internet and my 10.0.0.0/8 network.

Here is my configuration file for pf. I'm a bit stuck I'm not able to get an internet connection but I am able to access the network locally. I'm trying to deny everything unless explicitly allowed.

Please see below

Code:
# Macros

int_if = 're0'                                                          # internal interface
ext_if = 're1'                                                          # external interface

internal_network = '10.0.0.0/8'                                         # internal network address

# Options
set block-policy drop                                                   # drop packets on block
set skip on lo0                                                         # skip filtering rules on loopback

# Rules
nat on $ext_if inet from ! ($ext_if) to any -> ($ext_if)                # NAT translation

#block                                                                  # By default, block all connections that don't match a rule below.
pass out on $int_if from $int_if to $internal_network                   # Allow all connections between internal network and the router.
pass in on $int_if proto udp from $internal_network to $int_if port 67  # Allow DHCP on the internal network.
pass in on $int_if proto tcp from $internal_network to $int_if port 22  # Allow SSH on the internal network.
pass in on $int_if proto tcp from $internal_network to $int_if port 53  # Allow DNS on the internal network.
pass in on $int_if proto icmp from $internal_network to $int_if         # Allow ICMP on the internal network.

pass out on $ext_if proto udp all
pass out on $ext_if proto tcp all modulate state

pass on $ext_if inet proto icmp all icmp-type 8 code 0

pass in on $ext_if proto udp from any to any port domain

Any help is appreciated. :e
 
If I'm not mistaken port 67 needs TCP as well as UDP access for DHCP.
 
I would use the quick keyword in order to simplify your rule. Then, I don't understand your first pass rule is supposed to be. Also, using log keywork should help you and us to fix the problem
 
Trihexagonal said:
If I'm not mistaken port 67 needs TCP as well as UDP access for DHCP.

Well, everyone is able to get an address okay.

I'm confused on how to turn on logging could someone point me in the right direction? I've attempted it, but I keep getting syntax errors.

thegolum35 said:
Then, I don't understand your first pass rule is supposed to be. Also, using log keywork should help you and us to fix the problem

I was trying to allow unrestricted communication out from the router to any device on my 10.0.0.0/8 network. I'm also misunderstanding how the 'quick' keyword works.
 
Start your rules with

Code:
block all

The default is to allow everything so you should that as the first rule.

Then change the first pass rule to

Code:
pass out quick on $int_if all

This will allow all outgoing traffic on int_if, the quick stops the rule evaluation at this rule, without it the packets would be matched against all other rules following it. pf(4) is last matching rule wins type packet filter.

Add this rule as the last pass in rule:

Code:
pass in log quick on $int_if from $int_if:network to any port http

This will allow plain http traffic from the hosts on the internal network to the internet. The log keyword turns on logging for the rule, you need to enable the pflogd(8) service in /etc/rc.conf:

Code:
pflog_enable="YES"

To read the log use this:

# tcpdump -n -tttt -e -r /var/log/pflog.
 
Thank you sir, will try this when the internet can be taken down in the next hour or so.

In the mean time, would anyone care to validate my configuration?

Code:
# Macros

int_if = 're0'                                                          # internal interface
ext_if = 're1'                                                          # external interface

# Options
set block-policy drop                                                   # drop packets on block
set skip on lo0                                                         # skip filtering rules on loopback

# Rules
block all                                                               # Block all connections unless otherwise matching a rule below.
nat on $ext_if inet from ! ($ext_if) to any -> ($ext_if)                # NAT translation

pass out quick on $int_if all                                           # Allow outbound connections from the internal network.

pass in on $int_if proto udp from $int_if:network to $int_if port 67    # Allow DHCP on the internal network.
pass in on $int_if proto tcp from $int_if:network to $int_if port 22    # Allow SSH on the internal network.
pass in on $int_if proto tcp from $int_if:network to $int_if port 53    # Allow DNS on the internal network.
pass in on $int_if proto icmp from $int_if:network to $int_if           # Allow ICMP on the internal network.

pass in log quick on $int_if from $int_if:network to any port http      # Pass and log all outbound http(s) connections.
pass in log quick on $int_if from $int_if:network to any port https
 
Update:

Still unable to access internet through firewall. I had to make some changes. I added a couple of rules as well for ICMP and I am able to ping outside IPs. DNS does not appear to be working either with these rules (the FreeBSD router also acts as a DNS server). Commenting block all and reloading allows for connectivity.

Code:
# Macros

int_if = 're0'                                                                          # internal interface
ext_if = 're1'                                                                          # external interface

# Options
set block-policy drop                                                                   # drop packets on block
set skip on lo0                                                                         # skip filtering rules on loopback

# Rules
nat on $ext_if inet from ! ($ext_if) to any -> ($ext_if)                                # NAT translation

block all
pass out quick on $int_if all                                                           # Allow outbound connections from the internal network.

pass in on $int_if proto udp from $int_if:network to $int_if port 67                    # Allow DHCP on the internal network.
pass in on $int_if proto tcp from $int_if:network to $int_if port 22                    # Allow SSH on the internal network.
pass in on $int_if proto { udp tcp } from $int_if:network to $int_if port 53            # Allow DNS on the internal network.
pass in on $int_if proto icmp from $int_if:network to $int_if                           # Allow ICMP on the internal network.

pass in log quick on $int_if proto { tcp udp } from $int_if:network to any port http    # Pass and log all outbound http(s) connections.
pass in log quick on $int_if proto { tcp udp } from $int_if:network to any port https
pass in log quick on $int_if proto icmp from $int_if:network to any
pass out inet proto icmp all icmp-type echoreq
 
Add this after the first pass out rule:

Code:
pass out quick on $ext_if all

This will allow all outgoing traffic on ext_if. You're filtering connections initiated on the internal network so this is not as open as it sounds.
 
Just a note...

Just so you know, you don't need rules for DHCP (unless you are running a relay) in pf. This is because dhcpd listens on the raw (unfiltered) bpf device, and does not receive packets in the normal socket manner.
 
Back
Top