freebsd-dev/share/doc/handbook/firewalls.sgml
1996-01-31 19:03:02 +00:00

526 lines
20 KiB
Plaintext

<!-- $Id: firewalls.sgml,v 1.3 1996/01/31 14:26:06 mpp Exp $ -->
<!-- The FreeBSD Documentation Project -->
<sect><heading>Firewalls<label id="firewalls"></heading>
<p><em>Contributed by &a.gpalmer;.<newline>4th of October 1995</em>
Firewalls are an area of increasing interest for people who are
connected to the Internet, and are even finding applications on
private networks to provide enhanced security. This section will
hopefully explain what firewalls are, how to use them, and how to use
the facilities provided in the FreeBSD kernel to implement them.
<quote><bf>Note</bf>: People often think that having a firewall between
your companies internal network and the ``Big Bad Internet'' will
solve all your security problems. It may help, but a poorly setup
firewall system is more of a security risk than not having one at all.
A firewall can only add another layer of security to your systems, but
they will not be able to stop a really determined hacker from
penetrating your internal network. If you let internal security lapse
because you believe your firewall to be impenetrable, you have just
made the hackers job that bit easier.</quote>
<sect1><heading>What is a firewall?</heading>
<p>There are currently two distinct types of firewalls in common
use on the Internet today. The first type is more properly called
a <bf>packet filtering router</bf>, where the kernel on a
multi-homed machine chooses whether to forward or block packets
based on a set of rules. The second type, known as <bf>proxy
servers</bf>, rely on daemons to provide authentication and to
forward packets, possibly on a multi-homed machine which has
kernel packet forwarding disabled.
<p>Sometimes sites combine the two types of firewalls, so that only a
certain machine (known as a <bf>bastion host</bf>) is allowed to send
packets through a packet filtering router onto an internal
network. Proxy services are run on the bastion host, which are
generally more secure than normal authentication mechanisms.
<p>FreeBSD comes with a kernel packet filter (known as <tt>IPFW</tt>),
which is what the rest of this section will concentrate on. Proxy
servers can be built on FreeBSD from third party software, but there
is such a variety of proxy servers available that it would be
impossible to cover them in this document.
<sect2><heading>Packet filtering routers<label id="firewalls:packet_filters"></heading>
<p>A router is a machine which forwards packets between two or more
networks. A packet filtering router has an extra piece of code in its
kernel, which compares each packet to a list of rules before deciding
if it should be forwarded or not. Most modern IP routing software has
packet filtering code in it, which defaults to forwarding all
packets. To enable the filters, you need to define a set of rules for
the filtering code, so that it can decide if the packet should be
allowed to pass or not.
<p>To decide if a packet should be passed on or not, the code looks
through its set of rules for a rule which matches the contents of
this packets headers. Once a match is found, the rule action is
obeyed. The rule action could be to drop the packet, to forward the
packet, or even to send an ICMP message back to the originator. Only
the first match counts, as the rules are searched in order. Hence, the
list of rules can be referred to as a ``rule chain''.
<p>The packet matching criteria varies depending on the software used,
but typically you can specify rules which depend on the source IP
address of the packet, the destination IP address, the source port
number, the destination port number (for protocols which support
ports), or even the packet type (UDP, TCP, ICMP, etc).
<sect2><heading>Proxy servers<label id="firewalls:proxy_servers"></heading>
<p>Proxy servers are machines which have had the normal system daemons
(telnetd, ftpd, etc) replaced with special servers. These servers are
called <bf>proxy servers</bf> as they normally only allow onward
connections to be made. This enables you to run (for example) a proxy
telnet server on your firewall host, and people can telnet in to your
firewall from the outside, go through some authentication mechanism,
and then gain access to the internal network (alternatively, proxy
servers can be used for signals coming from the internal network and
heading out).
<p>Proxy servers are normally more secure than normal servers, and
often have a wider variety of authentication mechanisms available,
including ``one-shot'' password systems so that even if someone
manages to discover what password you used, they will not be able to use
it to gain access to your systems as the password instantly
expires. As they do not actually give users access to the host machine,
it becomes a lot more difficult for someone to install backdoors
around your security system.
<p>Proxy servers often have ways of restricting access further, so
that only certain hosts can gain access to the servers, and often they
can be set up so that you can limit which users can talk to which
destination machine. Again, what facilities are available depends
largely on what proxy software you choose.
<sect1><heading>What does <tt>IPFW</tt> allow me to do?</heading>
<p><tt>IPFW</tt>, the software supplied with FreeBSD, is a packet
filtering and accounting system which resides in the kernel, and has a
user-land control utility, <tt>ipfw(8)</tt>. Together, they
allow you to define and query the rules currently used by the kernel
in its routing decisions.
<p>There are two related parts to <tt>IPFW</tt>. The firewall section
allows you to perform packet filtering. There is also an IP accounting
section which allows you to track usage of your router, based on
similar rules to the firewall section. This allows you to see (for
example) how much traffic your router is getting from a certain
machine, or how much WWW (World Wide Web) traffic it is forwarding.
<p>As a result of the way that <tt>IPFW</tt> is designed, you can use
<tt>IPFW</tt> on non-router machines to perform packet filtering on
incoming and outgoing connections. This is a special case of the more
general use of <tt>IPFW</tt>, and the same commands and techniques
should be used in this situation.
<sect1><heading>Enabling <tt>IPFW</tt> on FreeBSD</heading>
<p>As the main part of the <tt>IPFW</tt> system lives in the kernel, you will
need to add one or more options to your kernel configuration
file, depending on what facilities you want, and recompile your kernel. See
<ref id="kernelconfig" name="reconfiguring the kernel"> for more
details on how to recompile your kernel.
<p>There are currently three kernel configuration options
relevant to IPFW:
<descrip>
<tag/options IPFIREWALL/ Compiles into the kernel the code for packet
filtering.
<tag/options IPFIREWALL_VERBOSE/ Enables code to allow logging of
packets through <tt>syslogd(8)</tt>. Without this option, even if you
specify that packets should be logged in the filter rules, nothing
will happen.
<tag/options IPACCT/ Turns on the IP accounting facilities.
</descrip>
<sect1><heading>Configuring <tt>IPFW</tt></heading>
<p>The configuration of the <tt>IPFW</tt> software is done through the
<tt>ipfw(8)</tt> utility. The syntax for this command looks
quite complicated, but it is relatively simple once you understand
its structure.
<p>There are currently two different command line formats for the
utility, depending on what you are doing. The first form is used when
adding/deleting entries from the firewall or accounting chains, or
when clearing the counters for an entry on the accounting chain. The
second form is used for more general actions, such as flushing the
rule chains, listing the rule chains or setting the default policy.
<sect2><heading>Altering the <tt>IPFW</tt> rules</heading>
<p>The syntax for this form of the command is:
<tscreen>
ipfw [-n] <em>command</em> <em>action</em> <em>protocol</em> <em>addresses</em>
</tscreen>
<p>There is one valid flag when using this form of the command:
<descrip>
<tag/-n/Do not attempt to resolve given addresses.
</descrip>
The <em>command</em> given can be shortened to the shortest unique
form. The valid <em>commands</em> are:
<descrip>
<tag/addfirewall/Add an entry to the firewall rule list
<tag/delfirewall/Delete an entry from the firewall rule list
<tag/addaccounting/Add an entry to the accounting rule list
<tag/delaccounting/Delete an entry from the accounting rule list
<tag/clraccounting/Clear the counters for an accounting rule entry.
</descrip>
If no command is given, it will default <bf>addfirewall</bf> or
<bf>addaccounting</bf> depending on the arguments given.
<p>Currently, the firewall support in the kernel applies a set of
weights to the rule being added. This means that the rules will
<em>not</em> be evaluated in the order that they are given to the
system. The weighting system is designed so that rules which are very
specific are evaluated first, and rules which cover very large ranges
are evaluated last. In other words, a rule which applies to a specific
port on a specific host will have a higher priority than a rule which
applies to that same port, but on a range of hosts, or that host on a
range of ports.
<p>The weighting system is not perfect, however, and can lead to
problems. The best way to see what order it has put your rules in is
to use the <bf>list</bf> command, as that command lists the rules in
the order that they are evaluated, not the order that they were fed to
the system.
<p>The <em>actions</em> available depend on which rule chain the
entry is destined for. For the firewall chain, valid
<em>actions</em> are:
<descrip>
<tag/reject/Drop the packet, and send an ICMP HOST_UNREACHABLE or
ICMP PORT_UNREACHABLE (as appropriate) packet to the source.
<tag/lreject/As <bf>reject</bf>, but also log the packet details.
<tag/deny/Drop the packet.
<tag/ldeny/As <bf>deny</bf>, but also log the packet details.
<tag/log/Log the packets details and pass it on as normal.
<tag/accept/Pass the packet on as normal.
<tag/pass/Synonym for <bf>accept</bf>.
</descrip>
For the accounting chain, valid <em>actions</em> are:
<descrip>
<tag/single/Count packets matching the address specifier.
<tag/bidirectional/Count packets matching the address specifier, and
also packets traveling in the opposite direction (i.e. those going
from ``destination'' to ``source'').
</descrip>
<p>Each <em>action</em> will be recognized by the shortest unambiguous
prefix.
The <em>protocols</em> which can be specified are:
<descrip>
<tag/all/Matches any IP packet
<tag/icmp/Matches ICMP packets
<tag/tcp/Matches TCP packets
<tag/udp/Matches UDP packets
<tag/syn/Matches the TCP SYN (synchronization) packet used during TCP
connection negotiation. You can use this to block ``incoming'' TCP
connections, but allow ``outgoing'' TCP connections.
</descrip>
<p>The <em>address</em> specification is:
<tscreen>
&lsqb;<bf>from</bf> &lt;<em>address/mask</em>&gt;&lsqb;<em>port</em>&rsqb;&rsqb; &lsqb;<bf>to</bf>
&lt;<em>address/mask</em>&gt;&lsqb;<em>port</em>&rsqb;&rsqb; &lsqb;<bf>via</bf> &lt;<em>interface</em>&gt;&rsqb;
</tscreen>
<p>You can only specify <em>port</em> in conjunction with
<em>protocols</em> which support ports (UDP, TCP and SYN).
<p>The order of the <bf>from</bf>, <bf>to</bf>, and
<bf>via</bf> keywords is unimportant. Any of them can be omitted,
in which case a default entry for that keyword will be supplied which
matches everything.
<p>The <bf>via</bf> is optional and may specify the IP address or
domain name of a local IP interface, or an interface name (e.g.
<tt>ed0</tt>) to match only packets coming through this interface. The
keyword <bf>via</bf> can be substituted by <bf>on</bf>, for
readability reasons.
<p>The syntax used to specify an <tt>&lt;address/mask&gt;</tt> is:
<tscreen>
&lt;address&gt;
</tscreen>
or
<tscreen>
&lt;address&gt;/mask-bits
</tscreen>
or
<tscreen>
&lt;address&gt;:mask-pattern
</tscreen>
<p>A valid hostname may be specified in place of the IP
address. <tt>mask-bits</tt> is a decimal number representing how many
bits in the address mask should be set. e.g. specifying
<tscreen>
192.216.222.1/24
</tscreen>
will create a mask which will allow any address in a class C subnet
(in this case, 192.216.222) to be matched. <tt>mask-pattern</tt> is an IP
address which will be logically AND'ed with the address given. The
keyword <tt>any</tt> may be used to specify ``any IP address''.
<p>The port numbers to be blocked are specified as:
<tscreen>
port&lsqb;,port&lsqb;,port&lsqb;...&rsqb;&rsqb;&rsqb;
</tscreen>
to specify either a single port or a list of ports, or
<tscreen><verb>
port:port
</verb></tscreen>
to specify a range of ports. The name of a service (from
<em>/etc/services</em>) can be used instead of a numeric port value.
<sect2><heading>Listing/flushing the <tt>IPFW</tt> rules</heading>
<p>The syntax for this form of the command is:
<tscreen>
ipfw &lsqb;-ans&rsqb; <em>command</em> &lsqb;<em>argument</em>&rsqb;
</tscreen>
<p>There are three valid flags when using this form of the command:
<descrip>
<tag/-a/While listing, show counter values. This option is the only
way to see accounting counters. Works only with <bf>-s</bf>.
<tag/-n/Do not attempt to resolve given addresses.
<tag/-s/Use short listing form. This should be used with <bf>-a</bf>
to see accounting counters. The short form listing is incompatible
with the input syntax used by the <tt>ipfw(8)</tt> utility.
</descrip>
The <em>command</em> given can be shortened to the shortest unique
form. The valid <em>commands</em> are:
<descrip>
<tag/list/List the chain rule entries. Unless the <bf>-s</bf> flag is
given, the format is compatible with the command line syntax.
<tag/flush/Flush the chain rule entries.
<tag/zero/Clear counters for the entire accounting chain.
<tag/policy/Set or display the default policy for the firewall
code. Without an argument, the current policy will be displayed.
</descrip>
The <bf>list</bf> and <bf>flush</bf> commands may optionally be passed
an <em>argument</em> to specify which chain to flush. Valid arguments are:
<descrip>
<tag/firewall/The packet filter chain.
<tag/accounting/The accounting chain.
</descrip>
<p>The <bf>policy</bf> command can be given one of two arguments:
<descrip>
<tag/accept/If a packet is not matched by any rule, pass it on.
<tag/deny/If a packet is not matched by any rule, do not pass it on.
</descrip>
As usual, the arguments can be shortened to the shortest unique form
(in this case, the first letter).
<sect1><heading>Example commands for ipfw</heading>
<p>This command will deny all packets from the host
<bf>evil.hacker.org</bf> to the telnet port of the host
<bf>nice.people.org</bf> by being forwarded by the router:
<tscreen><verb>
ipfw addf deny tcp from evil.hacker.org to nice.people.org telnet
</verb></tscreen>
<p>The next example denies and logs any TCP traffic from the entire
<bf>hacker.org</bf> network (a class C) to the <bf>nice.people.org</bf>
machine (any port).
<tscreen><verb>
ipfw addf ldeny tcp from evil.hacker.org/24 to nice.people.org
</verb></tscreen>
If you do not want people sending X sessions to your internal network
(a subnet of a class C), the following command will do the necessary
filtering:
<tscreen><verb>
ipfw addf deny syn to my.org/28 6000
</verb></tscreen>
To allow access to the SUP server on <bf>sup.FreeBSD.ORG</bf>, use the
following command:
<tscreen><verb>
ipfw addf accept syn to sup.FreeBSD.ORG supfilesrv
</verb></tscreen>
To see the accounting records:
<tscreen><verb>
ipfw -sa list accounting
</verb></tscreen>
or in the short form
<tscreen><verb>
ipfw -sa l a
</verb></tscreen>
<sect1><heading>Building a packet filtering firewall</heading>
<p><quote><bf>Note:</bf> The following suggestions are just that:
suggestions. The requirements of each firewall are different and I
cannot tell you how to build a firewall to meet your particular
requirements.</quote>
<p>When initially setting up your firewall, unless you have a test
bench setup where you can configure your firewall host in a controlled
environment, I strongly recommend you use the logging version of the
commands and enable logging in the kernel. This will allow you to
quickly identify problem areas and cure them without too much
disruption. Even after the initial setup phase is complete, I
recommend using the logging for of `deny' as it allows tracing of
possible attacks and also modification of the firewall rules if your
requirements alter.
<quote><bf>Note:</BF> If you use the logging versions of the
<bf>accept</bf> command, it can generate <em>large</em> amounts
of log data as one log line will be generated for every packet
that passes through the firewall, so large ftp/http transfers,
etc, will really slow the system down. It also increases the
latencies on those packets as it requires more work to be done by
the kernel before the packet can be passed on. syslogd with also
start using up a lot more processor time as it logs all the extra
data to disk, and it could quite easily fill the partition
<tt>/var/log</tt> is located on.</quote>
<p>As currently supplied, FreeBSD does not have the ability to
load firewall rules at boot time. My suggestion is to put a call
to a shell script in the <tt>/etc/netstart</tt> script. Put the
call early enough in the netstart file so that the firewall is
configured before any of the IP interfaces are configured. This
means that there is no window during which time your network is
open.
<p>The actual script used to load the rules is entirely up to
you. There is currently no support in the <tt>ipfw</tt> utility for
loading multiple rules in the one command. The system I use is to use
the command:
<tscreen><verb>
# ipfw list
</verb></tscreen>
to write a list of the current rules out to a file, and then use a
text editor to prepend ``<tt>ipfw </tt>'' before all the lines. This
will allow the script to be fed into /bin/sh and reload the rules into
the kernel. Perhaps not the most efficient way, but it works.
<p>The next problem is what your firewall should actually <bf>DO</bf>!
This is largely dependent on what access to your network you want to
allow from the outside, and how much access to the outside world you
want to allow from the inside. Some general rules are:
<itemize>
<item>Block all incoming access to ports below 1000 for TCP. This is
where most of the security sensitive services are, like finger, SMTP
(mail) and telnet.
<item>Block incoming SYN connections to ports between 1001 and 1024
(this will allow internal users to rsh/rlogin to the outside). If you
do not want to allow rsh/rlogin connections from the inside to the
outside, then extend the above suggestion to cover ports 1-1024.
<item>Block <bf>all</bf> incoming UDP traffic. There are very few
useful services that travel over UDP, and what useful traffic there is
is normally a security threat (e.g. Suns RPC and NFS protocols). This
has its disadvantages also, since UDP is a connectionless protocol,
denying incoming UDP traffic also blocks the replies to outgoing UDP
traffic. This can cause a problem for people (on the inside)
using external archie (prospero) servers. If you want to allow access
to archie, you'll have to allow packets coming from ports 191 and 1525
to any internal UDP port through the firewall. ntp is another service
you may consider allowing through, which comes from port 123.
<item>Block traffic to port 6000 from the outside. Port 6000 is the
port used for access to X11 servers, and can be a security threat
(especially if people are in the habit of doing <tt>xhost +</tt> on
their workstations). X11 can actually use a range of ports starting at
6000, the upper limit being how many X displays you can run on the
machine. The upper limit as defined by RFC 1700 (Assigned Numbers) is
6063.
<item>Check what ports any internal servers use (e.g. SQL servers,
etc). It's probably a good idea to block those as well, as they
normally fall outside the 1-1024 range specified above.
</itemize>
<p>Of course, if you want to make sure that no un-authorized traffic
gets through the firewall, change the default policy to ``deny''. This
will mean that any traffic which is allowed through has to be
specified explicitly in an ``accept'' or ``allow'' filter rule. Which
ports you allow through is again something that you will have to
decide for yourself. If you do set the default policy to be deny, you
will probably want to install proxy servers, as no traffic will be
able to get OUT either unless you allow TCP SYN connections going form
the inside out.
<p>As I said above, these are only <em>guidelines</em>. You will have
to decide what filter rules you want to use on your firewall
yourself. I cannot accept ANY responsibility if someone breaks into
your network, even if you follow the advice given above.