PF Rules must be in order: options, normalization, queueing, translation, filtering

Hello guys,
Can you help? I know There was a similar topic, but I did not understand the answer.

I have rules for my BSD System for defend apache.

I have error:

Code:
/usr/local/etc/pf.conf:31: Rules must be in order: options, normalization, queueing, translation, filtering

I do not understand what is not recommended? Can you edit and show it to me visually?
I apologize for the stupid problem.

Code:
# Source and tutorial -  https://www.cyberciti.biz/faq/how-to-set-up-a-firewall-with-pf-on-freebsd-to-protect-a-web-server/
# /usr/local/etc/pf.conf
#
## Set your public interface ##
ext_if="em0"

## Set your server public IP address ##
ext_if_ip="52.13.2.37"

## Set and drop these IP ranges on public interface ##
martians = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, \
          10.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24, \
          0.0.0.0/8, 240.0.0.0/4 }"

## Set http(80)/https (443) port here ##
webports = "{http, https}"

## enable these services ##
int_tcp_services = "{domain, ntp, smtp, www, https, ftp, ssh}"
int_udp_services = "{domain, ntp}"

## Skip loop back interface - Skip all PF processing on interface ##
set skip on lo

## Sets the interface for which PF should gather statistics such as bytes in/out and packets passed/blocked ##
set loginterface $ext_if

## Set default policy ##
block return in log all
block out all

# Deal with attacks based on incorrect handling of packet fragments
scrub in all

# Drop all Non-Routable Addresses
block drop in quick on $ext_if from $martians to any
block drop out quick on $ext_if from any to $martians

## Blocking spoofed packets
antispoof quick for $ext_if

# Open SSH port which is listening on port 22 from VPN 139.xx.yy.zz Ip only
# I do not allow or accept ssh traffic from ALL for security reasons
pass in quick on $ext_if inet proto tcp from  139.33.212.91 to $ext_if_ip port = ssh flags S/SA keep state label "USER_RULE: Allow SSH from 139.33.212.91"
## Use the following rule to enable ssh for ALL users from any IP address #
## pass in inet proto tcp to $ext_if port ssh
### [ OR ] ###
## pass in inet proto tcp to $ext_if port 22

# Allow Ping-Pong stuff. Be a good sysadmin
pass inet proto icmp icmp-type echoreq

# All access to our Nginx/Apache/Lighttpd Webserver ports
pass proto tcp from any to $ext_if port $webports

# Allow essential outgoing traffic
pass out quick on $ext_if proto tcp to any port $int_tcp_services
pass out quick on $ext_if proto udp to any port $int_udp_services

# Add custom rules below



# vim: set ft=pf
 
What is so hard to understand here? If you check the pf.conf(5) manualpage it will tell you exactly what the 7 statement types are and in which order pf is expecting them.

For example; you'll notice that Packet Filtering comes last. If you check you'll see that this involves blocking (or returning, usually a bad idea) and passing traffic. This means that you can't use any other statement in between your filtering rules. And the same applies to the other sections: you cannot mix those up.

So if we then take a look at your rule set:

Code:
## Set default policy ##
block return in log all
block out all

# Deal with attacks based on incorrect handling of packet fragments
scrub in all

# Drop all Non-Routable Addresses
block drop in quick on $ext_if from $martians to any
block drop out quick on $ext_if f
That is obviously not going to work because you put another type of statement in between your filtering rules, and those need to come last.

If you take a look at the manualpage again you'll see that scrub is part of the Traffic Normalization section which should come before Packet Filtering.

That's all there is to it: make sure that you use your statements in the right order. Look them up in the manualpage, check which sections they're in and then verify the order (or sequence) you're using. It's actually very easy because the manualpage lists all the statements in the right order.

I'm not going to go over your entire ruleset, it should be trivial enough to sort this out I think.
 
For someone experienced, it may be quite clear. Looking at the man page for pf.conf (not pf, where scrub isn't mentioned) it's not that clear that it is different from a rule if you're not that familiar with pf.

The trouble with man pages, and docs written by experts is that things that are obvious to someone who knows something are not that obvious to someone who doesn't. Ask a non-tech friend of yours to go through the man page for pf.conf and see if they are clear that scrub is not a rule.
 
For someone experienced, it may be quite clear. Looking at the man page for pf.conf (not pf, where scrub isn't mentioned) it's not that clear that it is different from a rule if you're not that familiar with pf.
I have to disagree with you on that point. I mean...

Code:
     With the exception of macros and tables, the types of statements should
     be grouped and appear in pf.conf in the order shown above, as this
     matches the operation of the underlying packet filtering engine.  By
     default pfctl(8) enforces this order (see set require-order below).
I don't think it can be put more clearly than this. It should be grouped, and it should appear in the right order.

Even if you don't understand then you'll soon see that further down all the 7 types are mentioned after which a list of options and commands follow. And that's even ignoring the working examples at the bottom.

The trouble with man pages, and docs written by experts is that things that are obvious to someone who knows something are not that obvious to someone who doesn't.
I'm a professional writer myself and I definitely agree that this is a thing.

But as said, I don't recognize that problem here. See, the thing is that this aspect you mention is actually a fine line to walk on. On one end you want to make things as easy to understand as possible, but on the other it's also not unreasonable to expect at least some basic understanding of the reader. Or... them taking the effort to try and understand.

And in my opinion that should go double when you're working with a firewall. Because if you don't understand how your firewall functions, then how can you expect any safety?

Do note that my comments are generally meant and should not be picked up within the context of this thread.
 
Take a look at your error message:

Code:
/usr/local/etc/pf.conf:31: Rules must be in order: options, normalization, queueing, translation, filtering

The "31" indicates the line number in /etc/pf.conf that has the problem, in your case it's:

Code:
scrub in all

scrub is a normalization that must be after the options section of pf.conf, so move that line up to just before the "set default policy" line.

That online tutorial is not very good, especially if it doesn't work.

In addion to the Handbook and pf man page, Try this one instead: https://calomel.org/pf_config.html
 
Do note that pf won't protect your webserver except possibly for DDoS

You're probably looking for mod_security or webranger in that regard.
 
What is so hard to understand here? If you check the pf.conf(5) manualpage it will tell you exactly what the 7 statement types are and in which order pf is expecting them.

For example; you'll notice that Packet Filtering comes last. If you check you'll see that this involves blocking (or returning, usually a bad idea) and passing traffic. This means that you can't use any other statement in between your filtering rules. And the same applies to the other sections: you cannot mix those up.

So if we then take a look at your rule set:

Code:
## Set default policy ##
block return in log all
block out all

# Deal with attacks based on incorrect handling of packet fragments
scrub in all

# Drop all Non-Routable Addresses
block drop in quick on $ext_if from $martians to any
block drop out quick on $ext_if f
That is obviously not going to work because you put another type of statement in between your filtering rules, and those need to come last.

If you take a look at the manualpage again you'll see that scrub is part of the Traffic Normalization section which should come before Packet Filtering.

That's all there is to it: make sure that you use your statements in the right order. Look them up in the manualpage, check which sections they're in and then verify the order (or sequence) you're using. It's actually very easy because the manualpage lists all the statements in the right order.

I'm not going to go over your entire ruleset, it should be trivial enough to sort this out I think.
Hello,
Hello guys,
Can you help? I know There was a similar topic, but I did not understand the answer.

I have rules for my BSD System for defend apache.

I have error:

Code:
/usr/local/etc/pf.conf:31: Rules must be in order: options, normalization, queueing, translation, filtering

I do not understand what is not recommended? Can you edit and show it to me visually?
I apologize for the stupid problem.

Code:
# Source and tutorial -  https://www.cyberciti.biz/faq/how-to-set-up-a-firewall-with-pf-on-freebsd-to-protect-a-web-server/
# /usr/local/etc/pf.conf
#
## Set your public interface ##
ext_if="em0"

## Set your server public IP address ##
ext_if_ip="52.13.2.37"

## Set and drop these IP ranges on public interface ##
martians = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, \
          10.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24, \
          0.0.0.0/8, 240.0.0.0/4 }"

## Set http(80)/https (443) port here ##
webports = "{http, https}"

## enable these services ##
int_tcp_services = "{domain, ntp, smtp, www, https, ftp, ssh}"
int_udp_services = "{domain, ntp}"

## Skip loop back interface - Skip all PF processing on interface ##
set skip on lo

## Sets the interface for which PF should gather statistics such as bytes in/out and packets passed/blocked ##
set loginterface $ext_if

## Set default policy ##
block return in log all
block out all

# Deal with attacks based on incorrect handling of packet fragments
scrub in all

# Drop all Non-Routable Addresses
block drop in quick on $ext_if from $martians to any
block drop out quick on $ext_if from any to $martians

## Blocking spoofed packets
antispoof quick for $ext_if

# Open SSH port which is listening on port 22 from VPN 139.xx.yy.zz Ip only
# I do not allow or accept ssh traffic from ALL for security reasons
pass in quick on $ext_if inet proto tcp from  139.33.212.91 to $ext_if_ip port = ssh flags S/SA keep state label "USER_RULE: Allow SSH from 139.33.212.91"
## Use the following rule to enable ssh for ALL users from any IP address #
## pass in inet proto tcp to $ext_if port ssh
### [ OR ] ###
## pass in inet proto tcp to $ext_if port 22

# Allow Ping-Pong stuff. Be a good sysadmin
pass inet proto icmp icmp-type echoreq

# All access to our Nginx/Apache/Lighttpd Webserver ports
pass proto tcp from any to $ext_if port $webports

# Allow essential outgoing traffic
pass out quick on $ext_if proto tcp to any port $int_tcp_services
pass out quick on $ext_if proto udp to any port $int_udp_services

# Add custom rules below



# vim: set ft=pf
Hello guys,
Can you help? I know There was a similar topic, but I did not understand the answer.

I have rules for my BSD System for defend apache.

I have error:

Code:
/usr/local/etc/pf.conf:31: Rules must be in order: options, normalization, queueing, translation, filtering

I do not understand what is not recommended? Can you edit and show it to me visually?
I apologize for the stupid problem.

Code:
# Source and tutorial -  https://www.cyberciti.biz/faq/how-to-set-up-a-firewall-with-pf-on-freebsd-to-protect-a-web-server/
# /usr/local/etc/pf.conf
#
## Set your public interface ##
ext_if="em0"

## Set your server public IP address ##
ext_if_ip="52.13.2.37"

## Set and drop these IP ranges on public interface ##
martians = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, \
          10.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24, \
          0.0.0.0/8, 240.0.0.0/4 }"

## Set http(80)/https (443) port here ##
webports = "{http, https}"

## enable these services ##
int_tcp_services = "{domain, ntp, smtp, www, https, ftp, ssh}"
int_udp_services = "{domain, ntp}"

## Skip loop back interface - Skip all PF processing on interface ##
set skip on lo

## Sets the interface for which PF should gather statistics such as bytes in/out and packets passed/blocked ##
set loginterface $ext_if

## Set default policy ##
block return in log all
block out all

# Deal with attacks based on incorrect handling of packet fragments
scrub in all

# Drop all Non-Routable Addresses
block drop in quick on $ext_if from $martians to any
block drop out quick on $ext_if from any to $martians

## Blocking spoofed packets
antispoof quick for $ext_if

# Open SSH port which is listening on port 22 from VPN 139.xx.yy.zz Ip only
# I do not allow or accept ssh traffic from ALL for security reasons
pass in quick on $ext_if inet proto tcp from  139.33.212.91 to $ext_if_ip port = ssh flags S/SA keep state label "USER_RULE: Allow SSH from 139.33.212.91"
## Use the following rule to enable ssh for ALL users from any IP address #
## pass in inet proto tcp to $ext_if port ssh
### [ OR ] ###
## pass in inet proto tcp to $ext_if port 22

# Allow Ping-Pong stuff. Be a good sysadmin
pass inet proto icmp icmp-type echoreq

# All access to our Nginx/Apache/Lighttpd Webserver ports
pass proto tcp from any to $ext_if port $webports

# Allow essential outgoing traffic
pass out quick on $ext_if proto tcp to any port $int_tcp_services
pass out quick on $ext_if proto udp to any port $int_udp_services

# Add custom rules below



# vim: set ft=pf
Hello, matek231 !
pf(4) , and pf.conf(5) can seem intimidating at first. Not the least of which, because there is so many different HOW-TO's out there. All from different *BSD's, or different pf(4) versions.
That said. The following should accomplish what you're after:
Code:
# /usr/local/etc/pf.conf
#
set loginterface em0

# drop return
set block-policy drop
set fingerprints "/etc/pf.os"

scrub in all
set skip on lo0

antispoof quick for lo0
#antispoof for nfe0 inet
antispoof for em0 inet

## Set your server public IP address ##
# unless you are managing more than one IP the following is pointless
#ext_if_ip="52.13.2.37"

# This table contains the ptivate IP blocks you defined in $martians
table <privip> persist file "/etc/PRIVIP"

# see /etc/PRIVIP
#martians = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, \
#          10.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24, \
#          0.0.0.0/8, 240.0.0.0/4 }"

block drop in quick on em0 from { <privip> } to any
block drop out quick on em0 from any to { <privip> }

pass proto tcp from any to em0 port { 80, 443 }

pass out quick on $ext_if proto tcp to any port {domain, smtp, www, https, ftp, ssh}
pass out quick on $ext_if proto udp to any port {domain, ntp}

# Allow Ping-Pong stuff. Be a good sysadmin
pass inet proto icmp icmp-type echoreq
If it's not already clear. I've moved the $martians IP's to a TABLE (file)
create the file: /etc/PRIVIP with the following contents:
Code:
127.0.0.0/8
192.168.0.0/16
172.16.0.0/12
10.0.0.0/8
169.254.0.0/16
192.0.2.0/24
0.0.0.0/8
240.0.0.0/4
You should be able to eliminate this TABLE, because of the antispoof rules
in pf.conf(5). But I've left the TABLE for your experimentation. :)
If it were be, I wouldn't create this TABLE, or use it. But your call. :)

HTH

--Chris
 
Back
Top