PF Is there a bug in this configuration?

Hello everyone,

This is a simple PF test. A router, a PF firewall and a NPT server. Since only the router WAN interface is a public IP, NAT is enabled on the PF.

The purpose is to allow the NTP server to synchronize with the Internet time server. It also allows the firewall to synchronize with the local NTP server.

Below is the configuration of the PF firewall, which looks a bit confusing. Do some places need to be simplified or modified?

The name resolution of the Internet time server is not considered here.

Code:
ext_if = "em0"
int_if = "em1"
ntp_1 = "10.0.0.2"

set skip on lo0
set reassemble yes no-df

block all
antispoof quick for $ext_if
antispoof quick for $int_if
block in quick on $ext_if from { no-route, urpf-failed } to any

pass inet proto icmp all icmp-type 8 code 0
pass in on $int_if proto udp from $ntp_1 port 123 to any port 123
pass out on $ext_if proto udp from $ext_if to any port 123

#Translation
pass out on $ext_if inet from $int_if:network to any nat-to $ext_if

pass out on $int_if proto udp from $int_if port 123 to $ntp_1 port 123


pass out on $ext_if proto udp from $ext_if to any port 123
Can it be modified to
pass out on $ext_if proto udp from $ntp_1 port 123 to any port 123
Which is correct?


pass out on $ext_if proto udp from $ext_if to any port 123
pass out on $ext_if inet from $int_if:network to any nat-to $ext_if
Should they be reversed in order?

Thanks.
 
Last edited:
You'll probably also want to allow outgoing DNS requests, or else your firewall will have a hard time resolving anything.
 
Do you mean the last rule? I have modified it a bit.

Code:
# Macros
ext_if = "em0"
int_if = "em1"
ntp_1 = "10.0.0.2"

# Options
set skip on lo0
set reassemble yes no-df

# Packet Filtering
block all
antispoof quick for { $int_if, $ext_if }
block in quick on $ext_if from { no-route, urpf-failed } to any

pass inet proto icmp all
pass proto udp from $ntp_1 port 123 to any port 123
pass out on $int_if proto udp from $int_if port 123 to $ntp_1 port 123

#Translation
pass out on $ext_if inet from $int_if:network to any nat-to $ext_if
 
Your antispoof is a bit off: for the external interface you'd also want to specify inet; you can't just mix the two together.

And that brings me to: you could consider removing the blocking rules because there's no direct need. You start with
Code:
block all
..which means that if there are no matching pass rules then the end result is that the traffic will be blocked.

With a larger ruleset there is something to say to quickly block traffic but for a rather small set like this there really isn't much advantage.
 
These are my antispoof rules:

Code:
antispoof for lo0
antispoof for $ext_if inet
block in from no-route to any
block in from urpf-failed to any
block in quick on $ext_if from any to 255.255.255.255
block in log quick on $ext_if from { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 255.255.255.255/32 } to any


This is from your ruleset:

Code:
pass proto udp from $ntp_1 port 123 to any port 123
pass out on $ext_if proto udp from $ext_if to any port 123

I default block port 123 for incoming UDP and TCP and use this as my egress rule:

Code:
### Keep and modulate state of outbound tcp, udp and icmp traffic
pass out on $ext_if proto { tcp, udp, icmp } from any to any modulate state
 
The quick keyword stops other rules being evaluated, therefore any pass or block rule could use the quick keyword to stop other rules being evaluated.
i.e.
pass quick inet proto icmp all
 
The quick keyword stops other rules being evaluated, therefore any pass or block rule could use the quick keyword to stop other rules being evaluated.
i.e.
pass quick inet proto icmp all
Thank you. But here also needs NAT.
 
PF threads are always interesting. May I ask where can redirection rules come in? Is it allow after NAT rules and the rest? I mean can we set them within the packet filtering rules?
 
Redirection is the same thing as NAT regardless of the direction and both nat and rdr rules go in the same section. For example this is part of what I have in my pf.conf(5) in the NAT rules section:

Code:
nat on re0 inet from ! (re0) to any -> (re0) port 1024:65535 round-robin
rdr on re0 inet proto tcp from any to (re0) port = 50022 tag SSH_EXTERNAL -> 127.0.0.1 port 22
 
Code:
pass proto udp from any to any port 123
abbreviated as
Code:
pass proto udp to port 123

Is it conducive to reading?
 
Redirection is the same thing as NAT regardless of the direction and both nat and rdr rules go in the same section. For example this is part of what I have in my pf.conf(5) in the NAT rules section:

Code:
nat on re0 inet from ! (re0) to any -> (re0) port 1024:65535 round-robin
rdr on re0 inet proto tcp from any to (re0) port = 50022 tag SSH_EXTERNAL -> 127.0.0.1 port 22

I normally use a pass rule on my redirection:

Code:
rdr pass on re0 inet proto tcp from any to (re0) port = 50022 tag SSH_EXTERNAL -> 127.0.0.1 port 22


Code:
pass proto udp from any to any port 123
abbreviated as
Code:
pass proto udp to port 123

Is it conducive to reading?

It is to me
 
I normally use a pass rule on my redirection:

Code:
rdr pass on re0 inet proto tcp from any to (re0) port = 50022 tag SSH_EXTERNAL -> 127.0.0.1 port 22




It is to me

Enabling pf/etc/pf.conf:102: Rules must be in order: options, normalization, queueing, translation, filtering ...

Unless I'm missing something, this means that sdf original posted rules are out of order, or labeled out of order. Should I take it since the pass proto and pass out rules are a form of redirection are allowed within the filtering section? I have not tested yet because I'm just noticing this possible flaw. It seems to make since that this part of sdf rules should work in the -> Filtering Section. .. if so, Wow!
Code:
pass inet proto icmp all
[code]pass proto udp from $ntp_1 port 123 to any port 123
pass out on $int_if proto udp from $int_if port 123 to $ntp_1 port 123
 
Back
Top