Build Your Own Gateway Firewall With FreeBSD
Build Your Own Gateway Firewall With FreeBSD
Build Your Own Gateway Firewall With FreeBSD
Due to time constraints, I only have time to cover the required software and a brief overview
of the installation process.
Obtaining the OS
Grab the CD ISOs or purchase the actual CDs or DVD from www.freebsd.org You can use
either FreeBSD 5.4 or 6.0, either one works. Be sure you download the correct image for
your architecture (only x86 is covered here). When in doubt, just grab the x86 and try it. I've
never tried the AMD64 version of FreeBSD. The libraries were a pain to maintain with the
AMD64 version of FC2 though. If you've used this architecture build, let me know how it
works. If you have a 64-bit AMD processor, it is backwards compatible with the x86
architecture, so you have something to fallback to if you want to have an adventure in 64-bit
computing.
As far as the ports collection is concerned, there are two methods to consider. If you don't
want to bother with manually installing only what you need, install the entire ports collection;
otherwise, perform a minimal install
» Update your ports collection. THIS IS IMPORTANT. If you do this PRIOR to building and
installing any software, you'll save time later by not having to upgrade.
» Make sure all of your hardware is recognized. You may want to install the nVidia or ATI
drivers if you're going to be using a desktop environment like KDE or Gnome
» Configure your ethernet interfaces
» Reboot and make sure that everything works and that you have internet access (by using
lynx to view a website, or a simple ping connectivity test)
Again, any collaboration would be appreciated. See the intro for contact details.
step 5Configuring your software
Here is a VERY brief overview of the configuration process.
» Install and configure OpenSSH for network terminal emulation. Pre-shared keys are
definately recommended, but not a requirement.
» Confirm SSH connectivity from another machine on the LAN using OpenSSH (*nix) or
PuTTY (Windows)
» Install and configure the ported version of OpenBSD's PF packet-filtering, stateful firewall.
You can take a look at pf.conf for an example of what your PF configuration file might look
like. Also, two great sources for information pertaining to PF are the PF User Guide and Peter
Hansteen's Firewalling with OpenBSD's PF packet filter . Thanks for the resource Peter!
» Install and configure any other software that you would like. I recommend the Squid
caching-proxy (installing as a reverse-proxy is nice too), Snort IDS (Intrusion Detection
System), ClamAV (antivirus) with vectoring through your firewall, Bruteforceblocker (SSH
bruteforce blocker), and Snarf (web interface for Snort logs).
Craig McLean was kind enough to let me integrate a how-to article on the same topic into
this one. We've agreed to post some of his article here. Please realize, he, like I, wrote this
article from memory. If you find any errors in it, please let us know. What follows is taken
directly from his howto.
Things to decide
You will need to decide what you want your internal network to look like when this is over,
and which machines should have access to what. This is not as complex as it sounds but it
benefits us to work it out in advance. In this guide I will use the following:
172.16.0.0/16 (172.16.0.1 to 172.16.255.254) Will be the internal network.172.16.3.200 Will
be the firewall's internal IP address.172.16.4.0/24 (172.16.4.1 to 172.16.4.254) will be
assigned to a DHCP range.
Things to know
» You will need to know what your internal- and external-facing interfaces and IP addresses
are.
» You will also need to know the IP address(es) of the DNS servers provided by your ISP.
» The FreeBSD device name for your internal/external interfaces. These are named like so:
The name of the driver used for the device followed by a number. This number is typically 0
(zero), but if you have multiple devices using the same drivers, each device will have a
unique number starting at zero and counting up. For example, two Realtek based NICs will
apear as rl0 and rl1. lo0 is your loopback device (IP 127.0.0.1). If you've configured pflog to
monitor your firewall, you'll see pflog0 here also. (John)
You may not know your external IP yet, but once the install is complete you should use:
# ifconfig -ato find it out.
If the IP assigned by your ISP is dynamic, you may need to setup DHCP on your external
interface. Use dhclient for this. Also, while using DHCP on your internal network is more
user-friendly, static IP addressing works just fine too. It can also make security audits more
straightforward. (John)
The pw command can also be used to add/modify/delete users and groups. (John)
Set up OpenSSH
OpenSSH (Open Secure SHell) should be your weapon of choice when connecting to your
new FreeBSD host. It's secure, included by default with the OS, and there are any number of
clients you can use to connect to it. Linux machines will have ssh by default, windows users
can get hold of PuTTY (www.chiark.greenend.org.uk/~sgtatham/putty/).
OpenSSH can be enabled on FreeBSD by editing /etc/rc.conf and making sure you have the
following:
sshd_enable="YES"in there.
Your machine will be on the internet, and people will try and get in. One of the ways they
will do this is to try to guess usernames and passwords, which ssh uses by default. If you
don't absolutely need ssh from the internet, make sure you only listen for connections on the
internal interface. Do this by editing the ssh daemon configuration file which lives at
/etc/ssh/sshd_config and make sure you have
ListenAddress 172.16.3.200in there, replacing 172.16.3.200 with the internal IP address we
decided on earlier.
If you decide that you need ssh access from the outside world, you should disable password-
based access and instead use publik-key authentication. Google will tell you how!
The Firewall
While Craig covers using IP Filter here, I will append a tutorial for using PF when I get the
chance. For now, you can refer to the PF Guide (openbsd.org/faq/pf/) and the sample
configuration file that i've attached (pf.conf). (John)
First, let me point you at another great URL, it's the renowned "ipf HOWTO":
www.obfuscation.org/ipf/. Keep it to hand as we go through these steps.
In a minute, "in" and "out" are going to have very specific meaning, but let's not worry about
that yet. Logically, we want to do the following:
» Allow internal IP traffic to the firewall machine.
» Redirect (where necessary) internal IP traffic to the internet.
» Redirect replies to internal traffic back to individual systems.
» Allow machines on the internet access to certain ports/services on the firewall.
» (maybe) Redirect access from machines on the internet to other machines on the local
network.
» Block everything else.
First we need to enable ipfilter. That needs the following in /etc/rc.conf
ipfilter_enable="YES"ipfilter_program="/sbin/ipf"ipfilter_rules="/etc/ipf.conf"ipfilter_flags=
""
This should be pretty self-explanatory, and the first thing to note is the location of the rules
file, /etc/ipf.conf . This is where all our rules will live.
From here onwards, "in" and "out" need to be used very carefully, as they refer to "in" and
"out" of a specific interface. Keep this in mind as we go on.
We decided earlier what logic we wanted, and can now translate that into rules:
# First, deny everything unless specified.block in on xl0 # Our internal interfaceblock out on
xl0block in on dc0 # Our external interfaceblock out on dc0# Allow our internal network to
come into the internal interfacepass in on xl0 from 172.16.0.0/16 to any# Allow our internal
interface to talk to the internal networkpass out on xl0 from 172.16.3.200 to any# Allow tcp
or udp from our external interface outwards to anywhere, keeping# a "state table" of
connections and assembling fragmented packetspass out on dc0 proto tcp/udp from any to
any keep state keep frags# Allow "ping" and its friends out from the external interfacepass
out on dc0 proto icmp from any to any## Services## We're going to be running a web server,
so we need port 80pass in on dc0 proto tcp from any to any port = 80 flags S keep frags keep
statepass in on dc0 proto tcp from any to any port = 443 flags S keep frags keep state#
Likewise sendmail, eventually. Leave it commented for now, though.# pass in on dc0 proto
tcp from any to any port = smtp flags S keep frags keep state# pass in on dc0 proto tcp from
any to any port = smtps flags S keep frags keep state
Those are the basics. You can start the firewall, using these rules, by issuing:
# /etc/rc.d/ipf startIf you change the rules, and want to reload the firewall tables, you can use:
# ipf -Fa -f /etc/ipf.confwhich translates as "Flush all, read new rules from file /etc/ipf.conf ".
If you want to clear out your firewall rules just use:
# ipf -FaTo view all rules for inbound packets:
# ipfstat -iand outbound:
# ipfstat -o
The 'ipf' functionality in FreeBSD is huge. This has only just scratched the surface of what is
possible, or desirable. There's more info in the manpages, and at the link at the beginning of
this section. I strongly suggest you take a look at both.
Warning: Think very hard before changing firewall rules if you are connected over TCP/IP.
You may find if hard to recover if you get it wrong, and suddenly find yourself
disconnected :-)
The NAT
Next we want to set up Network Address Translation for other devices on our internal
network. NAT allows many internal clients to share one internet address.
To do this, we need to add some more lines to /etc/rc.conf:
gateway_enable="YES"ipnat_enable="YES"ipnat_program="/sbin/ipnat"ipnat_rules="/etc/ip
nat.rules"ipnat_flags=""Pretty much like the firewall stuff, but this time the rules are in
/etc/ipnat.rules.
NAT is really easy to set up. We want to allow anything on 172.16.0.0/16 to use the internet,
so our rule is:
map dc0 172.16.0.0/16 -> dc0/32 portmap tcp/udp automap dc0 172.16.0.0/16 -> dc0/32
proxy port ftp ftp/tcpThe first line maps internet access outbound on dc0 to appear from
"dc0/32", which is shorthand for "the IP address currently associated with the interface dc0".
The second line will proxy outbout ftp access. This is necessary if you don't want to have to
use passive ftp all the time because the ftp protocol sucks.
# cd /usr/ports/net/isc-dhcp3-server# make
From the menu, select whichever options you want (I'd recommend at least PARANOIA and
JAIL)
# make install# cd /usr/local/etc# mv dhcpd.conf.sample dhcpd.conf
Then edit the dhcpd.conf file, so it looks like this:
ddns-update-style none;log-facility local7;shared-network Dynamic-4-subnet {option routers
172.16.3.200;option domain-name-servers nnn.nnn.nnn.nnn;subnet 172.16.0.0 netmask
255.255.0.0 {range 172.16.4.1 172.16.4.100;}
You will need to substitute nnn.nnn.nnn.nnn with your ISP's domain name servers.
Then ensure /etc/rc.conf contains:
dhcpd_enable="YES"and start the dhcp server using
# /usr/local/etc/rc.d/isc-dhcpd.sh start
Thanks Craig, I appreciate the help. While my home network is a little different than Craigs,
the same still applies. Here is how mine is setup:
» Cisco uBR900 cable modem provides connectivity to the internet.
» The modem is connected to my firewall. The WAN IP on the firewall is assigned by DHCP
from the modem.
» The LAN network is 192.168.0.0/16 and static (no DHCP)
» My firewall connects to a 24port switch. This is connected to a 108Mbps 802.11g D-link
WAP and an 8port gigabit switch. The WAP has a static IP, but provides wireless access
through DHCP.
» My firewall provides no internal protection. All internal traffic moves unprohibitted by the
firewall. This includes outbound traffic also. While this may not be the most secure, it is
definitely easier to manage. I don't have to add firewall rules everytime I want to access a
new service.
i
step 6Packet Prioritization
Packet Prioritization with ALTQ
If your WAN connection stays fairly saturated (with things like bittorrent), then I'm sure
you've experienced your fair share of timeouts, lag, or slow page loads. Packet prioritzation
offers a solution to this problem. Instead of spending $100+ on a router that has this feature,
you can instead use ALTQ with PF to accomplish the same thing.
ALTQ is very easy to setup. The most complicated thing you have to do is recompile your
kernel. Don't worry, it's much easier than you think. Just follow my instructions, and you
should be fine. A new kernel is required, because ALTQ support is disabled by default in
FreeBSD.
I'll be using the "new" method. After duplicating the GENERIC kernel configuration file, edit
it with your favorite editor (pico is great for beginners). Now, add the folowing lines to the
end of the file:
#ALTQ OPTIONSoptions ALTQoptions ALTQ_CBQ # CLASS BASES QUEINGoptions
ALTQ_RED # RANDOM EARLY DETECTIONoptions ALTQ_RIO # RED
IN/OUToptions ALTQ_HFSC # HIERARCHIAL PACKET SCHEDULERoptions
ALTQ_PRIQ # PRIORITY QUEUINGoptions ALTQ_NOPCC # REQUIRED FOR SMP
BUILDNow save the file (I called mine FIREWALLKERNEL), then follow these steps
(from the handbook) to compile it:
Configuring ALTQ
ALTQ supports two kinds of packet prioritization: class-based (CBQ) and priority-based
(PRIQ).
Class-based queueing divides trafic into "classes". A specific portion of your overall
bandwidth is then allocated to each one of these classes.
Priority-based queueing, like it's name suggests, assigns priorities to packets. The packets
with the highest priority are processed first.
There are also a few additional features that you have at your disposal: random early
detection and explicit congestion notification (ECN).
Random early detection, or RED, calculates the average queue size, then drops or forwards
packets depending on the level of congestion. If the average queue size is above a maximum
threshold, all packets will be dropped. If the queue size is below a minimum threshold, no
packets will be dropped. Anywhere between these thresholds, and packets will be dropped
depending on how close the queue size is to the upper and lower thresholds.
Explicit congestion notification, or ECN, sets a flag in packets to notifiy hosts of network
congestion. When a host that supports ECN receives a packet marked with this flag, it
responds by throttling back it's activity.
Now that I've determined my priority levels, it's time to actually assign them to my firewall
rules. This is very easy. Simply add "queue <queue_name>" to the end of any rules that you
would like to assign to the priority level identified by <queue_name>.
And that's it. Packet prioritization is that simple. Leave me a comment to let me know if this
helps anyone. It has definately helped me.
UPS's
If you experience frequent power surges, power outages, or even if you don't a UPS
(Uninteruptable Power Supply) can save you many headaches. FreeBSD doesn't like being
shutdown instantaneously. Often times, this leads to corrupted data. While most of the time
(in my experience atleast) this can be fixed by running `fsck` in single-user mode with your
disks unmounted, a UPS will eliminate this problem alltogether. Unless your power goes out
for a prolonged amount of time, a UPS will provide reliable power to your firewall to keep it
running smoothly. There are two different types of UPS's: offline (or standby) and online.
Offline UPS's provide power from the outlet until they sense a power outtage, in which case
they switch over to battery power. Online powersupplies have a zero switchover time (the
amount of time it takes between loss of mains power and when stable power is supplied by
the UPS) because they use inverters. Online UPS's are a little more expensive than offline
UPS's, but more reliable. Offline UPS's will work fine though, so long as they have a low
switchover time.
RTFM
The FreeBSD Handbook is the single-most important resource when working with FreeBSD.
Just point your browser to www.freebsd.org/docs.html and click on "Handbook". Google is
also another valuable resource. The best (and most enjoyable IMO) way to learn how to use
FreeBSD, or any flavor of Linux or Unix, is by doing the research yourself and diving right
in. You'll screw your system up, curse everyone and their mother, and possibly become an
alcoholic because of it, but you'll be that much more elite once you figure it out. As a last
resort, try some the IRC channels on Dalnet or Freenode. When resorting to chatrooms, be
expecting insulting comments and a few "RTFM"s.
Other uses
I also build a NAS (Network Accessible/attached Storage) device using a more modern AMD
K8, 512MB of PC3200 DDR-RAM, and a few gigabit ethernet NICs. This system is more
than enough to provide reliable streaming media, file serving capabilities, and SVN
repositories to anyone with wired, wireless, or VPN access to our LAN. We've even setup
dynamic DNS services to provide internet access to our media through a custom web
interface. Eventually, we will release the MyNAS project to provide a user-friendly interface
to the NAS and an out-of-the-box file-sharing community.