The next step on the firewall is to set up the packet filter PF. Most of what I do here comes from the OpenBSD PF FAQ.
Setting up PF itself The file to edit is /etc/pf.conf. Here’s mine:
# macros
int_if="vr0"
ext_if="vr1"
# FTP Proxy rules
anchor "ftp-proxy/*"
pass in quick on $int_if inet proto tcp to any port ftp \
divert-to 127.0.0.1 port 8021
# options
set block-policy return
set loginterface $ext_if
set skip on lo
# match rules
match out on egress inet from !(egress) to any nat-to (egress:0)
# filter rules
block in log
pass out quick
antispoof quick for { lo $int_if }
# uncomment this to respond to pings
# pass in inet proto icmp all icmp-type echoreq
pass in on $int_if
It’s basically the example config file for home or small office, with a couple of changes:
- I define an int_if and ext_if for internal network and external network
- I don’t have any port forwarding from outside through to the inside network except ftp-proxy
- I block all incoming ICMP traffic (which is broken according to spec, but might keep me safer from denial of service attacks).
- I keep port 22 closed on the firewall machine.
Basically, I present a blank wall to the Internet. Traffic I initiate can get out, but outside doesn’t get in except via ftp-proxy.
One thing to note is that if you mess up pf, you can get into a state where you can’t talk to your ALIX over the network. So make sure you have a serial port handy to talk to it. I’d recommend making changes to pf.conf over serial, and then testing with the network.
To test, run:
pfctl -F all
pfctl -f /etc/pf.conf
The first command flushes whatever existing PF config is there; the second command loads your new pf config.
Next, hook up a machine to the switch that’s connected to the LAN side of the firewall, and see if you have Internet. If you do, life is good!
Getting FTP running You might have noticed I use ftp-proxy in my pf.conf. That’s a daemon that needs to be enabled in /etc/rc.conf: ftpproxy_flags=""
According to the PF FAQ, you can run ftp-proxy to get the daemon going, but I rebooted instead after changing /etc/rc.conf. Also according to the FAQ, some (fussy) clients may need “-r” on ftpproxy_flags.
Blocking IP addresses using PF I haven’t done this before, but I wanted to try blocking ad servers by IP address using PF. Some instructions are here.
My list of IP addresses came from the excellent pgl.yoyo.org/adservers site. I picked “list ad server IP addresses” as plain HTML text, checked the “view list as plain text” button, and pressed “go”. This gave me a URL that I copied.
I wanted a semi-automatic way to download this list. Luckily, OpenBSD’s ftp is a lot more than plain FTP. You can use it instead of wget/curl/etc. Here’s the command I used:
ftp -o /etc/pf.blocked.ip.conf "http://pgl.yoyo.org\
/adservers/iplist.php?ipformat=plain&;showintro=1&\
mimetype=plaintext"
Then I updated my pf.conf to account for that:
# macros
int_if="vr0"
ext_if="vr1"
# Table of IP addresses to block
table <blockedips> persist file "/etc/pf.blocked.ip.conf"
# FTP Proxy rules
anchor "ftp-proxy/*"
pass in quick on $int_if inet proto tcp to any port ftp \
divert-to 127.0.0.1 port 8021
# options
set block-policy return
set loginterface $ext_if
set skip on lo
# match rules
match out on egress inet from !(egress) to any nat-to (egress:0)
# filter rules
# These two rules block traffic from blacklisted IP addresses
block drop in quick on $ext_if from <blockedips> to any
block return out quick from any to <blockedips>
block in log
pass out quick
antispoof quick for { lo $int_if }
# pass in inet proto icmp all icmp-type $icmp_types
pass in on $int_if
I’m not sure if this strategy will work long term. Previously I excluded ad servers in named instead. Excluding by IP address seems to take less RAM (I’ve got about 163M free of my 256M RAM with this table loaded) and has the advantage of blocking sneaky servers that use IP address URLs. The downside is that if another server uses the same IP address, I won’t get the content, and I have no real way to unblock by name if I need to.
At any rate, to update, I just need to do the ftp command again, and then: pfctl -t blockedips -T replace -f /etc/pf.blocked.ip.conf
(This post is part of Building an ALIX firewall)