/ Server / Openbsd Pf Rules For Webservers


Published:2014-03-03T13:23:24Z Edited:2016-08-10T13:23:24Z
OpenBSD pf make a magnificent job to simplifing packet filtering for writing network packet filters ( aka firewalls ), its quite powerful and it's syntax looks very natural. In this article We'll learn how to secure a web server with openbsd pf, if you look for firewall for linux then check iptables iptables for securing webservers.
 
 

Whats Openbsd PF?

Openbsd pf is network packets filtering pseudo device /dev/pf , which enables programs to allow/disallow packets ( internet connections for simplicity ) incoming/outgoing in simple and dynamic way.
 

How pf differs from iptables?

pf differs from iptables as follows:
  • pf  runs on BSDs only ( openbsd, freebsd, dragonflybsd ..etc) , while iptables runs on linux only ( debian, centos, gentoo ..etc)
  • pf has all rules of ipv4/ipv6 on the same config file, iptables need a different command to manage ipv6 named ip6tables.
  • pf has realtime logging facility on pseudo interface pflog, as I'm aware iptables has logging but not in realtime ( it logs to syslog by default ).
  • pf's Syntax is quite simple, powerful and very human-friendly, iptables's syntax is more complicated, less powerful and not human-friendly.
  • pf can prioritise packets and net traffic, iptables cannot ( need different command, on linux tc )
  • pf last rule matches will win, iptables first rule matches will win.

 

Before We begin

packet filtering can become a complex topic and if you're working on a remote system you may be blocked from accessing your system, therefore our approach for configuring our packet filter (pf) for KISS sake will be careful and easy.

 

pf rules

We'll work on /etc/pf.conf 

  1. First lest set some macros:
    • For interfaces, lo0 is our internal loopback interface, em0 is the external interface
      in_if = "lo0"
      ex_if = "em0"
    • For allowed ports for: ssh (22), mail server (25), web server (80 443):
      ports = "{ 22 25 80 443 }"
    • For allowed protocols : tcp, udp icmp:
      protocols = "{ tcp udp icmp }"
  2. Set configuration settings:
    • Let the default blocking method to drop unpermitted connection without any notice
      set block-policy drop
    • Let Skip packet filtering on internal interface since all connections are from/to localhost
      set skip on $in_if
    • Sanitise all traffic
      match in all scrub (no-df random-id)
    • Block spoofed ip addreses
      antispoof quick for $in_if
  3. Pass/Block rules started here, remember that pf apply last matching rule So we need to define the fallback rule, then allowed rules:
    • Fallback rule will apply unless "pass" rule match later
      block all
    • Let traffic of allowed protocols and ports we defined above to pass
      pass in on $ex_if inet proto $protocols from any to any port $ports keep state
      pass in on $ex_if inet6 proto $protocols from any to any port $ports keep state
    • Allow all outgoing traffic from allowed protocols only
      pass out on $ex_if inet proto $protocols from any to any
      pass out on $ex_if inet6 proto $protocols from any to any
    • Malformed connections need to be dropped:
      block in from no-route to any
      block in from urpf-failed to any
  4. The final content of /etc/pf.conf may look like the following:
    # macros
    # lo0 internal
    # em0 external
    in_if = "lo0"
    ex_if = "em0"
    
    # ssh (22), mail server (25), web server (80 443)
    ports = "{ 22 25 80 443 }"
    
    # allowed protocols : tcp, udp icmp
    protocols = "{ tcp udp icmp }"
    
    # config
    set block-policy drop
    set skip on $in_if
    match in all scrub (no-df random-id)
    antispoof quick for $in_if
    
    # fallback
    block all
    
    # allow incoming traffic
    pass in on $ex_if inet proto $protocols from any to any port $ports keep state
    pass in on $ex_if inet6 proto $protocols from any to any port $ports keep state
    
    # allow outgoing traffic
    pass out on $ex_if inet proto $protocols from any to any
    pass out on $ex_if inet6 proto $protocols from any to any\n
    # finally drop some known-bad traffic
    block in from no-route to any
    block in from urpf-failed to any
    
  5. Check /etc/pf.conf for any error and reload it
    pfctl -n -f /etc/pf.conf && pfctl -f /etc/pf.conf

 

Thats it

I hope I gave you some taste of pf syntax, there's always room for enhancments, but as I said earlier better test your filtering rules maybe on some staging server before you apply'em on production server and get fired :)

 

if you run manage linux webservers on some of your computer check iptables for linux

Next
Debian Router - DHCP server setup
Previous
Jorgee the kidbot
Tags