PF Fine Tuning PF Ruleset

I've been playing around with pf(4) for the last few days trying to get everything setup the way I want it, and I think I've almost got it, but there's a few things I'd like to check with you guys about.

First, about my setup. A FreeBSD 10.1 machine with two network IFs acting as a gateway/router. re1 is the internal IF at 10.0.0.1 and re0/tun0 is the external IF with the site's IP address. Two ports, 80 and 22 are open to inbound connections from the internet. The machine itself is running http, ftpd, sshd, telnetd, named, nfsd, dhcpd, Samba, ntpd, and qpopper. Except for httpd, sshd, and maybe ftpd and qpopper, none of those services need to be visible to the internet.

Here's a copy of my pf.conf
Code:
# Macros
int_if = "re1"
ext_if = "tun0"
localnet = $int_if:network
tcp_svc =  "{ 80, 22 }"
icmp_types = "echoreq"
proxy = "184.13.32.35 port 8021"

# Security
scrub in all fragment reassemble no-df max-mss 1440

# Network address translation
nat on $ext_if from $localnet to any -> ($ext_if)
nat-anchor "ftp-proxy/*"
rdr-anchor "ftp-proxy/*"
rdr pass on $int_if proto tcp from $localnet to any port 21 -> \
127.0.0.1 port 8021

# Rules
block all
pass inet proto icmp all icmp-type $icmp_types keep state

# Allow all internally initiated network traffic
pass inet proto tcp from { self, $localnet }
pass inet proto udp from { self, $localnet }

# Allow select services
pass in inet proto tcp to $ext_if port $tcp_svc


# Block private bound traffic on ext if
private = "{ 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 $ext_if from $private to any
block drop out quick on $ext_if from any to $private

# More security
antispoof for $ext_if

table <bruteforce> persist
block quick from <bruteforce>
pass inet proto tcp to $localnet port $tcp_svc \
  keep state (max-src-conn 100, max-src-conn-rate 15/5, \
  overload <bruteforce> flush global)

# FTP Issues
anchor "ftp-proxy/*"
pass out proto tcp from $proxy to any port 21
Right now it's blocking all incoming connections from the net except 22, 80, and ICMP echo, while allowing unlimited access to itself and outbound connections to the LAN. Since all of the machines on the LAN are trustworthy, I'd like to keep allowing unlimited traffic to the server from the LAN, but I'd like to block all incoming connections to the LAN and outgoing connections to the internet from the LAN and server except: ftp, ssh, telnet, smtp, http, pop3, sftp, ntp, imap, https, UDP ports 5001, and 5060-5070. I'd also like to block DNS and pop3/imap requests from the LAN to the internet, since the server/router takes care of forwarding/caching DNS and downloading mail. So far I haven't found a way to do all this without screwing everything else up.

I should also mention that I'm having a small problem with FTP Proxy, right now I can only get it to work by specifying the external interface's address (proxy = "184.13.32.35 port 8021"), which is a problem since it's a dynamic IP.
 
Last edited by a moderator:
You want to allow more than just echoreq regarding ICMP, something like this is more correct unless you want to break stuff:
Code:
icmp_types = "{ 0, 3, 4, 8, 11, 12 }"
As for chinese IPs you can just setup a table with all entries just like what you did with private addresses. You can find several lists on the net although I have no idea which one is the most accurate one.
https://ip.ludost.net/cgi/process?c...x&format_name=&format_target=&format_default= is just one of many...
//Danne
 
Hi RevennaFox,
I like the tutorial at https://calomel.org/pf_config.html very much (in addition to the FreeBSD Handbook section at https://www.freebsd.org/doc/en/books/handbook/firewalls-pf.html). Please have a look at that as there are rules redirecting all DNS requests from the internal net to the DNS server running on the firewall host (localhost).
You can use
Code:
<self>
to create some rules like:
Code:
# block and log all traffic incoming on internal NIC to NOT-the-server on port 53
block drop in log quick on $int_if proto udp from $localnet to !<self> port 53
And you can reconfigure your pf firewall only if the syntax is correct by running:
Code:
# pfctl options:
# -n: dry-run (no actions taken, just read config)
# -f: use given config file
# -F: flush given parameters (default: all)
#      here: just reset rules, do not drop active connections
#
pfctl -n -f /etc/pf.conf && pfctl -f /etc/pf.conf -F rules
 
This probably serves as a pretty good template, at least it shouldn't break everything...

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

# External interface
ext_if="em0"

# Internal interface
int_if="em1"

# Follow RFC1918 and don't route to non-routable IPs
# http://www.iana.org/assignments/ipv4-address-space
# http://rfc.net/rfc1918.html
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 return

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

# Scrub traffic
# Gaming consoles such as PS3 and PS4 needs special care (minupnpd is also needed)
# scrub from 192.168.1.210 to any no-df random-id fragment reassemble
scrub on $ext_if all

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

# Enable NAT
# Gaming consoles such as PS3 and PS4 needs special care (minupnpd is also needed)
# nat on $ext_if from $int_if:network to any -> ($ext_if) static-port
nat on $ext_if inet from $int_if:network to any -> ($ext_if)

# Redirect ftp connections to ftp-proxy
rdr pass on $int_if inet proto tcp from $int_if:network to any port 21 -> 127.0.0.1 port 8021

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

# Enable uPNP
# rdr-anchor "miniupnpd"

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

################################
#### Rules inbound (int_if) ####
################################

# Pass on everything
pass in quick on $int_if from any to 239.0.0.0/8
pass in quick on $int_if inet all keep state

#################################
#### Rules outbound (int_if) ####
#################################

# Pass on everything
pass out quick on $int_if from any to 239.0.0.0/8
pass out quick on $int_if inet all keep state

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

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

# 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 our 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 drop 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 clients to access SSH, telnet, SMTP, HTTP, HTTPS on TCP ports
pass out quick on $ext_if inet proto tcp to any port { 22, 23, 25, 80, 443 }

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

# 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
# Drop packets to non-routable addresses directly
block drop out quick on $ext_if from any to $nonroute
block out log on $ext_if all
//Danne
 
Last edited:
Back
Top