mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2024-12-30 23:48:09 +01:00
1130b656e5
This will make a number of things easier in the future, as well as (finally!) avoiding the Id-smashing problem which has plagued developers for so long. Boy, I'm glad we're not using sup anymore. This update would have been insane otherwise.
529 lines
21 KiB
Plaintext
529 lines
21 KiB
Plaintext
<!-- $FreeBSD$ -->
|
|
<!-- The FreeBSD Documentation Project -->
|
|
|
|
<sect><heading>Firewalls<label id="firewalls"></heading>
|
|
|
|
<p><em>Contributed by &a.gpalmer; and &a.alex;.</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 IPFW 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 IPFW 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 IPFIREWALL_VERBOSE_LIMIT=10/ Limits the number of
|
|
packets logged through <tt>syslogd(8)</tt> on a per entry basis.
|
|
You may wish to use this option in hostile environments in which
|
|
you want to log firewall activity, but do not want to be open to
|
|
a denial of service attack via syslog flooding.
|
|
|
|
<p>When a chain entry reaches the packet limit specified, logging
|
|
is turned off for that particular entry. To resume logging, you
|
|
will need to reset the associated counter using the <tt>ipfw(8)</tt>
|
|
utility:
|
|
|
|
<tscreen><verb>
|
|
ipfw zero 4500
|
|
</verb></tscreen>
|
|
|
|
Where 4500 is the chain entry you wish to continue logging.
|
|
|
|
</descrip>
|
|
|
|
Previous versions of FreeBSD contained an <tt>IPFIREWALL_ACCT</tt>
|
|
option. This is now obsolete as the firewall code automatically
|
|
includes accounting facilities.
|
|
|
|
<sect1><heading>Configuring IPFW</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 four different command categories used by the
|
|
utility: addition/deletion, listing, flushing, and clearing.
|
|
Addition/deletion is used to build the rules that control how packets
|
|
are accepted, rejected, and logged. Listing is used to examine the
|
|
contents of your rule set (otherwise known as the chain) and packet
|
|
counters (accounting). Flushing is used to remove all entries from
|
|
the chain. Clearing is used to zero out one or more accounting
|
|
entries.
|
|
|
|
<sect2><heading>Altering the IPFW rules</heading>
|
|
|
|
<p>The syntax for this form of the command is:
|
|
<tscreen>
|
|
ipfw [-N] <em>command</em> [<em>index</em>]
|
|
<em>action</em> [log] <em>protocol</em> <em>addresses</em>
|
|
[<em>options</em>]
|
|
</tscreen>
|
|
|
|
<p>There is one valid flag when using this form of the command:
|
|
|
|
<descrip>
|
|
<tag/-N/Resolve addresses and service names in output.
|
|
</descrip>
|
|
|
|
The <em>command</em> given can be shortened to the shortest unique
|
|
form. The valid <em>commands</em> are:
|
|
|
|
<descrip>
|
|
|
|
<tag/add/Add an entry to the firewall/accounting rule list
|
|
|
|
<tag/delete/Delete an entry from the firewall/accounting rule list
|
|
|
|
</descrip>
|
|
|
|
Previous versions of <tt>IPFW</tt> used separate firewall and
|
|
accounting entries. The present version provides packet accounting
|
|
with each firewall entry.
|
|
|
|
<p>If an <tt>index</tt> value is supplied, it used to place the entry
|
|
at a specific point in the chain. Otherwise, the entry is placed at
|
|
the end of the chain at an index 100 greater than the last chain
|
|
entry (this does not include the default policy, rule 65535, deny).
|
|
|
|
<p>The <bf>log</bf> option causes matching rules to be output to the
|
|
system console if the kernel was compiled with <bf>IPFIREWALL_VERBOSE</bf>.
|
|
|
|
<p>Valid <em>actions</em> are:
|
|
|
|
<descrip>
|
|
|
|
<tag/reject/Drop the packet, and send an ICMP host or port
|
|
unreachable (as appropriate) packet to the source.
|
|
|
|
<tag/allow/Pass the packet on as normal. (aliases: <bf>pass</bf> and
|
|
<bf>accept</bf>)
|
|
|
|
<tag/deny/Drop the packet. The source is not notified via an ICMP
|
|
message (thus it appears that the packet never arrived at the
|
|
destination).
|
|
|
|
<tag/count/Update packet counters but do not allow/deny the packet
|
|
based on this rule. The search continues with the next chain entry.
|
|
|
|
</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
|
|
|
|
</descrip>
|
|
|
|
<p>The <em>address</em> specification is:
|
|
<tscreen>
|
|
<bf>from</bf> <<em>address/mask</em>>[<em>port</em>] <bf>to</bf>
|
|
<<em>address/mask</em>>[<em>port</em>&rsqb [<bf>via</bf> <<em>interface</em>>]
|
|
</tscreen>
|
|
|
|
<p>You can only specify <em>port</em> in conjunction with
|
|
<em>protocols</em> which support ports (UDP and TCP).
|
|
|
|
<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.
|
|
Interface unit numbers can be specified with an optional wildcard.
|
|
For example, <tt>ppp*</tt> would match all kernel PPP interfaces.
|
|
|
|
<p>The syntax used to specify an <tt><address/mask></tt> is:
|
|
<tscreen>
|
|
<address>
|
|
</tscreen>
|
|
or
|
|
<tscreen>
|
|
<address>/mask-bits
|
|
</tscreen>
|
|
or
|
|
<tscreen>
|
|
<address>: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[,port[,port[...]]]
|
|
</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. You may also combine a single range with a
|
|
list, but the range must always be specified first.
|
|
|
|
<p>The <em>options</em> available are:
|
|
|
|
<descrip>
|
|
|
|
<tag/frag/Matches if the packet is not the first fragment of the datagram.
|
|
|
|
<tag/in/Matches if the packet is on the way in.
|
|
|
|
<tag/out/Matches if the packet is on the way out.
|
|
|
|
<tag/ipoptions <em>spec</em>/Matches if the IP header contains the
|
|
comma separated list of options specified in <em>spec</em>. The
|
|
supported list of IP options are: <bf>ssrr</bf> (strict source route),
|
|
<bf>lsrr</bf> (loose source route), <bf>rr</bf> (record packet route),
|
|
and <bf>ts</bf> (timestamp). The absence of a particular option may
|
|
be denoted with a leading '!'.
|
|
|
|
<tag/established/Matches if the packet is part of an already established
|
|
TCP connection (i.e. it has the RST or ACK bits set). You can optimize
|
|
the performance of the firewall by placing <em>established</em> rules
|
|
early in the chain.
|
|
|
|
<tag/setup/Matches if the packet is an attempt to establish a TCP connection
|
|
(the SYN bit set is set but the ACK bit is not).
|
|
|
|
<tag/tcpflags <em>flags</em>/Matches if the TCP header contains
|
|
the comma separated list of <em>flags</em>. The supported flags
|
|
are <bf>fin</bf>, <bf>syn</bf>, <bf>rst</bf>, <bf>psh</bf>, <bf>ack</bf>,
|
|
and <bf>urg</bf>. The absence of a particular flag may be indicated
|
|
by a leading '!'.
|
|
|
|
<tag/icmptypes <em>types</em>/Matches if the ICMP type is present in
|
|
the list <em>types</em>. The list may be specified as any combination
|
|
of ranges and/or individual types separated by commas. Commonly used
|
|
ICMP types are: <bf>0</bf> echo reply (ping reply), <bf>5</bf>
|
|
redirect, <bf>8</bf> echo request (ping request), and <bf>11</bf>
|
|
time exceeded (used to indicate TTL expiration as with
|
|
<tt>traceroute(8)</tt>).
|
|
|
|
</descrip>
|
|
|
|
<sect2><heading>Listing the IPFW rules</heading>
|
|
|
|
<p>The syntax for this form of the command is:
|
|
<tscreen>
|
|
ipfw [-atN] l
|
|
</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.
|
|
|
|
<tag/-t/Display the last match times for each chain entry. The time
|
|
listing is incompatible with the input syntax used by the
|
|
<tt>ipfw(8)</tt> utility.
|
|
|
|
<tag/-N/Attempt to resolve given addresses and service names.
|
|
|
|
</descrip>
|
|
|
|
<sect2><heading>Flushing the IPFW rules</heading>
|
|
|
|
<p>The syntax for flushing the chain is:
|
|
<tscreen>
|
|
ipfw flush
|
|
</tscreen>
|
|
|
|
<p>This causes all entries in the firewall chain to be removed except
|
|
the fixed default policy enforced by the kernel (index 65535). Use
|
|
caution when flushing rules, the default deny policy will leave your
|
|
system cut off from the network until allow entries are added to the
|
|
chain.
|
|
|
|
<sect2><heading>Clearing the IPFW packet counters</heading>
|
|
|
|
<p>The syntax for clearing one or more packet counters is:
|
|
<tscreen>
|
|
ipfw zero [index]
|
|
</tscreen>
|
|
|
|
<p>When used without an <em>index</em> argument, all packet counters
|
|
are cleared. If an <em>index</em> is supplied, the clearing operation
|
|
only affects a specific chain entry.
|
|
|
|
<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 add deny tcp from evil.hacker.org to nice.people.org 23
|
|
</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 add deny log 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 add deny from any to my.org/28 6000 setup
|
|
</verb></tscreen>
|
|
|
|
To allow access to the SUP server on <bf>sup.FreeBSD.ORG</bf>, use the
|
|
following command:
|
|
|
|
<tscreen><verb>
|
|
ipfw add accept from any to sup.FreeBSD.ORG 871
|
|
</verb></tscreen>
|
|
|
|
To see the accounting records:
|
|
<tscreen><verb>
|
|
ipfw -a list
|
|
</verb></tscreen>
|
|
or in the short form
|
|
<tscreen><verb>
|
|
ipfw -a l
|
|
</verb></tscreen>
|
|
You can also see the last time a chain entry was matched with
|
|
<tscreen><verb>
|
|
ipfw -at l
|
|
</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 1024 for TCP. This is
|
|
where most of the security sensitive services are, like finger, SMTP
|
|
(mail) and telnet.
|
|
|
|
<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 is probably a good idea to block those as well, as they
|
|
normally fall outside the 1-1024 range specified above.
|
|
|
|
</itemize>
|
|
|
|
<p>Another checklist for firewall configuration is available from CERT
|
|
at <htmlurl url="ftp://ftp.cert.org/pub/tech_tips/packet_filtering"
|
|
name="ftp://ftp.cert.org/pub/tech_tips/packet_filtering">
|
|
|
|
<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.
|