December 18, 2009

FreeBSD 5.4+ 'pf' firewall for Cpanel How-To

Refer: http://layer0.layeredtech.com/showthread.php?t=2164


FreeBSD 5.4 and higher firewall rules for a Cpanel enabled host. USE AT YOUR OWN RISK. MIS-CONFIGURATION OF THIS HOWTO WILL LEAD TO YOU BEING LOCKED OUT OF YOUR SERVER.

# Edit /etc/rc.conf to have the following.


% grep pf_en /etc/defaults/rc.conf | sed 's/NO/YES/g' >> /etc/rc.conf

The above command adds 'pf_enable="YES"' so 'pf' will start and load the 'pf.ko' on boot.

# Edit the 'pure-ftpd.conf' to have the following
Code:

% ee /usr/local/etc/pure-ftpd.conf


Around line #182 change the 'PassivePortRange'



# From PassivePortRange 30000 50000


To the default FreeBSD / OpenBSD port ranges for ftpd.


PassivePortRange 49151 65535


You will need to restart 'pure-ftpd' before the changes will take affect for the new port ranges. If you do not modify the ranges it will cause your 'dir' to be very slow when connecting to your server with remote a ftp client.

Now you will need to fetch the 'pf.conf', pf.conf.open and related 'pf.blocklist.txt' file used for the 'badguys' table. The pfdump script will allow you to view the traffic being blocked real time.



% cd /etc % fetch http://tutorials.layeredtech.com/pf/pf.blocklist.txt % fetch http://tutorials.layeredtech.com/pf/pf.conf % fetch http://tutorials.layeredtech.com/pf/pf.conf.open % cd /usr/local/sbin/ % fetch http://tutorials.layeredtech.com/pf/pfdump % chmod +x pfdump % rehash


Everything to start, stop and load the firewall rules should be setup now. To start the firewall do the following.

For the first time you use the firewall before a reboot is done you will need to load the kernel module for 'pf'



% kldload pf.ko


First turn on 'pf' with the following.


% pfctl -e


Now load your rules. When the command below is run you will see all of your translated rules displayed and then loaded. 'pf' will now allow the loading of a bad ruleset or one with syntax errors so if you see a failure look for the line number and investigate that in the 'pf.conf' file.

To load the rules through the pf parser but not into the firewall run the following. Use the following to test for syntax errors in your 'pf.conf' file after you have made any changes.



% pfctl -vvv -nf /etc/pf.conf


Load the rules for '90' seconds and then rollback to an 'open' ruleset after the 90 seconds has passed. This is a great way to test your rules during changes.
Code:

% pfctl -vvv -f /etc/pf.conf ; sleep 90 ; pfctl -vvv -f /etc/pf.conf.open


To load the rules with no rollback run the following.


% pfctl -vvv -f /etc/pf.conf


To see the loaded rules run


% pfctl -sa | less


To see the loaded rules with line numbers run


% pfctl -sa -r | less


To see the same but with much more verbose details


% pfctl -sa -r -vvv | less


To view your pflog0 device data realtime use the 'pfdump' command


% pfdump


If you are having problems with the firewall and do not wish to run it any further the best solution is to load a 'pass all' ruleset. I have included a file for this called 'pf.conf.open' To load it run the following



% pfctl -vvv -f /etc/pf.conf.open % cp /etc/pf.conf /etc/pf.conf.bak % cp /etc/pf.conf.open /etc/pf.conf


This will open the firewall completely and pass all traffic. This will also load a 'open' ruleset on boot up. If you want to disable it further reverse the steps you have followed here and it will remove the firewall completely.

By default FreeBSD will load any rules listed in /etc/pf.conf by default. Make sure you copy the correct rules over before any reboots.

Now the actual files.



# FreeBSD Cpanel 'pf' firewall with basic dDoS mitigation using 'syn-proxy' states
# and other rate limits. USE AT YOUR OWN RISK.

# Macros: define common values, so they can be referenced and changed easily.
ext_if="fxp0" # replace with actual external interface name i.e., dc0
tcp_services="{ 22, 25, 26, 53, 80, 110, 143, 443, 465, 783, 953, 993, 995, 3306 }"
udp_services="{ 53, 514 }"
cpanel_services="{ 995, 2082, 2083, 2095, 2096, 2084, 2086, 2087 }"
icmp_types="8"

# Game servers (Quake3, CS )
# game_ports="27015"

# Tables: similar to macros, but more flexible for many addresses.
table const { 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }
table persist file "/etc/pf.blocklist.txt"

# Options: tune the behavior of pf, default values are given.
set timeout { interval 10, frag 30 }
set timeout { tcp.first 120, tcp.opening 30, tcp.established 86400 }
set timeout { tcp.closing 900, tcp.finwait 45, tcp.closed 90 }
set timeout { udp.first 60, udp.single 30, udp.multiple 60 }
set timeout { icmp.first 20, icmp.error 10 }
set timeout { other.first 60, other.single 30, other.multiple 60 }
set timeout { adaptive.start 0, adaptive.end 0 }
set limit { states 10000, frags 5000 }
set loginterface $ext_if
set optimization normal
set block-policy drop
set require-order yes
set fingerprints "/etc/pf.os"

# Normalization: reassemble fragments and resolve or reduce traffic ambiguities.
#scrub in all
scrub in on $ext_if all fragment reassemble min-ttl 15 max-mss 1400
scrub in on $ext_if all no-df
scrub on $ext_if all reassemble tcp

# Filtering: the implicit first two rules are
pass in all
pass out all

# Pass all 'quick' on localhost loopback device
pass quick on lo0 all

## Default DENY & Log filter rules
block in log all
block out log all

# Drop our 'badguys' 'quick' with no reply or logging.
block in quick on $ext_if from to any

# Drop our rfc1918 ranges
block in quick on $ext_if from to any

# Pass in rules for Various services defined above. Using 'synproxy-state' for
# basic dDoS mitigation on TCP services.
pass in on $ext_if proto tcp from any to $ext_if port $tcp_services flags S/SA synproxy state
pass in on $ext_if proto tcp from any to $ext_if port $cpanel_services flags S/SA synproxy state

# Pass UDP keeping state
pass in on $ext_if proto udp from any to $ext_if port $udp_services keep state

# Pass ICMP Type 8 (echo-reply) only with state
pass in on $ext_if inet proto icmp all icmp-type $icmp_types keep state

# Pass FTP
pass in quick on $ext_if proto tcp from any to any port 21 flags S/SA keep state
pass in quick on $ext_if proto tcp from any to any port > 49151 keep state

# Pass out rule allowing all with modulate state
pass out on $ext_if proto tcp all modulate state flags S/SA

# Pass out rules for UDP, ICMP
pass out on $ext_if proto { udp, icmp } all keep state

# End


# pf.conf.open contents



pass all


# pf.blocklist.txt contents



# Add IP's in here you want to be dropped like a rock. # See this link for more details on the syntax # http://www.openbsd.org/faq/pf/tables.html # Example below. 192.168.1.1 192.168.1.0/24


# pfdump contents


tcpdump -vvvnetti pflog0

No comments:

Post a Comment