Westbo Linux User Group






Setting Up A Linux Firewall



* Introduction

This article is about setting up a Linux PC for use as a firewall between
the Internet and a local network.  Some knowledge of TCP/IP networking
is assumed.  The reader should also be familiar with the theory behind
firewalls.  If not, it might be a good idea to do some reading here first.
There are two types of firewall in use on Linux.  The first type is a
filtering firewall.  Packets are allowed or denied according to a rule-set.
The other type is the proxy firewall.  This blocks off the internal network
from the external network entirely, and provides proxy services as requested
to the internal network.  There is a distinction between two types of
proxy firewall: firstly, application proxy gateway, secondly circuit level
relay.  In this article, we will be setting up a basic filtering firewall.
For more information about the other sort, see the Firewalling and Proxy
Server HOWTO at http://sunsite.unc.edu/LDP/HOWTO/Firewall-HOWTO.html.

* Installation

** Hardware Requirements

Any PC capable of running Linux can be used as a firewall.  There are
certain features that a firewall relies on more than others.  In particular,
a proxying firewall's hardware needs are determined by the requirements of
the services for which it provides proxy support.  For example, providing
WWW proxy support can demand plenty of RAM and high-performance hard disk
space, depending on how much caching is done.  However, for the filtering
firewall which we be examining in this article, any PC capable of running
Linux should od the job adequetely.  Here, the most important area to look
at if performance is an issue are the speed of the network interfaces.

** The Software

Using a Linux box as a firewall can be done either by using the built-in
firewall capability, or by installing additional packages.  This article
looks specifically at turning a Linux machine into a packet-filtering
router, using the facilities built in to the Linux kernel, and one piece
of additional software to administer the set-up.  One could write one's own
programs to do the administering: the task is simple, and can be done using
any language supporting the setsockopt(2) system call: but why re-invent
the wheel?  I will be using the ipfwadm program to do this.

** Network

Your linux box must be connected to the local network, and set up to connect
to the external network (presumably the Internet).  An earlier article
has shown you how to do this.  Here, we assume that both connections are
up and running.

** Kernel

The Linux kernel needs to be compiled with certain options enabled
in order to use the firewalling code.  Most generic kernels i.e. the
type usually supplied with a distribution, will have these  options
turned off, so that it is necessary to recompile the kernel.  This is
a simple task, and we will quickly run through the steps here.
If you need more details on this, see the Linux Kernel HOWTO, at
http://sunsite.unc.edu/LDP/HOWTO/Kernel-HOWTO.html.

*** Configuring The Kernel

The Linux kernel is configured by the ``make config'' command, which will
prompt you with all the kernel options, supplying a sensible default which
it is safe to take if the option means nothing to you.  The following
options must be switched on:

    CONFIG_FIREWALL
    CONFIG_INET
    CONFIG_IP_FORWARD
    CONFIG_IP_FIREWALL
    CONFIG_IP_ACCT

It is also advisable to set the following option on, to get maximum benefit
from the system logs:

    CONFIG_IP_FIREWALL_VERBOSE

If you will be doing masquerading (q.v.) through the firewall, then these
options should also be set:

    CONFIG_IP_MASQUERADE
    CONFIG_IP_ALWAYS_DEFRAG	(ideally)

*** Recompiling The Kernel

The following command sequence will re-compile the kernel.

    make dep && make clean && make zImage

Modules can be compiled by

    make modules

This may be necessary if IP masquerading is to be done (see below).

*** Installing the New Kernel

The following sequence of commands copies the new kernel image and its
associated symbol table to the root directory, and reruns lilo so that the
boot loader knows about the new kernel (it presumes the lilo config. file
is in the default location, ``/etc/lilo.conf'').

    cp /usr/src/linux/arch/i386/boot/zImage /
    cp /usr/src/linux/System.map /
    /sbin/lilo

** Getting ipfwadm

The software package we will be using to administer the firewall, ipfwadm,
is is available http://simba.xos.nl/linux/ipfwadm/ in source and binary form.
It is very easy to compile and install.

* Configuration

*** Rule-sets

The core of firewall functionality is contained in the rule-sets that
determine what happens to packets.  There are four types of rule-set: those
governing input, those governing output, those in charge of forwarding,
and those controlling accounting.  Rather than bludgeoning the reader
with a great list of options and arguments that ipfwadm can take, we will
introduce the most important gradually through examples.  The man page
provides more details on the more esoteric arguments.

In the examples that follow, we shall construct a firewall machine that
is connected to the local network via interface 192.168.1.1, and to the
Internet via 192.168.20.1 (obviously, a made-up number for illustration
only).  The system acts as a mail relay hub for the local network, as a
router for the local network, provides local DNS services, and provides
WWW and ftp services.

**** Blocking

The blocking rules control going directly to or from the firewall itself.
In what follows, I will build up step by step a set of blocking rules for
our basic firewall.  With ipfwadm, blocking rules are controlled by two
parameters: -I for input rules and -O for output rules.

Firstly, we block everything!  The idea here is that we deny access
wherever we do not explicitly permit it.

    ipfwadm -I -p deny
    ipfwadm -O -p deny

The -p option sets the default policy, which will be used when no matching
rule is found.  So, as it stands, our firewall will reject all packets
coming in or going out.  Obviously, this won't do!  So, we will add some
rules to selectively allow traffic to and from the firewall.  First though,
we need a way of protecting ourselves from packet spoofing.  The following
two rules will ensure that we do not fall victim to such attacks:

For a start, we can allow packets between the firewall and our local network.

    ipfwadm -I -a accept -V 192.168.1.1 -S 0.0.0.0/0 -D 0.0.0.0/0
    ipfwadm -O -a accept -V 192.168.1.1 -S 0.0.0.0/0 -D 0.0.0.0/0

Here, we see the use of the -I and -O categories, to control what direction
of traffic our rule will be applied to.  The -V option states that only
traffic originating from that interface will be affected by this rule.
So, other traffic from outside our local network, and thus by definition not
passing through this interface, will continue to be subject to the blanket
ban we set up earlier.  In this example, I have assumed that the network card
connecting our firewall to the local network has the address 192.168.1.1.

Now, in one fell swoop, we add SMTP, FTP, WWW and DNS access to the firewall
machine from anywhere.

   ipfwadm -I -a accept -P tcp -S 0.0.0.0/0 -D $LOCALHOST smtp ftp www domain
   ipfwadm -I -a accept -P udp -S 0.0.0.0/0 -D $LOCALHOST domain
   ipfwadm -I -a accept -k -P tcp S 0.0.0.0/0 -D $LOCALHOST ftp-data
   ipfwadm -O -a accept -P tcp -S $LOCALHOST smtp ftp ftp-data www domain -D 0.0.0.0/0
   ipfwadm -O -a accept -P udp -S $LOCALHOST domain -D 0.0.0.0/0

Since we intend to allow traffic to be forwarded to and from the internal
network, we must also add some input and output rules to allow for this,
in addition to the forwarding rules in the next section.

   ipfwadm -I -a accept -k -P tcp -S 0.0.0.0/0 ftp www telnet domain -D 192.168.1.0 1024:65535

   ipfwadm -I -a accept -k -P tcp -S 0.0.0.0/0 ftp www telnet domain -D 192.168.20.1 1024:65535

   ipfwadm -I -a accept -P tcp -S 0.0.0.0/0 ftp-data -D 192.168.1.0 1024:65535

   ipfwadm -I -a accept -P tcp -S 0.0.0.0/0 ftp-data -D 192.168.20.1 1024:65535

   ipfwadm -O -a accept -P tcp -S 192.168.1.0 1024:65535 -D 0.0.0.0/0 smtp ftp ftp-data www telnet domain

   ipfwadm -O -a accept -P tcp -S 192.168.20.1 1024:65535 -D 0.0.0.0/0 smtp ftp ftp-data www telnet domain

Firstly, we allow input TCP packets from anywhere into our local network,
provided they are from our allowed services.  We also allow UDP packets
to the name server.  The -k option says to only allow packets with the ACK
bit set.  Then, we have two output rules, again, one for TCP, one for UDP.
These should be easy to understand now, as they are but the mirror-image
of the input rules.

We might also allow the machine to talk to itself, via localhost:

    ipfwadm -I -a accept -V 127.0.0.1 -S 127.0.0.1 -D 127.0.0.1
    ipfwadm -O -a accept -V 127.0.0.1 -S 127.0.0.1 -D 127.0.0.1

This is neither necessary nor desirable on a pure packet-filtering firewall,
but can be useful on a machine where firewalling has been added as one task
among others.  Of course, such is not an ideal firewall configuration,
but it may be adequate for sites without any great security risks.

**** Forwarding

The forwarding rules control which packets will be forwarded by the
firewall.  In addition, our forwarding rules must take care of masquerading.
As mentioned above in the section on routing, we are using ``private''
I.P. numbers for our network, and we cannot allow packets with source
addresses set to these numbers out onto the Internet.  Therefore, our
firewall will ``masquerade'' as these other machines for the purposes of
sending packets to and from the Internet.

Once again, we start by denying everything, before explicitly allowing
some sorts of traffic.

    ipfwadm -F -p deny

-F tells us that this is a forwarding rule. ``-p deny'' we have seen before:
once again, we set the default policy to deny everything, then explicitly
allow the services we wish to permit.

***** Standard Forwarding

Now, we have four rules that determine the type of traffic that will be
forwarded from the internet network to the Internet, and vice versa.
The first rule is a general one that allows all TCP traffic from the
internal network to the Internet for ftp, www and telnet.  The second rule
allows all outbound UDP traffic.  The third rule allows inbound TCP traffic
for ftp, www and telnet.  Note here the use of the -k option, to specify
that the ACK bit must be set.  This allows traffic only in response to
connections  initiated from our local network --- no one is allowed to
initiate connections from outside.  The fourth rule is a special case,
allowing inbound ftp traffic on the data connection (hence ftp-data)
without the ACK-bit set.

   ipfwadm -F -a accept -P tcp -S 192.168.1.0 1024:65535 -D 0.0.0.0/0 ftp ftp-data www telnet 

   ipfwadm -F -a accept -P udp -S 192.168.1.0 1024:65535 -D 0.0.0.0/0

   ipfwadm -F -a accept -k -P tcp -S 0.0.0.0/0 ftp www telnet -D 192.168.1.0 1024:65535

   ipfwadm -F -a accept -P tcp -S 0.0.0.0/0 ftp-data -D 192.168.1.0 1024:65535

-P specifies the protocol involved.  The numeric argument after the
network/port source is the range of non-privileged ports this operation
is permitted to use.  The destination is set to ``any''.  The -k option,
as already explained, allows only packets with the ACK bit set.

***** Masquerading

The previous rules were applicable only in the case of a network with
registered I.P. addresses.  Many small networks not previously connected to
the Internet, however, use one of the ranges allocated in RFC 1597.  A Linux
firewall provides a way to continue using the existing I.P. addresses
of this type. This is done using a technique called masquerading.
In masquerading, packets from the internal network are altered on the
firewalling host to make them look as if they originated on that host.
Specifically, the source IP address is replaced by the local IP address and
the source port is replaced by a locally-generated port.  Incoming packets
to that port will then be automatically ``demasqueraded'' and forwarded
to the system that originally initiated the connection.

ipfwadm uses the -m option to switch on masquerading.  So, our four
forwarding rules now look as follows:

   ipfwadm -F -m -a accept -P tcp -S 192.168.1.0 1024:65535 -D 0.0.0.0/0 ftp ftp-data www telnet 

   ipfwadm -F -m -a accept -P udp -S 192.168.1.0 1024:65535 -D 0.0.0.0/0

   ipfwadm -F -m -a accept -k -P tcp -S 0.0.0.0/0 ftp www telnet -D 192.168.1.0 1024:65535

   ipfwadm -F -m -a accept -P tcp -S 0.0.0.0/0 ftp-data -D 192.168.1.0 1024:65535

Here, the -m option turns on masquerading.  -P specifies the protocol
involved.  The numeric argument after the network/port source is the range
of non-privileged ports this operation is permitted to use.  The destination
is set to ``any''.  The -k option, as already explained, allows only packets
with the ACK bit set.

Some protocols need special care e.g. ftp.  The Linux IP masquerading
implementation deals with such protocol-specific features in
separately-loadable modules.  For example, to enable ftp masquerading,
the module supporting this must be loaded.  This is done like so:

    insmod /usr/src/linux/modules/ip_masq_ftp.o

Of course, the modules must have been built first.   this is done by 

    make modules

in the linux source directory, typically /usr/src/linux.

As it stands, these rules do not allow ICMP packets to be masqueraded,
nor indeed to be forwarded at all.  This is not generally necessary in
any case.  Should you wish to provide access from behind the firewall
to services that use ICMP packets e.g. ping, then there is an additional
kernel option, CONFIG_IP_MASQUERADE_ICMP, that must be set on.

**** Accounting

The accounting rules are used to build up packet and byte counts for
selected traffic.  There is a single set, used for both incoming and
outgoing traffic.  Every packet is checked against each rule, and the
counts of each matching rule incremented.  The counts are stored in
/proc/net/ip_acct.

IP accounting rules
00000000/00000000->00000000/00000000 - 00000000 40 0 0 337       19673     0 0 0 0 0 0 0 0 0 0 AFF X00

ipfwadm controls accounting with the -A option.  A direction can be
specified (in, out, or both; default both) indicating whether only
packets in the specified direction should be counted.  For example,
the following keeps track of all traffic.

    ipfwadm -A -b 

The statistics can then be listed with

    ipfwadm -A -l

Output looks like this:

    tiny1:/root# ipfwadm -A -l
    IP accounting rules
    pkts bytes dir prot source               destination          ports
     467 27269 i/o all  anywhere             anywhere             n/a

Here, we can see total packet and byte counts for both directions (dir),
all protocols (prot), for all network addresses,  for any ports.

Of course, it is more useful if we specify different types of traffic
to be monitored, so we can keep separate sets of statistics for them.
For example, the following rule would keep statistics for all http traffic
generated by connections to your web server:

    ipfwadm -A -a -b -P tcp -S 0.0.0.0/0 -D 0.0.0.0/0 www

Which gives log records like this: 

   pkts bytes dir prot source               destination          ports
     40 13582 i/o tcp  anywhere             anywhere             any -> www

* Conclusion

This article has shown you how to set up a Linux box as a combined router
and firewall, using the network capabilities built in to the Linux kernel.
It does not attempt to provide a complete, robust firewalling solution;
but it will prove sufficient for sites without major security concerns.
It is particularly suited for internal firewalls, where the main concern
is simply to put a block between sections of the internal network, without
having to worry about threats from outside.

Tillbaka till startsidan