Selasa, 15 April 2008

PF 1.60 + ALTQ 0.4.1 on FreeBSD 5.1-RELEASE
(1483 total words in this text)
(viewed: 7986 times)



### INTRO

In this tut, getting pf 1.60 with ALTQ support running smoothly
on FreeBSD 5.1 will be our goal. We'll take a fresh, clean install of
FreeBSD 5.1-RELEASE, do some prepping, upgrade the FreeBSD
sources to the latest security branch release, get the necessary
files and install everything. Lastly, we'll create a basic pf.conf to
work from. How you go from there is up to you. The latest version
of ALTQ (0.4.1) has a new fix for the tun device.

### PREPARATION

## CVSup

Since there is no -STABLE yet, we'll use the
standard-supfile for getting the latest security branch;
create the following:
# mkdir /etc/cvsup
# vi /etc/cvsup/standard-supfile

*default host=cvsup11.FreeBSD.org
*default base=/usr
*default prefix=/usr
*default release=cvs tag=RELENG_5_1
*default delete use-rel-suffix
*default compress
src-all
cite from http://www.iana.org/assignments/port-numbers
Save, exit and create the following file, and set the
appropriate permissions so users on your system can't
launch cvsup:
# vi /etc/cvsup/srcupdate (chmod 700)
cvsup -g -L 2 /etc/cvsup/standard-supfile

Save and exit. You'll have to add /etc/cvsup or . to your $PATH (~/.cshrc if
you use /bin/csh) if you want to run without using ./ beforehand.

### FILES

ALTQ source and patches:
http://www.nipsi.de/FreeBSD/altq-freebsd-5.1-release-0.4.1.tar.gz
(MD5 = 4e2b66a6be0ba8e785aef038868705e1)

PF for FreeBSD 5.1:
http://pf4freebsd.love2party.net/pf_freebsd_1.60.tar.gz
(MD5 = cb4b504815b1dadb85d337daba61e332)

### PROCEDURE

Back up kernel:
# cd /boot
# cp -Rp kernel kernel.noaltq

Back up /usr/include:
# cd /usr
# mkdir include.noaltq
# cd include.noaltq
# (cd ../include; tar Bpcf - .)|tar Bpxf -

CVSup to get latest FreeBSD 5.1-RELEASE src:
# cd /etc/cvsup
# srcupdate

Copy /usr/src/sys to /usr/src/sys.altq:
# cd /usr/src
# mkdir sys.altq
# cd sys.altq
# (cd ../sys; tar Bpcf - .)|tar Bpxf -

Move original /usr/src/sys out of the way, and create a symbolic link
to point to the new sys.altq dir:
# mv /usr/src/sys /usr/src/sys.orig
# ln -s /usr/src/sys.altq /usr/src/sys

Create pf/altq build location (you can use /tmp if you prefer)
# mkdir /pf
# cd /pf

Wget or fetch the necessary files:
# wget http://www.nipsi.de/FreeBSD/altq-freebsd-5.1-release-0.4.1.tar.gz
# wget http://pf4freebsd.love2party.net/pf_freebsd_1.60.tar.gz

Verify the files with MD5 (your results should match these):
# md5 altq-freebsd-5.1-release-0.4.1.tar.gz
MD5 (altq-freebsd-5.1-release-0.4.1.tar.gz) = 4e2b66a6be0ba8e785aef038868705e1
# md5 pf_freebsd_1.60.tar.gz
MD5 (pf_freebsd_1.60.tar.gz) = cb4b504815b1dadb85d337daba61e332

Detar source for ALTQ and PF:
# tar zxf altq-freebsd-5.1-release-0.4.1.tar.gz
# tar zxf pf_freebsd_1.60.tar.gz

Patch ALTQ src:
# cd /usr/src/sys ('pwd' to see that you are really in /usr/src/sys.altq)
# cp /pf/altq-freebsd-5.1-release-0.4.1/sys-altq-freebsd-5.1-release-0.4.1.diff .
# patch -p0 < sys-altq-freebsd-5.1-release-0.4.1.diff
# cp -HR /pf/altq-freebsd-5.1-release-0.4.1/altq .
# cp ./net/if_var.h /usr/include/net
# cp ./netinet/ip.h /usr/include/netinet

Prepare ALTQ-enabled kernel config (if you already have a custom kernel, simply
copy that one instead of GENERIC):
# cp /usr/src/sys/i386/conf/GENERIC /usr/src/sys/i386/conf/ALTQKERNEL
# vi /etc/make.conf and add the following:

CFLAGS= -O -pipe
NOPROFILE= true
USA_RESIDENT= yes

Save and exit the file, then edit the kernel config:
# vi /usr/src/sys/i386/conf/ALTQKERNEL and make sure the following are enabled:

device bpf # default
options INET # default
options INET6 # default
options RANDOM_IP_ID
options PFIL_HOOKS
options ALTQ

If you have an SMP kernel, you will also need options ALTQ_NOPCC additionally.

Save and exit the file, then compile the new kernel the old-fashioned way:
# cd /sys/i386/conf && config ALTQKERNEL
# cd ../compile/ALTQKERNEL && make depend && make && make install

Build PF:
# cd /pf/pf_freebsd_1.60
# make WITH_ALTQ=yes && make WITH_ALTQ=yes install

These next files are very simple executables used to load and unload PF at will
(if you want to improve upon them, go ahead):
# vi /usr/local/sbin/pf

# loadpf - load all pf-related modules
echo ""
kldload /boot/kernel/pf.ko
echo "pf.ko loaded"
ifconfig pflog0 up
echo "pflog0 up"
ifconfig pfsync0 up
echo "pfsync0 up"
/sbin/pflogd
echo "pflog daemon started"
pfctl -e -f /etc/pf.conf
echo "pf now active"
echo ""

Save, exit and create the next one:
# vi /usr/local/sbin/unpf

# unloadpf
echo ""
kldunload pf
echo "pf.ko unloaded"
killall pflogd
echo "pflog daemon stopped"
ifconfig pfsync0 down
echo "pfsync0 down"
ifconfig pflog0 down
echo "pflog0 down"
echo "pf disabled"
echo ""

Save, exit and append the following to /etc/rc.local so that pf enables on
startup:
# echo "/usr/local/sbin/pf" >> /etc/rc.local

Reboot and see if your new kernel works. To verify that ALTQ is enabled in the
kernel:
# strings /boot/kernel/kernel|grep -c altq_lookup
(Return value of '1' means it's enabled, '0' means it's not)

Verify that the four pf modules are loaded:
# kldstat|grep pf
3 1 0xcb4d8000 21000 pf.ko
4 2 0xcb4a6000 2000 pflog.ko
5 2 0xcb4cc000 3000 pfsync.ko
6 1 0xcb27c000 c000 pfaltq.ko

Now that we're up and running, we'll need to create our /etc/pf.conf file.
Since this is not a PF tutorial per se, I will show a simple example to start
from.

### /etc/pf.conf

## MACROS - here's where you set variables for use in your rules
# specify your own values and interfaces
loop="lo0"
ext_if="xl0"
ext_net="xxx.xxx.xxx.xxx/xx"
int_if="rl0"
int_net="192.168.0.0/24"
unfiltered="{ lo0, rl0 }"
tcp_svcs="{ 22, 25, 53, 80, 110, 443, 465, 995, > 1024 }"

## OPTIONS - network settings
# use 'return' instead of 'drop' if you wish to return responses to connection
# attempts, 'drop' is the same as the 'blackhole' sysctl option
set timeout { frag 15, interval 5 }
set limit { frags 2500, states 5000 }
set optimization aggressive
set block-policy drop
set loginterface $ext_if

## TABLES - useful for specifying large lists of data

## NORMALIZATION - Scrubbing will automatically drop TCP packets that have invalid
# flag combinations, so there's no need for typical 'anti-portscan' rules that ipf
# and ipfw use.
scrub in on $ext_if
scrub out on $ext_if no-df random-id min-ttl 24 max-mss 1492

## QUEUES - ALTQ rules
altq on $ext_if cbq bandwidth 500Kb queue { q_std }
queue q_std bandwidth 100% cbq
{ q_def, q_pri, q_web, q_msc, q_dat, q_gms }
queue q_def bandwidth 25% priority 1 cbq(borrow default red ecn)
queue q_dat bandwidth 10% priority 0 cbq(red)
queue q_web bandwidth 25% priority 5 cbq(borrow)
queue q_msc bandwidth 15% priority 4 cbq(borrow)
queue q_gms bandwidth 25% priority 6 cbq(borrow)
queue q_pri priority 7

## TRANSLATIONS - nat, binat and rdr rules
no nat on $unfiltered
no rdr on $unfiltered
nat on $ext_if from $int_net to any -> $ext_if

## FILTER - specific rules for blocking and allowing various traffic
# 'from any to any' and 'all' are inferred by default and do NOT have to be
# declared in your rules.
# Let loopback and internal interface traffic flow without restrictions
pass quick on $unfiltered

# Deny and log all by default
# This replaces 'block in all' and 'block out all'
block log

# Allow pings and replies while keeping state
pass out quick on $ext_if inet proto icmp icmp-type 8 code 0 keep state
pass in quick on $ext_if inet proto icmp icmp-type 8 code 0 keep state

# Keep state on all outgoing UDP and allow DNS replies
pass out on $ext_if inet proto udp keep state
pass in quick inet proto udp from any to $ext_if port 53 keep state

# Modulate state on all outgoing TCP and keep state on allowed incoming TCP ports
pass out on $ext_if inet proto tcp from $ext_if to any flags S/SA modulate state
pass in on $ext_if inet proto tcp from any to $ext_if port $tcp_svcs flags
S/SA keep state

# Here are some ALTQ rules to show how 'cbq' works, 'priq' is also popular
# The indented lines are a continuation of the previous line, as
# backslash doesn't display here # Pass out valid TCP states and UDP.
pass out on $ext_if keep state queue(q_std)
pass out on $ext_if inet proto tcp from $ext_if to any
flags S/SA modulate state queue(q_def, q_pri)
pass out on $ext_if inet proto tcp
port { 21, 20, 5800, 5801, 5900, 5901 } queue(q_dat)
pass out on $ext_if inet proto { tcp, udp } keep state
port { 53, 80, 443 } queue(q_web)
pass out on $ext_if inet proto tcp
port { 22, 25, 110, 143, 993, 994, 995, 6667 } flags S/SA
modulate state queue(q_msc)
pass out on $ext_if inet proto udp keep state
port { 27000 >< 28000 } queue(q_gms)

# EOF

Save and exit the file. Run the following:
# pfctl -e -f /etc/pf.conf

Check for any errors. If none, pf is running. Use 'pfctl -sr' to see how PF
interprets your ruleset. Use 'pfctl -sa' to show all pfctl output. You can use
'pf' and 'unpf' to enable and disable PF. Note: you might lost your ssh
connection when doing this. Disable PF manually by running 'pfctl -d'; flush
rules after making changes by running 'pfctl -Fr'; enable PF
manually by running 'pfctl -e -f /etc/pf.conf' again. use 'pfctl -vvsq' to
view ALTQ output. To view logs in realtime, run 'pftcpdump -nettti pflog0' or
to view the logfile (tcpdump binary format, don't try to vi it), run
'pftcpdump -netttr /var/log/pflog'.

That should be enough to give you an idea of the various things you can do.
Check the pf-repository for more examples, tips, tutorials and articles related
to PF. Hopefully, this should get some people who use FreeBSD 5.1 to try out
PF. Even if you don't care about bandwidth management (ALTQ), PF is very
flexible and has been stable for several months during my usage.

Tidak ada komentar: