Solved Rules problem

Greetings all,

for past two days I have been working on pf.conf, but the rules do not work the way I think they should. :-(

Code:
###################
#### Variables ####
###################

# External interface
ext_if="em0"

# Follow RFC1918 and don't route to non-routable IPs
nonroute= "{ 0.0.0.0/8, 20.20.20.0/24, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.2.0/24, 192.168.0.0/16, 224.0.0.0/3, 255.255.255.255 }"

# Set allowed ICMP types
icmp_types = "{ 0, 3, 4, 8, 11, 12 }"

####################################
#### Options and optimizations #####
####################################

# Set interface for logging (statistics)
set loginterface $ext_if

# Drop states as fast as possible without having excessively low timeouts
set optimization aggressive

# Block policy, either silently drop packets or tell sender that request is blocked
set block-policy drop

# Don't bother filter following interfaces such as loopback:
set skip on lo0

# Scrub traffic
scrub on $ext_if all

#######################
#### NAT & Proxies ####
#######################

# Enable ftp-proxy
nat-anchor "ftp-proxy/*"
rdr-anchor "ftp-proxy/*"

# Anchors needs to be set after nat/rdr-anchor
anchor "ftp-proxy/*"

################################
#### Rules inbound (ext_if) ####
################################

# Drop packets from non-routable addresses directly
block in quick on $ext_if from $nonroute to any
block in log quick on $ext_if from urpf-failed

# Allow DHCP
pass in quick on $ext_if inet proto udp to ($ext_if) port { 67, 68 }

# Allow ICMP
pass in quick on $ext_if inet proto icmp all icmp-type $icmp_types

# Allow FTPs to connect to FTP-proxy
pass in quick on $ext_if inet proto tcp to ($ext_if) port ftp-data user proxy

# Allow SSH, HTTP on TCP ports
pass in quick on $ext_if inet proto tcp to any port { 22, 80 }

# Block everything else
block in on $ext_if all

#################################
#### Rules outbound (ext_if) ####
#################################

# Drop packets to non-routable addresses directly
block out log quick on $ext_if from any to $nonroute

# Allow ICMP
pass out quick on $ext_if inet proto icmp all icmp-type $icmp_types

# Allow FTP-proxy to connect to servers
pass out quick on $ext_if inet proto tcp to any user proxy

# Allow access to SSH, SMTP, HTTP, HTTPS, and SMTPS on TCP ports
pass out quick on $ext_if inet proto tcp to any port { 22, 25, 80, 443, 465, 587 }

# Allow server to access POP3, IMAP, and IMAPS
pass out quick on $ext_if inet proto tcp from ($ext_if) to any port { 110, 143, 993 }

# Allow DHCP, NTP, 5001 5060-5070 on UDP ports
pass out quick on $ext_if inet proto udp from any to any port { 67, 68, 123, 5001}
pass out quick on $ext_if inet proto udp to any port 5060><5070

# Allow DNS access
pass out quick on $ext_if inet proto tcp from ($ext_if) to any port 53

# Block everything else
block out log on $ext_if all
The pfctl -vnf /etc/pf.conf results in:
Code:
ext_if = "em0"
nonroute = "{ 0.0.0.0/8, 20.20.20.0/24, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.2.0/24, 192.168.0.0/16, 224.0.0.0/3,255.255.255.255 }"
icmp_types = "{ 0, 3, 4, 8, 11, 12 }"
set loginterface em0
set optimization aggressive
set block-policy drop
set skip on { lo0 }
scrub on em0 all fragment reassemble
nat-anchor "/*" all
rdr-anchor "/*" all
table <__automatic_0> const { 0.0.0.0/8 20.20.20.0/24 127.0.0.0/8 169.254.0.0/16 172.16.0.0/12 192.0.2.0/24 192.168.0.0/16 224.0.0.0/3 }
table <__automatic_1> const { 0.0.0.0/8 20.20.20.0/24 127.0.0.0/8 169.254.0.0/16 172.16.0.0/12 192.0.2.0/24 192.168.0.0/16 224.0.0.0/3 }
anchor "/*" all
block drop in quick on em0 inet from <__automatic_0> to any
block drop in log quick on em0 from urpf-failed to any
pass in quick on em0 inet proto icmp all icmp-type echorep keep state
pass in quick on em0 inet proto icmp all icmp-type unreach keep state
pass in quick on em0 inet proto icmp all icmp-type squench keep state
pass in quick on em0 inet proto icmp all icmp-type echoreq keep state
pass in quick on em0 inet proto icmp all icmp-type timex keep state
pass in quick on em0 inet proto icmp all icmp-type paramprob keep state
pass in quick on em0 inet proto tcp from any to (em0) port = ftp-data user = 62 flags S/SA keep state
pass in quick on em0 inet proto tcp from any to any port = ssh flags S/SA keep state
pass in quick on em0 inet proto tcp from any to any port = http flags S/SA keep state
pass in quick on em0 inet proto udp from any to (em0) port = bootps keep state
pass in quick on em0 inet proto udp from any to (em0) port = bootpc keep state
block drop in on em0 all
block drop out log quick on em0 inet from any to <__automatic_1>
pass out quick on em0 inet proto tcp from (em0) to any port = pop3 flags S/SA keep state
pass out quick on em0 inet proto tcp from (em0) to any port = imap flags S/SA keep state
pass out quick on em0 inet proto tcp from (em0) to any port = imaps flags S/SA keep state
pass out quick on em0 inet proto tcp from (em0) to any port = domain flags S/SA keep state
pass out quick on em0 inet proto tcp all user = 62 flags S/SA keep state
pass out quick on em0 inet proto tcp from any to any port = ssh flags S/SA keep state
pass out quick on em0 inet proto tcp from any to any port = smtp flags S/SA keep state
pass out quick on em0 inet proto tcp from any to any port = http flags S/SA keep state
pass out quick on em0 inet proto tcp from any to any port = https flags S/SA keep state
pass out quick on em0 inet proto tcp from any to any port = smtps flags S/SA keep state
pass out quick on em0 inet proto tcp from any to any port = submission flags S/SA keep state
pass out quick on em0 inet proto icmp all icmp-type echorep keep state
pass out quick on em0 inet proto icmp all icmp-type unreach keep state
pass out quick on em0 inet proto icmp all icmp-type squench keep state
pass out quick on em0 inet proto icmp all icmp-type echoreq keep state
pass out quick on em0 inet proto icmp all icmp-type timex keep state
pass out quick on em0 inet proto icmp all icmp-type paramprob keep state
pass out quick on em0 inet proto udp from any to any port = bootps keep state
pass out quick on em0 inet proto udp from any to any port = bootpc keep state
pass out quick on em0 inet proto udp from any to any port = ntp keep state
pass out quick on em0 inet proto udp from any to any port = commplex-link keep state
pass out quick on em0 inet proto udp from any to any port 5060 >< 5070 keep state
block drop out log on em0 all
The first issue that I do not understand is why the "nonroute" variable expands into
"table <__automatic_0>" and "table <__automatic_0>", and are used in different parts of the pf.conf.

The other issue is that although the pfctl appears to indicate that I am passing the packets in and out correctly, I cannot, e.g., ssh, ping in or out once I enable the firewall.

Any help would be appreciated.

Kindest regards,

M

P.S. I am aware that most resources suggest to have the directives
Code:
block in on $ext_if all
block out log on $ext_if all
at the beginning, my reasoning was that if an allowed packet is detected, the rest of the rules does not need to be evaluated based on the
Code:
quick
directive.
 
Not sure about the actual firewall issues, but see the following page about the __automatic tables:
http://blather.michaelwlucas.com/archives/1049
It looks like it's automatically turning your IP address list into a table.

I don't know why it creates two tables, maybe it creates a separate table depending on whether the list is used as a src or dst. Regardless, you can clean that up by defining nonroute directly as a table (or just ignore it).
 
Hi usdmatt,

thank you for the advice on the list vs tables.

I have fixed part of my problem. Since I have the server behind a firewall with NAT my server has been assigned one of the non-routable addresses, and all the packets in and out of my server were promptly dropped. At least I know that the pf.conf works. ;-)

Now I have another problem, that although I can ping a name server, defined in /etc/resolv.conf, I am receiving "Host name lookup failure." Well, little by little I will get there.

Kindest regards,

M
 
Now I have another problem, that although I can ping a name server, defined in /etc/resolv.conf, I am receiving "Host name lookup failure." Well, little by little I will get there.
You're not allowing port 53 out to the DNS server, so it can never query the DNS server.
 
Hi SirDice,

thank you for your help. Can you please clarify? I had this line in the /etc/pf.conf:
Code:
# Allow DNS access
pass out quick on $ext_if inet proto tcp from ($ext_if) to any port 53
However, as I have found, the DNS may query both tcp and udp on port 53. So I have changed the /etc/pf.conf:
Code:
# Allow DNS access
pass out quick on $ext_if inet proto { tcp, udp } from ($ext_if) to any port 53
This seems to work, but it resolves only to:
Code:
pass out quick on em0 inet proto udp from (em0) to any port = domain keep state
while I expected:
Code:
pass out quick on em0 inet proto tcp from (em0) to any port = domain keep state
pass out quick on em0 inet proto udp from (em0) to any port = domain keep state
Do I have a wrong syntax for both tcp and udp?

Kindest regards,

M
 
No, you have the right syntax and I would expect it to work too. Maybe a subtle typo?
 
Hi SirDice,

thank you, I will go through the syntax again.

Hi getopt,

SirDice is correct, it works as intended.

Kindest regards,

M
 
Back
Top