3329 lines
133 KiB
XML
3329 lines
133 KiB
XML
<?xml version="1.0" encoding="iso-8859-2"?>
|
|
<!--
|
|
The FreeBSD Documentation Project
|
|
|
|
$FreeBSD$
|
|
-->
|
|
|
|
<chapter id="firewalls">
|
|
<chapterinfo>
|
|
<authorgroup>
|
|
<author>
|
|
<firstname>Joseph J.</firstname>
|
|
<surname>Barbish</surname>
|
|
<contrib>Contributed by </contrib>
|
|
</author>
|
|
</authorgroup>
|
|
<authorgroup>
|
|
<author>
|
|
<firstname>Brad</firstname>
|
|
<surname>Davis</surname>
|
|
<contrib>Converted to SGML and updated by </contrib>
|
|
</author>
|
|
</authorgroup>
|
|
</chapterinfo>
|
|
|
|
<title>Firewalls</title>
|
|
|
|
<indexterm><primary>firewall</primary></indexterm>
|
|
|
|
<indexterm>
|
|
<primary>security</primary>
|
|
|
|
<secondary>firewalls</secondary>
|
|
</indexterm>
|
|
|
|
<sect1 id="firewalls-intro">
|
|
<title>Introduction</title>
|
|
|
|
<para>Firewalls make it possible to filter
|
|
incoming and outgoing traffic that flows through your system.
|
|
A firewall can use one or more sets of <quote>rules</quote> to
|
|
inspect the network packets as they come in or go out of your
|
|
network connections and either allows the traffic through or
|
|
blocks it. The rules of a firewall can inspect one or more
|
|
characteristics of the packets, including but not limited to the
|
|
protocol type, the source or destination host address, and the
|
|
source or destination port.</para>
|
|
|
|
<para>Firewalls can greatly enhance the security of a host or a
|
|
network. They can be used to do one or more of
|
|
the following things:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>To protect and insulate the applications, services and
|
|
machines of your internal network from unwanted traffic
|
|
coming in from the public Internet.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>To limit or disable access from hosts of the internal
|
|
network to services of the public Internet.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>To support network address translation
|
|
(<acronym>NAT</acronym>), which allows your internal network
|
|
to use private <acronym>IP</acronym> addresses and share a
|
|
single connection to the public Internet (either with a
|
|
single <acronym>IP</acronym> address or by a shared pool of
|
|
automatically assigned public addresses).</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>After reading this chapter, you will know:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>How to properly define packet filtering rules.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>The differences between the firewalls
|
|
built into &os;.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>How to use and configure the OpenBSD
|
|
<application>PF</application> firewall.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>How to use and configure
|
|
<application>IPFILTER</application>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>How to use and configure
|
|
<application>IPFW</application>.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>Before reading this chapter, you should:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Understand basic &os; and Internet concepts.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</sect1>
|
|
|
|
<sect1 id="firewalls-concepts">
|
|
<title>Firewall Concepts</title>
|
|
|
|
<indexterm>
|
|
<primary>firewall</primary>
|
|
|
|
<secondary>rulesets</secondary>
|
|
</indexterm>
|
|
|
|
<para>There are two basic ways to create firewall rulesets:
|
|
<quote>inclusive</quote> or <quote>exclusive</quote>. An
|
|
exclusive firewall allows all traffic through except for the
|
|
traffic matching the ruleset. An inclusive firewall does the
|
|
reverse. It only allows traffic matching the rules through and
|
|
blocks everything else.</para>
|
|
|
|
<para>Inclusive firewalls are generally safer than exclusive
|
|
firewalls because they significantly reduce the risk of allowing
|
|
unwanted traffic to pass through the firewall.</para>
|
|
|
|
<para>Security can be tightened further using a <quote>stateful
|
|
firewall</quote>. With a stateful firewall the firewall keeps
|
|
track of which connections are opened through the firewall and
|
|
will only allow traffic through which either matches an existing
|
|
connection or opens a new one. The disadvantage of a stateful
|
|
firewall is that it can be vulnerable to Denial of Service
|
|
(<acronym>DoS</acronym>) attacks if a lot of new connections are
|
|
opened very fast. With most firewalls it is possible to use a
|
|
combination of stateful and non-stateful behavior to make an
|
|
optimal firewall for the site.</para>
|
|
</sect1>
|
|
|
|
<sect1 id="firewalls-apps">
|
|
<title>Firewall Packages</title>
|
|
|
|
<para>&os; has three different firewall packages built
|
|
into the base system. They are: <emphasis>IPFILTER</emphasis>
|
|
(also known as <acronym>IPF</acronym>),
|
|
<emphasis>IPFIREWALL</emphasis> (also known as <acronym>IPFW</acronym>),
|
|
and <emphasis>OpenBSD's PacketFilter</emphasis> (also known as
|
|
<acronym>PF</acronym>). &os; also has two built in packages for
|
|
traffic shaping (basically controlling bandwidth usage):
|
|
&man.altq.4; and &man.dummynet.4;. Dummynet has traditionally been
|
|
closely tied with <acronym>IPFW</acronym>, and
|
|
<acronym>ALTQ</acronym> with
|
|
<acronym>IPF</acronym>/<acronym>PF</acronym>. IPF,
|
|
IPFW, and PF all use rules to control the access of packets to and
|
|
from your system, although they go about it different ways and
|
|
have different rule syntaxes.</para>
|
|
|
|
<para>The reason that &os; has multiple built in firewall packages
|
|
is that different people have different requirements and
|
|
preferences. No single firewall package is the best.</para>
|
|
|
|
<para>The author prefers IPFILTER because its stateful rules are
|
|
much less complicated to use in a <acronym>NAT</acronym>
|
|
environment and it has a built in ftp proxy that simplifies the
|
|
rules to allow secure outbound FTP usage.</para>
|
|
|
|
<para>Since all firewalls are based on inspecting the values of
|
|
selected packet control fields, the creator of the firewall
|
|
rulesets must have an understanding of how
|
|
<acronym>TCP</acronym>/IP works, what the different values in
|
|
the packet control fields are and how these values are used in a
|
|
normal session conversation. For a good explanation go to:
|
|
<ulink
|
|
url="http://www.ipprimer.com/overview.cfm"></ulink>.</para>
|
|
</sect1>
|
|
|
|
<sect1 id="firewalls-pf">
|
|
<title>The OpenBSD Packet Filter (PF) and
|
|
<acronym>ALTQ</acronym></title>
|
|
|
|
<indexterm>
|
|
<primary>firewall</primary>
|
|
|
|
<secondary>PF</secondary>
|
|
</indexterm>
|
|
|
|
<para>As of July 2003 the OpenBSD firewall software application
|
|
known as <acronym>PF</acronym> was ported to &os; and was made
|
|
available in the &os; Ports Collection; the first release that
|
|
contained <acronym>PF</acronym> as an integrated part of the
|
|
base system was &os; 5.3 in November 2004.
|
|
<acronym>PF</acronym> is a complete, fully featured firewall
|
|
that has optional support for <acronym>ALTQ</acronym> (Alternate
|
|
Queuing). <acronym>ALTQ</acronym> provides Quality of Service
|
|
(<acronym>QoS</acronym>) bandwidth shaping that allows
|
|
guaranteeing bandwidth to different services based on filtering
|
|
rules. The OpenBSD Project does an outstanding job of
|
|
maintaining the PF User's Guide that it will not be made part of
|
|
this handbook firewall section as that would just be duplicated
|
|
effort.</para>
|
|
|
|
<para>More info can be found at the PF for &os; web site: <ulink
|
|
url="http://pf4freebsd.love2party.net/"></ulink>.</para>
|
|
|
|
<sect2>
|
|
<title>Enabling PF</title>
|
|
|
|
<para>PF is included in the basic &os; install for versions newer
|
|
than 5.3 as a separate run time loadable module. The system
|
|
will dynamically load the PF kernel loadable module when the
|
|
rc.conf statement <literal>pf_enable="YES"</literal> is used.
|
|
The loadable module was created with &man.pflog.4; logging
|
|
enabled.</para>
|
|
|
|
<note>
|
|
<para>The module assumes the presence of <literal>options
|
|
INET</literal> and <literal>device bpf</literal>. Unless
|
|
<literal>NOINET6</literal> for &os; prior to 6.0-RELEASE and
|
|
<literal>NO_INET6</literal> for later releases (for example in
|
|
&man.make.conf.5;) was defined during the build, it also
|
|
requires<literal>options INET6</literal>.</para>
|
|
</note>
|
|
|
|
<para>Once the kernel module is loaded or the kernel is statically
|
|
built with PF support, it is possible to enable or disable
|
|
<application>pf</application> with the <command>pfctl</command>
|
|
command.</para>
|
|
|
|
<para>This example demonstrates how to enable
|
|
<application>pf</application>:</para>
|
|
|
|
<screen>&prompt.root; <userinput>pfctl -e</userinput></screen>
|
|
|
|
<para>The <command>pfctl</command> command provides a way to work
|
|
with the <application>pf</application> firewall. It is a good
|
|
idea to check the &man.pfctl.8; manual page to find out more
|
|
information about using it.</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Kernel options</title>
|
|
|
|
<indexterm>
|
|
<primary>kernel options</primary>
|
|
|
|
<secondary>device pf</secondary>
|
|
</indexterm>
|
|
|
|
<indexterm>
|
|
<primary>kernel options</primary>
|
|
|
|
<secondary>device pflog</secondary>
|
|
</indexterm>
|
|
|
|
<indexterm>
|
|
<primary>kernel options</primary>
|
|
|
|
<secondary>device pfsync</secondary>
|
|
</indexterm>
|
|
|
|
<para>It is not a mandatory requirement that you enable PF by
|
|
compiling the following options into the &os; kernel. It is
|
|
only presented here as background information. Compiling PF
|
|
into the kernel causes the loadable module to never be
|
|
used.</para>
|
|
|
|
<para>Sample kernel config PF option statements are in the
|
|
<filename>/usr/src/sys/conf/NOTES</filename> kernel source and
|
|
are reproduced here:</para>
|
|
|
|
<programlisting>device pf
|
|
device pflog
|
|
device pfsync</programlisting>
|
|
|
|
<para><literal>device pf</literal> enables support for the
|
|
<quote>Packet Filter</quote> firewall.</para>
|
|
|
|
<para><literal>device pflog</literal> enables the optional
|
|
&man.pflog.4; pseudo network device which can be used to log
|
|
traffic to a &man.bpf.4; descriptor. The &man.pflogd.8; daemon
|
|
can be used to store the logging information to disk.</para>
|
|
|
|
<para><literal>device pfsync</literal> enables the optional
|
|
&man.pfsync.4; pseudo network device that is used to monitor
|
|
<quote>state changes</quote>. As this is not part of the
|
|
loadable module one has to build a custom kernel to use
|
|
it.</para>
|
|
|
|
<para>These settings will take effect only after you have built
|
|
and installed a kernel with them set.</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Available rc.conf Options</title>
|
|
|
|
<para>You need the following statements in
|
|
<filename>/etc/rc.conf</filename> to activate PF at boot
|
|
time:</para>
|
|
|
|
<programlisting>pf_enable="YES" # Enable PF (load module if required)
|
|
pf_rules="/etc/pf.conf" # rules definition file for pf
|
|
pf_flags="" # additional flags for pfctl startup
|
|
pflog_enable="YES" # start pflogd(8)
|
|
pflog_logfile="/var/log/pflog" # where pflogd should store the logfile
|
|
pflog_flags="" # additional flags for pflogd startup</programlisting>
|
|
|
|
<para>If you have a LAN behind this firewall and have to forward
|
|
packets for the computers in the LAN or want to do NAT, you
|
|
have to enable the following option as well:</para>
|
|
|
|
<programlisting>gateway_enable="YES" # Enable as LAN gateway</programlisting>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Enabling <acronym>ALTQ</acronym></title>
|
|
|
|
<para><acronym>ALTQ</acronym> is only available by compiling the
|
|
options into the &os; Kernel. <acronym>ALTQ</acronym> is not
|
|
supported by all of the available network card drivers. Please
|
|
see the &man.altq.4; manual page for a list of drivers that are
|
|
supported in your release of &os;. The following options will
|
|
enable <acronym>ALTQ</acronym> and add additional
|
|
functionality.</para>
|
|
|
|
<programlisting>options ALTQ
|
|
options ALTQ_CBQ # Class Bases Queuing (CBQ)
|
|
options ALTQ_RED # Random Early Detection (RED)
|
|
options ALTQ_RIO # RED In/Out
|
|
options ALTQ_HFSC # Hierarchical Packet Scheduler (HFSC)
|
|
options ALTQ_PRIQ # Priority Queuing (PRIQ)
|
|
options ALTQ_NOPCC # Required for SMP build</programlisting>
|
|
|
|
<para><literal>options ALTQ</literal> enables the
|
|
<acronym>ALTQ</acronym> framework.</para>
|
|
|
|
<para><literal>options ALTQ_CBQ</literal> enables Class Based
|
|
Queuing (<acronym>CBQ</acronym>). <acronym>CBQ</acronym>
|
|
allows you to divide a connection's bandwidth into different
|
|
classes or queues to prioritize traffic based on filter
|
|
rules.</para>
|
|
|
|
<para><literal>options ALTQ_RED</literal> enables Random Early
|
|
Detection (<acronym>RED</acronym>). <acronym>RED</acronym> is
|
|
used to avoid network congestion. <acronym>RED</acronym> does
|
|
this by measuring the length of the queue and comparing it to
|
|
the minimum and maximum thresholds for the queue. If the
|
|
queue is over the maximum all new packets will be dropped.
|
|
True to its name, <acronym>RED</acronym> drops packets from
|
|
different connections randomly.</para>
|
|
|
|
<para><literal>options ALTQ_RIO</literal> enables Random Early
|
|
Detection In and Out.</para>
|
|
|
|
<para><literal>options ALTQ_HFSC</literal> enables the
|
|
Hierarchical Fair Service Curve Packet Scheduler. For more
|
|
information about <acronym>HFSC</acronym> see: <ulink
|
|
url="http://www-2.cs.cmu.edu/~hzhang/HFSC/main.html"></ulink>.</para>
|
|
|
|
<para><literal>options ALTQ_PRIQ</literal> enables Priority
|
|
Queuing (<acronym>PRIQ</acronym>). <acronym>PRIQ</acronym>
|
|
will always pass traffic that is in a higher queue
|
|
first.</para>
|
|
|
|
<para><literal>options ALTQ_NOPCC</literal> enables
|
|
<acronym>SMP</acronym> support for <acronym>ALTQ</acronym>.
|
|
This option is required on <acronym>SMP</acronym>
|
|
systems.</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Creating Filtering Rules</title>
|
|
|
|
<para>The Packet Filter reads its configuration rules from the
|
|
&man.pf.conf.5; file and it modifies, drops or passes packets
|
|
according to the rules or definitions specified there. The &os;
|
|
installation comes with a default
|
|
<filename>/etc/pf.conf</filename> which contains useful examples
|
|
and explanations.</para>
|
|
|
|
<para>Although &os; has its own <filename>/etc/pf.conf</filename>
|
|
the syntax is the same as one used in OpenBSD. A great
|
|
resource for configuring the <application>pf</application>
|
|
firewall has been written by OpenBSD team and is available at
|
|
<ulink url="http://www.openbsd.org/faq/pf/"></ulink>.</para>
|
|
|
|
<warning>
|
|
<para>When browsing the pf user's guide, please keep in mind that
|
|
different versions of &os; contain different versions of pf. The
|
|
<application>pf</application> firewall in &os; 5.X is at the level
|
|
of OpenBSD version 3.5 and in &os; 6.X is at the level of OpenBSD
|
|
version 3.7.</para>
|
|
</warning>
|
|
|
|
<para>The &a.pf; is a good place to ask questions about
|
|
configuring and running the <application>pf</application>
|
|
firewall. Do not forget to check the mailing list archives
|
|
before asking questions.</para>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 id="firewalls-ipf">
|
|
<title>The IPFILTER (IPF) Firewall</title>
|
|
|
|
<indexterm>
|
|
<primary>firewall</primary>
|
|
|
|
<secondary>IPFILTER</secondary>
|
|
</indexterm>
|
|
|
|
<note>
|
|
<para>This section is work in progress. The contents might
|
|
not be accurate at all times.</para>
|
|
</note>
|
|
|
|
<para>The author of IPFILTER is Darren Reed. IPFILTER is not
|
|
operating system dependent: it is an open source application and
|
|
has been ported to &os;, NetBSD, OpenBSD, &sunos;, HP/UX, and
|
|
&solaris; operating systems. IPFILTER is actively being
|
|
supported and maintained, with updated versions being released
|
|
regularly.</para>
|
|
|
|
<para>IPFILTER is based on a kernel-side firewall and
|
|
<acronym>NAT</acronym> mechanism that can be controlled and
|
|
monitored by userland interface programs. The firewall rules can
|
|
be set or deleted with the &man.ipf.8; utility. The
|
|
<acronym>NAT</acronym> rules can be set or deleted with the
|
|
&man.ipnat.1; utility. The &man.ipfstat.8; utility can print
|
|
run-time statistics for the kernel parts of IPFILTER. The
|
|
&man.ipmon.8; program can log IPFILTER actions to the system log
|
|
files.</para>
|
|
|
|
<para>IPF was originally written using a rule processing logic of
|
|
<quote>the last matching rule wins</quote> and used only
|
|
stateless type of rules. Over time IPF has been enhanced to
|
|
include a <quote>quick</quote> option and a stateful <quote>keep
|
|
state</quote> option which drastically modernized the rules
|
|
processing logic. IPF's official documentation covers the legacy
|
|
rule coding parameters and the legacy rule file processing
|
|
logic. The modernized functions are only included as additional
|
|
options, completely understating their benefits in producing a
|
|
far superior secure firewall.</para>
|
|
|
|
<para>The instructions contained in this section are based on
|
|
using rules that contain the <quote>quick</quote> option and the
|
|
stateful <quote>keep state</quote> option. This is the basic
|
|
framework for coding an inclusive firewall rule set.</para>
|
|
|
|
<!-- XXX: something like this already in
|
|
<xref linkend="firewalls-concepts"/>
|
|
AND: the para below is repeated 3 times in this chapter-->
|
|
|
|
<para>An inclusive firewall only allows packets matching the rules
|
|
to pass through. This way you can control what services can
|
|
originate behind the firewall destined for the public Internet
|
|
and also control the services which can originate from the
|
|
public Internet accessing your private network. Everything else
|
|
is blocked and logged by default design. Inclusive firewalls are
|
|
much, much more secure than exclusive firewall rule sets and is
|
|
the only rule set type covered herein.</para>
|
|
|
|
<para>For detailed explanation of the legacy rules processing
|
|
method see: <ulink
|
|
url="http://www.obfuscation.org/ipf/ipf-howto.html#TOC_1"></ulink>
|
|
and <ulink
|
|
url="http://coombs.anu.edu.au/~avalon/ip-filter.html"></ulink>.</para>
|
|
|
|
<para>The IPF FAQ is at <ulink
|
|
url="http://www.phildev.net/ipf/index.html"></ulink>.</para>
|
|
|
|
<para>A searchable archive of the open-source IPFilter mailing list is
|
|
available at <ulink
|
|
url="http://marc.theaimsgroup.com/?l=ipfilter"></ulink>.</para>
|
|
|
|
<sect2>
|
|
<title>Enabling IPF</title>
|
|
|
|
<indexterm>
|
|
<primary>IPFILTER</primary>
|
|
|
|
<secondary>enabling</secondary>
|
|
</indexterm>
|
|
|
|
<para>IPF is included in the basic &os; install as a separate run
|
|
time loadable module. The system will dynamically load the IPF
|
|
kernel loadable module when the rc.conf statement
|
|
<literal>ipfilter_enable="YES"</literal> is used. The loadable
|
|
module was created with logging enabled and the
|
|
<literal>default pass all</literal> options. You do not need
|
|
to compile IPF into the &os; kernel just to change the default
|
|
to <literal>block all</literal>, you can do that by just coding
|
|
a block all rule at the end of your rule set.</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Kernel options</title>
|
|
|
|
<indexterm>
|
|
<primary>kernel options</primary>
|
|
|
|
<secondary>IPFILTER</secondary>
|
|
</indexterm>
|
|
|
|
<indexterm>
|
|
<primary>kernel options</primary>
|
|
|
|
<secondary>IPFILTER_LOG</secondary>
|
|
</indexterm>
|
|
|
|
<indexterm>
|
|
<primary>kernel options</primary>
|
|
|
|
<secondary>IPFILTER_DEFAULT_BLOCK</secondary>
|
|
</indexterm>
|
|
|
|
<indexterm>
|
|
<primary>IPFILTER</primary>
|
|
|
|
<secondary>kernel options</secondary>
|
|
</indexterm>
|
|
|
|
<para>It is not a mandatory requirement that you enable IPF by
|
|
compiling the following options into the &os; kernel. It is
|
|
only presented here as background information. Compiling IPF
|
|
into the kernel causes the loadable module to never be
|
|
used.</para>
|
|
|
|
<para>Sample kernel config IPF option statements are in the
|
|
<filename>/usr/src/sys/conf/NOTES</filename> kernel source
|
|
and are reproduced here:</para>
|
|
|
|
<programlisting>options IPFILTER
|
|
options IPFILTER_LOG
|
|
options IPFILTER_DEFAULT_BLOCK</programlisting>
|
|
|
|
<para><literal>options IPFILTER</literal> enables support for the
|
|
<quote>IPFILTER</quote> firewall.</para>
|
|
|
|
<para><literal>options IPFILTER_LOG</literal> enables the option
|
|
to have IPF log traffic by writing to the
|
|
<devicename>ipl</devicename> packet logging pseudo—device
|
|
for every rule that has the <literal>log</literal>
|
|
keyword.</para>
|
|
|
|
<para><literal>options IPFILTER_DEFAULT_BLOCK</literal> changes
|
|
the default behavior so any packet not matching a firewall
|
|
<literal>pass</literal> rule gets blocked.</para>
|
|
|
|
<para>These settings will take effect only after you have built
|
|
and installed a kernel with them set.</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Available rc.conf Options</title>
|
|
|
|
<para>You need the following statements in
|
|
<filename>/etc/rc.conf</filename> to activate IPF at boot
|
|
time:</para>
|
|
|
|
<programlisting>ipfilter_enable="YES" # Start ipf firewall
|
|
ipfilter_rules="/etc/ipf.rules" # loads rules definition text file
|
|
ipmon_enable="YES" # Start IP monitor log
|
|
ipmon_flags="-Ds" # D = start as daemon
|
|
# s = log to syslog
|
|
# v = log tcp window, ack, seq
|
|
# n = map IP & port to names</programlisting>
|
|
|
|
<para>If you have a LAN behind this firewall that uses the
|
|
reserved private IP address ranges, then you need to add the
|
|
following to enable <acronym>NAT</acronym>
|
|
functionality:</para>
|
|
|
|
<programlisting>gateway_enable="YES" # Enable as LAN gateway
|
|
ipnat_enable="YES" # Start ipnat function
|
|
ipnat_rules="/etc/ipnat.rules" # rules definition file for ipnat</programlisting>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>IPF</title>
|
|
|
|
<indexterm><primary><command>ipf</command></primary></indexterm>
|
|
|
|
<para>The ipf command is used to load your rules file. Normally
|
|
you create a file containing your custom rules and use this
|
|
command to replace in mass the currently running firewall
|
|
internal rules:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ipf -Fa -f /etc/ipf.rules</userinput></screen>
|
|
|
|
<para><option>-Fa</option> means flush all internal rules
|
|
tables.</para>
|
|
|
|
<para><option>-f</option> means this is the file to read for the
|
|
rules to load.</para>
|
|
|
|
<para>This gives you the ability to make changes to your custom
|
|
rules file, run the above IPF command, and thus update the
|
|
running firewall with a fresh copy of all the rules without
|
|
having to reboot the system. This method is very convenient
|
|
for testing new rules as the procedure can be executed as many
|
|
times as needed.</para>
|
|
|
|
<para>See the &man.ipf.8; manual page for details on the other
|
|
flags available with this command.</para>
|
|
|
|
<para>The &man.ipf.8; command expects the rules file to be a
|
|
standard text file. It will not accept a rules file written as
|
|
a script with symbolic substitution.</para>
|
|
|
|
<para>There is a way to build IPF rules that utilizes the power
|
|
of script symbolic substitution. For more information, see
|
|
<xref linkend="firewalls-ipf-rules-script"/>.</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>IPFSTAT</title>
|
|
|
|
<indexterm><primary><command>ipfstat</command></primary></indexterm>
|
|
|
|
<indexterm>
|
|
<primary>IPFILTER</primary>
|
|
|
|
<secondary>statistics</secondary>
|
|
</indexterm>
|
|
|
|
<para>The default behavior of &man.ipfstat.8; is to retrieve and
|
|
display the totals of the accumulated statistics gathered as a
|
|
result of applying the user coded rules against packets going
|
|
in and out of the firewall since it was last started, or since
|
|
the last time the accumulators were reset to zero by the
|
|
<command>ipf -Z</command> command.</para>
|
|
|
|
<para>See the &man.ipfstat.8; manual page for details.</para>
|
|
|
|
<para>The default &man.ipfstat.8; command output will look
|
|
something like this:</para>
|
|
|
|
<screen>input packets: blocked 99286 passed 1255609 nomatch 14686 counted 0
|
|
output packets: blocked 4200 passed 1284345 nomatch 14687 counted 0
|
|
input packets logged: blocked 99286 passed 0
|
|
output packets logged: blocked 0 passed 0
|
|
packets logged: input 0 output 0
|
|
log failures: input 3898 output 0
|
|
fragment state(in): kept 0 lost 0
|
|
fragment state(out): kept 0 lost 0
|
|
packet state(in): kept 169364 lost 0
|
|
packet state(out): kept 431395 lost 0
|
|
ICMP replies: 0 <acronym>TCP</acronym> RSTs sent: 0
|
|
Result cache hits(in): 1215208 (out): 1098963
|
|
IN Pullups succeeded: 2 failed: 0
|
|
OUT Pullups succeeded: 0 failed: 0
|
|
Fastroute successes: 0 failures: 0
|
|
<acronym>TCP</acronym> cksum fails(in): 0 (out): 0
|
|
Packet log flags set: (0)</screen>
|
|
|
|
<para>When supplied with either <option>-i</option> for inbound
|
|
or <option>-o</option> for outbound, it will retrieve and
|
|
display the appropriate list of filter rules currently
|
|
installed and in use by the kernel.</para>
|
|
|
|
<para><command>ipfstat -in</command> displays the inbound
|
|
internal rules table with rule number.</para>
|
|
|
|
<para><command>ipfstat -on</command> displays the outbound
|
|
internal rules table with the rule number.</para>
|
|
|
|
<para>The output will look something like this:</para>
|
|
|
|
<screen>@1 pass out on xl0 from any to any
|
|
@2 block out on dc0 from any to any
|
|
@3 pass out quick on dc0 proto tcp/udp from any to any keep state</screen>
|
|
|
|
<para><command>ipfstat -ih</command> displays the inbound
|
|
internal rules table, prefixing each rule with a count of how
|
|
many times the rule was matched.</para>
|
|
|
|
<para><command>ipfstat -oh</command> displays the outbound
|
|
internal rules table, prefixing each rule with a count of how
|
|
many times the rule was matched.</para>
|
|
|
|
<para>The output will look something like this:</para>
|
|
|
|
<screen>2451423 pass out on xl0 from any to any
|
|
354727 block out on dc0 from any to any
|
|
430918 pass out quick on dc0 proto tcp/udp from any to any keep state</screen>
|
|
|
|
<para>One of the most important functions of the
|
|
<command>ipfstat</command> command is the <option>-t</option>
|
|
flag which displays the state table in a way similar to the way
|
|
&man.top.1; shows the &os; running process table. When your
|
|
firewall is under attack this function gives you the ability to
|
|
identify, drill down to, and see the attacking packets. The
|
|
optional sub-flags give the ability to select the destination
|
|
or source IP, port, or protocol that you want to monitor in
|
|
real time. See the &man.ipfstat.8; manual page for
|
|
details.</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>IPMON</title>
|
|
|
|
<indexterm><primary><command>ipmon</command></primary></indexterm>
|
|
|
|
<indexterm>
|
|
<primary>IPFILTER</primary>
|
|
|
|
<secondary>logging</secondary>
|
|
</indexterm>
|
|
|
|
<para>In order for <command>ipmon</command> to work properly, the
|
|
kernel option IPFILTER_LOG must be turned on. This command has
|
|
two different modes that it can be used in. Native mode is the
|
|
default mode when you type the command on the command line
|
|
without the <option>-D</option> flag.</para>
|
|
|
|
<para>Daemon mode is for when you want to have a continuous
|
|
system log file available so that you can review logging of
|
|
past events. This is how &os; and IPFILTER are configured to
|
|
work together. &os; has a built in facility to automatically
|
|
rotate system logs. That is why outputting the log information
|
|
to syslogd is better than the default of outputting to a
|
|
regular file. In the default <filename>rc.conf</filename> file
|
|
you see the ipmon_flags statement uses the <option>-Ds</option>
|
|
flags:</para>
|
|
|
|
<programlisting>ipmon_flags="-Ds" # D = start as daemon
|
|
# s = log to syslog
|
|
# v = log tcp window, ack, seq
|
|
# n = map IP & port to names</programlisting>
|
|
|
|
<para>The benefits of logging are obvious. It provides the
|
|
ability to review, after the fact, information such as which
|
|
packets had been dropped, what addresses they came from and
|
|
where they were going. These all give you a significant edge
|
|
in tracking down attackers.</para>
|
|
|
|
<para>Even with the logging facility enabled, IPF will not
|
|
generate any rule logging on its own. The firewall
|
|
administrator decides what rules in the rule set he wants to
|
|
log and adds the log keyword to those rules. Normally only
|
|
deny rules are logged.</para>
|
|
|
|
<para>It is very customary to include a default deny everything
|
|
rule with the log keyword included as your last rule in the
|
|
rule set. This way you get to see all the packets that did not
|
|
match any of the rules in the rule set.</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>IPMON Logging</title>
|
|
|
|
<para><application>Syslogd</application> uses its own special
|
|
method for segregation of log data. It uses special groupings
|
|
called <quote>facility</quote> and <quote>level</quote>. IPMON
|
|
in <option>-Ds</option> mode uses <literal>security</literal>
|
|
as the <quote>facility</quote>
|
|
name. All IPMON logged data goes to <literal>security</literal>
|
|
The following levels can be
|
|
used to further segregate the logged data if desired:</para>
|
|
|
|
<screen>LOG_INFO - packets logged using the "log" keyword as the action rather than pass or block.
|
|
LOG_NOTICE - packets logged which are also passed
|
|
LOG_WARNING - packets logged which are also blocked
|
|
LOG_ERR - packets which have been logged and which can be considered short</screen>
|
|
|
|
<!-- XXX: "can be considered short" == "with incomplete header" -->
|
|
|
|
<para>To setup IPFILTER to log all data to
|
|
<filename>/var/log/ipfilter.log</filename>, you will need to
|
|
create the file. The following command will do that:</para>
|
|
|
|
<screen>&prompt.root; <userinput>touch /var/log/ipfilter.log</userinput></screen>
|
|
|
|
<para>The syslog function is controlled by definition statements
|
|
in the <filename>/etc/syslog.conf</filename> file. The
|
|
<filename>syslog.conf</filename> file offers considerable
|
|
flexibility in how syslog will deal with system messages issued
|
|
by software applications like IPF.</para>
|
|
|
|
<para>Add the following statement to
|
|
<filename>/etc/syslog.conf</filename>:</para>
|
|
|
|
<programlisting>security.* /var/log/ipfilter.log</programlisting>
|
|
|
|
<para>Or add the following statement to
|
|
<filename>/etc/syslog.conf</filename>.</para>
|
|
|
|
<para>The <literal>security.*</literal>
|
|
means to write all the logged messages to the coded
|
|
file location.</para>
|
|
|
|
<para>To activate the changes to <filename>/etc/syslog.conf
|
|
</filename> you can reboot or bump the syslog task into
|
|
re-reading <filename>/etc/syslog.conf</filename> by running
|
|
<command>/etc/rc.d/syslogd reload</command></para>
|
|
|
|
<para>Do not forget to change
|
|
<filename>/etc/newsyslog.conf</filename> to rotate the new log
|
|
you just created above.</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>The Format of Logged Messages</title>
|
|
|
|
<para>Messages generated by <command>ipmon</command> consist of
|
|
data fields separated by white space. Fields common to all
|
|
messages are:</para>
|
|
|
|
<orderedlist>
|
|
<listitem>
|
|
<para>The date of packet receipt.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>The time of packet receipt. This is in the form
|
|
HH:MM:SS.F, for hours, minutes, seconds, and fractions of a
|
|
second (which can be several digits long).</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>The name of the interface the packet was processed on,
|
|
e.g. <devicename>dc0</devicename>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>The group and rule number of the rule, e.g.
|
|
<literal>@0:17</literal>.</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
|
|
<para>These can be viewed with <command>ipfstat
|
|
-in</command>.</para>
|
|
|
|
<orderedlist>
|
|
<listitem>
|
|
<para>The action: p for passed, b for blocked, S for a short
|
|
packet, n did not match any rules, L for a log rule. The
|
|
order of precedence in showing flags is: S, p, b, n, L. A
|
|
capital P or B means that the packet has been logged due to
|
|
a global logging setting, not a particular rule.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>The addresses. This is actually three fields: the
|
|
source address and port (separated by a comma), the ->
|
|
symbol, and the destination address and port.
|
|
209.53.17.22,80 -> 198.73.220.17,1722.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>PR</literal> followed by the protocol name or
|
|
number, e.g. PR tcp.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>len</literal> followed by the header length
|
|
and total length of the packet, e.g. len 20 40.</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
|
|
<para>If the packet is a <acronym>TCP</acronym> packet, there
|
|
will be an additional field starting with a hyphen followed by
|
|
letters corresponding to any flags that were set. See the
|
|
&man.ipmon.8; manual page for a list of letters and their
|
|
flags.</para>
|
|
|
|
<para>If the packet is an ICMP packet, there will be two fields
|
|
at the end, the first always being <quote>ICMP</quote>, and the
|
|
next being the ICMP message and sub-message type, separated by
|
|
a slash, e.g. ICMP 3/3 for a port unreachable message.</para>
|
|
</sect2>
|
|
|
|
<sect2 id="firewalls-ipf-rules-script">
|
|
<title>Building the Rule Script with Symbolic
|
|
Substitution</title>
|
|
|
|
<para>Some experienced IPF users create a file containing the
|
|
rules and code them in a manner compatible with running them as
|
|
a script with symbolic substitution. The major benefit of
|
|
doing this is that you only have to change the value associated
|
|
with the symbolic name and when the script is run all the rules
|
|
containing the symbolic name will have the value substituted in
|
|
the rules. Being a script, you can use symbolic substitution
|
|
to code frequently used values and substitute them in multiple
|
|
rules. You will see this in the following example.</para>
|
|
|
|
<para>The script syntax used here is compatible with the sh, csh,
|
|
and tcsh shells.</para>
|
|
|
|
<para>Symbolic substitution fields are prefixed with a dollar
|
|
sign: <literal>$</literal>.</para>
|
|
|
|
<para>Symbolic fields do not have the $ prefix.</para>
|
|
|
|
<para>The value to populate the symbolic field must be enclosed
|
|
with double quotes (<literal>"</literal>).</para>
|
|
|
|
<para>Start your rule file with something like this:</para>
|
|
|
|
<programlisting>############# Start of IPF rules script ########################
|
|
|
|
oif="dc0" # name of the outbound interface
|
|
odns="192.0.2.11" # ISP's DNS server IP address
|
|
myip="192.0.2.7" # my static IP address from ISP
|
|
ks="keep state"
|
|
fks="flags S keep state"
|
|
|
|
# You can choose between building /etc/ipf.rules file
|
|
# from this script or running this script "as is".
|
|
#
|
|
# Uncomment only one line and comment out another.
|
|
#
|
|
# 1) This can be used for building /etc/ipf.rules:
|
|
#cat > /etc/ipf.rules << EOF
|
|
#
|
|
# 2) This can be used to run script "as is":
|
|
/sbin/ipf -Fa -f - << EOF
|
|
|
|
# Allow out access to my ISP's Domain name server.
|
|
pass out quick on $oif proto tcp from any to $odns port = 53 $fks
|
|
pass out quick on $oif proto udp from any to $odns port = 53 $ks
|
|
|
|
# Allow out non-secure standard www function
|
|
pass out quick on $oif proto tcp from $myip to any port = 80 $fks
|
|
|
|
# Allow out secure www function https over TLS SSL
|
|
pass out quick on $oif proto tcp from $myip to any port = 443 $fks
|
|
EOF
|
|
################## End of IPF rules script ########################</programlisting>
|
|
|
|
<para>That is all there is to it. The rules are not important in
|
|
this example; how the symbolic substitution fields are
|
|
populated and used are. If the above example was in a file
|
|
named <filename>/etc/ipf.rules.script</filename>, you could
|
|
reload these rules by entering the following command:</para>
|
|
|
|
<screen>&prompt.root; <userinput>sh /etc/ipf.rules.script</userinput></screen>
|
|
|
|
<para>There is one problem with using a rules file with embedded
|
|
symbolics: IPF does not understand symbolic substitution, and
|
|
cannot read such scripts directly.</para>
|
|
|
|
<para>This script can be used in one of two ways:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Uncomment the line that begins with
|
|
<literal>cat</literal>, and comment out the line that
|
|
begins with <literal>/sbin/ipf</literal>. Place
|
|
<literal>ipfilter_enable="YES"</literal> into
|
|
<filename>/etc/rc.conf</filename> as usual, and run script
|
|
once after each modification to create or update
|
|
<filename>/etc/ipf.rules</filename>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Disable IPFILTER in system startup scripts by adding
|
|
<literal>ipfilter_enable="NO"</literal> (this is default
|
|
value) into <filename>/etc/rc.conf</filename> file.</para>
|
|
|
|
<para>Add a script like the following to your
|
|
<filename>/usr/local/etc/rc.d/</filename> startup
|
|
directory. The script should have an obvious name like
|
|
<filename>ipf.loadrules.sh</filename>. The
|
|
<filename>.sh</filename> extension is mandatory.</para>
|
|
|
|
<programlisting>#!/bin/sh
|
|
sh /etc/ipf.rules.script</programlisting>
|
|
|
|
<para>The permissions on this script file must be read,
|
|
write, execute for owner <username>root</username>.</para>
|
|
|
|
<screen>&prompt.root; <userinput>chmod 700 /usr/local/etc/rc.d/ipf.loadrules.sh</userinput></screen>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>Now, when your system boots, your IPF rules will be
|
|
loaded.</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>IPF Rule Sets</title>
|
|
|
|
<!-- XXX: looks incorrect (and duplicated 2 times in this chapter):
|
|
1. Packet can be processed two times depend of firewall
|
|
firewall configuration, but "return trip back" is
|
|
another packet.
|
|
2. "Each TCP/IP service ... is predefined by its protocol ..."
|
|
- this shold be about packet and it's parameters
|
|
(source/destination address and port). -->
|
|
|
|
<para>A rule set is a group of ipf rules coded to pass or block
|
|
packets based on the values contained in the packet. The
|
|
bi-directional exchange of packets between hosts comprises a
|
|
session conversation. The firewall rule set processes the
|
|
packet two times, once on its arrival from the public Internet
|
|
host and again as it leaves for its return trip back to the
|
|
public Internet host. Each TCP/IP service (i.e. telnet, www,
|
|
mail, etc.) is predefined by its protocol, source and
|
|
destination IP address, or the source and destination port
|
|
number. This is the basic selection criteria used to create
|
|
rules which will pass or block services.</para>
|
|
|
|
<indexterm>
|
|
<primary>IPFILTER</primary>
|
|
|
|
<secondary>rule processing order</secondary>
|
|
</indexterm>
|
|
|
|
<para>IPF was originally written using a rules processing logic
|
|
of <quote>the last matching rule wins</quote> and used only
|
|
stateless rules. Over time IPF has been enhanced to include a
|
|
<quote>quick</quote> option and a stateful <quote>keep
|
|
state</quote> option which drastically modernized the rule
|
|
processing logic.</para>
|
|
|
|
<para>The instructions contained in this section are based on
|
|
using rules that contain the <quote>quick</quote> option and
|
|
the stateful <quote>keep state</quote> option. This is the
|
|
basic framework for coding an inclusive firewall rule
|
|
set.</para>
|
|
|
|
<!-- XXX: something like this already in
|
|
<xref linkend="firewalls-concepts"/>
|
|
AND: the para below is repeated 3 times in this chapter-->
|
|
|
|
<para>An inclusive firewall only allows services matching the
|
|
rules through. This way you can control what services can
|
|
originate behind the firewall destined for the public Internet
|
|
and also control the services which can originate from the
|
|
public Internet accessing your private network. Everything
|
|
else is blocked and logged by default design. Inclusive
|
|
firewalls are much, much securer than exclusive firewall rule
|
|
sets and is the only rule set type covered herein.</para>
|
|
|
|
<warning>
|
|
<para>When working with the firewall rules, be <emphasis>very
|
|
careful</emphasis>. Some configurations <emphasis>will
|
|
lock you out</emphasis> of the server. To be on the safe
|
|
side, you may wish to consider performing the initial
|
|
firewall configuration from the local console rather than
|
|
doing it remotely e.g. via
|
|
<application>ssh</application>.</para>
|
|
</warning>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Rule Syntax</title>
|
|
|
|
<indexterm>
|
|
<primary>IPFILTER</primary>
|
|
|
|
<secondary>rule syntax</secondary>
|
|
</indexterm>
|
|
|
|
<para>The rule syntax presented here has been simplified to only
|
|
address the modern stateful rule context and <quote>first
|
|
matching rule wins</quote> logic. For the complete legacy rule
|
|
syntax description see the &man.ipf.8; manual page.</para>
|
|
|
|
<para>A <literal>#</literal> character is used to mark the start
|
|
of a comment and may appear at the end of a rule line or on its
|
|
own line. Blank lines are ignored.</para>
|
|
|
|
<para>Rules contain keywords. These keywords have to be coded in
|
|
a specific order from left to right on the line. Keywords are
|
|
identified in bold type. Some keywords have sub-options which
|
|
may be keywords themselves and also include more sub-options.
|
|
Each of the headings in the below syntax has a bold section
|
|
header which expands on the content.</para>
|
|
|
|
<!-- This section is probably wrong. See the OpenBSD flag -->
|
|
<!-- What is the "OpenBSD flag"? Reference please -->
|
|
|
|
<para><replaceable>ACTION IN-OUT OPTIONS SELECTION STATEFUL PROTO
|
|
SRC_ADDR,DST_ADDR OBJECT PORT_NUM TCP_FLAG
|
|
STATEFUL</replaceable></para>
|
|
|
|
<para><replaceable>ACTION</replaceable> = block | pass</para>
|
|
|
|
<para><replaceable>IN-OUT</replaceable> = in | out</para>
|
|
|
|
<para><replaceable>OPTIONS</replaceable> = log | quick | on
|
|
interface-name</para>
|
|
|
|
<para><replaceable>SELECTION</replaceable> = proto value |
|
|
source/destination IP | port = number | flags
|
|
flag-value</para>
|
|
|
|
<para><replaceable>PROTO</replaceable> = tcp/udp | udp | tcp |
|
|
icmp</para>
|
|
|
|
<para><replaceable>SRC_ADD,DST_ADDR</replaceable> = all | from
|
|
object to object</para>
|
|
|
|
<para><replaceable>OBJECT</replaceable> = IP address | any</para>
|
|
|
|
<para><replaceable>PORT_NUM</replaceable> = port number</para>
|
|
|
|
<para><replaceable>TCP_FLAG</replaceable> = S</para>
|
|
|
|
<para><replaceable>STATEFUL</replaceable> = keep state</para>
|
|
|
|
<sect3>
|
|
<title>ACTION</title>
|
|
|
|
<para>The action indicates what to do with the packet if it
|
|
matches the rest of the filter rule. Each rule
|
|
<emphasis>must</emphasis> have a action. The following
|
|
actions are recognized:</para>
|
|
|
|
<para><literal>block</literal> indicates that the packet should
|
|
be dropped if the selection parameters match the
|
|
packet.</para>
|
|
|
|
<para><literal>pass</literal> indicates that the packet should
|
|
exit the firewall if the selection parameters match the
|
|
packet.</para>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>IN-OUT</title>
|
|
|
|
<para>A mandatory requirement is that each filter rule
|
|
explicitly state which side of the I/O it is to be used on.
|
|
The next keyword must be either in or out and one or the
|
|
other has to be coded or the rule will not pass syntax
|
|
checks.</para>
|
|
|
|
<para><literal>in</literal> means this rule is being applied
|
|
against an inbound packet which has just been received on the
|
|
interface facing the public Internet.</para>
|
|
|
|
<para><literal>out</literal> means this rule is being applied
|
|
against an outbound packet destined for the interface facing
|
|
the public Internet.</para>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>OPTIONS</title>
|
|
|
|
<note>
|
|
<para>These options must be used in the order shown
|
|
here.</para>
|
|
</note>
|
|
|
|
<para><literal>log</literal> indicates that the packet header
|
|
will be written to
|
|
|
|
<!-- XXX - xref here -->
|
|
|
|
the <devicename>ipl</devicename> log (as described in the
|
|
LOGGING section below) if the selection parameters match the
|
|
packet.</para>
|
|
|
|
<para><literal>quick</literal> indicates that if the selection
|
|
parameters match the packet, this rule will be the last rule
|
|
checked, allowing a <quote>short-circuit</quote> path to avoid processing
|
|
any following rules for this packet. This option is a
|
|
mandatory requirement for the modernized rules processing
|
|
logic.</para>
|
|
|
|
<para><literal>on</literal> indicates the interface name to be
|
|
incorporated into the selection parameters. Interface names
|
|
are as displayed by &man.ifconfig.8;. Using this option, the
|
|
rule will only match if the packet is going through that
|
|
interface in the specified direction (in/out). This option
|
|
is a mandatory requirement for the modernized rules
|
|
processing logic.</para>
|
|
|
|
<para>When a packet is logged, the headers of the packet are
|
|
written to the IPL packet logging pseudo-device.
|
|
Immediately following the log keyword, the following
|
|
qualifiers may be used (in this order):</para>
|
|
|
|
<para><literal>body</literal> indicates that the first 128
|
|
bytes of the packet contents will be logged after the
|
|
headers.</para>
|
|
|
|
<para><literal>first</literal> If the <literal>log</literal>
|
|
keyword is being used in conjunction with a <quote>keep
|
|
state</quote> option, it is recommended that this option is
|
|
also applied so that only the triggering packet is logged and
|
|
not every packet which thereafter matches the <quote>keep
|
|
state</quote> information.</para>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>SELECTION</title>
|
|
|
|
<para>The keywords described in this section are used to
|
|
describe attributes of the packet to be interrogated when
|
|
determining whether rules match or not. There is a
|
|
keyword subject, and it has sub-option keywords, one of
|
|
which has to be selected. The following general-purpose
|
|
attributes are provided for matching, and must be used in
|
|
this order:</para>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>PROTO</title>
|
|
|
|
<para><literal>proto</literal> is the subject keyword and must
|
|
be coded along with one of its corresponding keyword
|
|
sub-option values. The value allows a specific protocol to
|
|
be matched against. This option is a mandatory requirement
|
|
for the modernized rules processing logic.</para>
|
|
|
|
<para><literal>tcp/udp | udp | tcp | icmp</literal> or any
|
|
protocol names found in <filename>/etc/protocols</filename>
|
|
are recognized and may be used. The special protocol keyword
|
|
<literal>tcp/udp</literal> may be used to match either a
|
|
<acronym>TCP</acronym> or a UDP packet, and has been added as
|
|
a convenience to save duplication of otherwise identical
|
|
rules.</para>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>SRC_ADDR/DST_ADDR</title>
|
|
|
|
<para>The <literal>all</literal> keyword is essentially a
|
|
synonym for <quote>from any to any</quote> with no other
|
|
match parameters.</para>
|
|
|
|
<para><literal>from src to dst</literal>: the from and to
|
|
keywords are used to match against IP addresses. Rules must
|
|
specify BOTH source and destination parameters.
|
|
<literal>any</literal> is a special keyword that matches any
|
|
IP address. Examples of use: <quote>from any to any</quote>
|
|
or <quote>from 0.0.0.0/0 to any</quote> or <quote>from any to
|
|
0.0.0.0/0</quote> or <quote>from 0.0.0.0 to any</quote> or
|
|
<quote>from any to 0.0.0.0</quote>.</para>
|
|
|
|
<!-- XXX: Needs rewording -->
|
|
|
|
<para>IP addresses may be specified as a dotted IP address
|
|
numeric form/mask-length, or as single dotted IP address
|
|
numeric form.</para>
|
|
|
|
<para>There is no way to match ranges of IP addresses which
|
|
do not express themselves easily as mask-length. See this
|
|
web page for help on writing mask-length: <ulink
|
|
url="http://jodies.de/ipcalc"></ulink>.</para>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>PORT</title>
|
|
|
|
<para>If a port match is included, for either or both of source
|
|
and destination, then it is only applied to
|
|
<acronym>TCP</acronym> and UDP packets. When composing port
|
|
comparisons, either the service name from
|
|
<filename>/etc/services</filename> or an integer port number
|
|
may be used. When the port appears as part of the from
|
|
object, it matches the source port number; when it appears
|
|
as part of the to object, it matches the destination port
|
|
number. The use of the port option with the
|
|
<literal>to</literal> object is a mandatory requirement for
|
|
the modernized rules processing logic. Example of use:
|
|
<quote>from any to any port = 80</quote></para>
|
|
|
|
<!-- XXX: Needs rewriting -->
|
|
|
|
<para>Port comparisons may be done in a number of forms, with
|
|
a number of comparison operators, or port ranges may be
|
|
specified.</para>
|
|
|
|
<para>port "=" | "!=" | "<" | ">" | "<=" | ">=" |
|
|
"eq" | "ne" | "lt" | "gt" | "le" | "ge".</para>
|
|
|
|
<para>To specify port ranges, port "<>" |
|
|
"><"</para>
|
|
|
|
<warning>
|
|
<para>Following the source and destination matching
|
|
parameters, the following two parameters are mandatory
|
|
requirements for the modernized rules processing
|
|
logic.</para>
|
|
</warning>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title><acronym>TCP</acronym>_FLAG</title>
|
|
|
|
<para>Flags are only effective for <acronym>TCP</acronym>
|
|
filtering. The letters represents one of the possible flags
|
|
that can be interrogated in the <acronym>TCP</acronym> packet
|
|
header.</para>
|
|
|
|
<para>The modernized rules processing logic uses the
|
|
<literal>flags S</literal> parameter to identify the tcp
|
|
session start request.</para>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>STATEFUL</title>
|
|
|
|
<para><literal>keep state</literal> indicates that on a pass
|
|
rule, any packets that match the rules selection parameters
|
|
should activate the stateful filtering facility.</para>
|
|
|
|
<note>
|
|
<para>This option is a mandatory requirement for the
|
|
modernized rules processing logic.</para>
|
|
</note>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Stateful Filtering</title>
|
|
|
|
<indexterm>
|
|
<primary>IPFILTER</primary>
|
|
|
|
<secondary>stateful filtering</secondary>
|
|
</indexterm>
|
|
|
|
<!-- XXX: duplicated -->
|
|
|
|
<para>Stateful filtering treats traffic as a bi-directional
|
|
exchange of packets comprising a session conversation. When
|
|
activated, keep-state dynamically generates internal rules for
|
|
each anticipated packet being exchanged during the
|
|
bi-directional session conversation. It has the interrogation
|
|
abilities to determine if the session conversation between the
|
|
originating sender and the destination are following the valid
|
|
procedure of bi-directional packet exchange. Any packets that
|
|
do not properly fit the session conversation template are
|
|
automatically rejected as impostors.</para>
|
|
|
|
<para>Keep state will also allow ICMP packets related to a
|
|
<acronym>TCP</acronym> or UDP session through. So if you get
|
|
ICMP type 3 code 4 in response to some web surfing allowed out
|
|
by a keep state rule, they will be automatically allowed in.
|
|
Any packet that IPF can be certain is part of an active
|
|
session, even if it is a different protocol, will be let
|
|
in.</para>
|
|
|
|
<para>What happens is:</para>
|
|
|
|
<para>Packets destined to go out the interface connected to the
|
|
public Internet are first checked against the dynamic state
|
|
table, if the packet matches the next expected packet
|
|
comprising in a active session conversation, then it exits the
|
|
firewall and the state of the session conversation flow is
|
|
updated in the dynamic state table, the remaining packets get
|
|
checked against the outbound rule set.</para>
|
|
|
|
<para>Packets coming in to the interface connected to the public
|
|
Internet are first checked against the dynamic state table, if
|
|
the packet matches the next expected packet comprising a
|
|
active session conversation, then it exits the firewall and
|
|
the state of the session conversation flow is updated in the
|
|
dynamic state table, the remaining packets get checked against
|
|
the inbound rule set.</para>
|
|
|
|
<para>When the conversation completes it is removed from the
|
|
dynamic state table.</para>
|
|
|
|
<para>Stateful filtering allows you to focus on blocking/passing
|
|
new sessions. If the new session is passed, all its subsequent
|
|
packets will be allowed through automatically and any impostors
|
|
automatically rejected. If a new session is blocked, none of
|
|
its subsequent packets will be allowed through. Stateful
|
|
filtering has technically advanced interrogation abilities
|
|
capable of defending against the flood of different attack
|
|
methods currently employed by attackers.</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<!-- XXX: This section needs a rewrite -->
|
|
|
|
<title>Inclusive Rule Set Example</title>
|
|
|
|
<para>The following rule set is an example of how to code a very
|
|
secure inclusive type of firewall. An inclusive firewall only
|
|
allows services matching pass rules through and blocks all
|
|
other by default. All firewalls have at the minimum two
|
|
interfaces which have to have rules to allow the firewall to
|
|
function.</para>
|
|
|
|
<para>All &unix; flavored systems including &os; are designed to
|
|
use interface <devicename>lo0</devicename> and IP address
|
|
<hostid role="ipaddr">127.0.0.1</hostid> for internal
|
|
communication within the operating system. The firewall rules
|
|
must contain rules to allow free unmolested movement of these
|
|
special internally used packets.</para>
|
|
|
|
<para>The interface which faces the public Internet is the one
|
|
where you place your rules to authorize and control access out
|
|
to the public Internet and access requests arriving from the
|
|
public Internet. This can be your user PPP
|
|
<devicename>tun0</devicename> interface or your NIC that is
|
|
connected to your DSL or cable modem.</para>
|
|
|
|
<para>In cases where one or more NICs are cabled to private LANs
|
|
behind the firewall, those interfaces must have a rule coded to
|
|
allow free unmolested movement of packets originating from
|
|
those LAN interfaces.</para>
|
|
|
|
<para>The rules should be first organized into three major
|
|
sections: all the free unmolested interfaces, the public
|
|
interface outbound, and the public interface inbound.</para>
|
|
|
|
<para>The rules in each of the public interface sections should
|
|
have the most frequently matched rules placed before less
|
|
commonly matched rules, with the last rule in the section
|
|
blocking and logging all packets on that interface and
|
|
direction.</para>
|
|
|
|
<para>The Outbound section in the following rule set only
|
|
contains 'pass' rules which contain selection values that
|
|
uniquely identify the service that is authorized for public
|
|
Internet access. All the rules have the 'quick', 'on',
|
|
'proto', 'port', and 'keep state' option coded. The 'proto
|
|
tcp' rules have the 'flag' option included to identify the
|
|
session start request as the triggering packet to activate the
|
|
stateful facility.</para>
|
|
|
|
<para>The Inbound section has all the blocking of undesirable
|
|
packets first, for two different reasons. The first is that
|
|
these things being blocked may be part of an otherwise valid
|
|
packet which may be allowed in by the later authorized service
|
|
rules. The second reason is that by having a rule that
|
|
explicitly blocks selected packets that I receive on an
|
|
infrequent basis and that I do not want to see in the log, they
|
|
will not be caught by the last rule in the section which blocks
|
|
and logs all packets which have fallen through the rules. The
|
|
last rule in the section which blocks and logs all packets is
|
|
how you create the legal evidence needed to prosecute the
|
|
people who are attacking your system.</para>
|
|
|
|
<para>Another thing you should take note of, is there is no
|
|
response returned for any of the undesirable stuff, their
|
|
packets just get dropped and vanish. This way the attacker
|
|
has no knowledge if his packets have reached your system. The
|
|
less the attackers can learn about your system, the more
|
|
time they must invest before actually doing something bad.
|
|
The inbound 'nmap OS fingerprint' attempts rule I log
|
|
|
|
<!-- XXX: what? -->
|
|
|
|
the first occurrence because this is something a attacker
|
|
would do.</para>
|
|
|
|
<para>Any time you see log messages on a rule with 'log first'.
|
|
You should do an <command>ipfstat -hio</command> command to see
|
|
the number of times the rule has been matched so you know if
|
|
you are being flooded, i.e. under attack.</para>
|
|
|
|
<para>When you log packets with port numbers you do not
|
|
recognize, look it up in <filename>/etc/services</filename> or
|
|
go to <ulink
|
|
url="http://www.securitystats.com/tools/portsearch.php"></ulink>
|
|
and do a port number lookup to find what the purpose of that
|
|
port number is.</para>
|
|
|
|
<para>Check out this link for port numbers used by Trojans <ulink
|
|
url="http://www.simovits.com/trojans/trojans.html"></ulink>.</para>
|
|
|
|
<para>The following rule set is a complete very secure
|
|
'inclusive' type of firewall rule set that I have used on my
|
|
system. You can not go wrong using this rule set for your own.
|
|
Just comment out any pass rules for services that you do not
|
|
want to authorize.</para>
|
|
|
|
<para>If you see messages in your log that you want to stop
|
|
seeing just add a block rule in the inbound section.</para>
|
|
|
|
<para>You have to change the <devicename>dc0</devicename>
|
|
interface name in every rule to the interface name of the Nic
|
|
card that connects your system to the public Internet. For
|
|
user PPP it would be <devicename>tun0</devicename>.</para>
|
|
|
|
<para>Add the following statements to
|
|
<filename>/etc/ipf.rules</filename>:</para>
|
|
|
|
<programlisting>#################################################################
|
|
# No restrictions on Inside LAN Interface for private network
|
|
# Not needed unless you have LAN
|
|
#################################################################
|
|
|
|
#pass out quick on xl0 all
|
|
#pass in quick on xl0 all
|
|
|
|
#################################################################
|
|
# No restrictions on Loopback Interface
|
|
#################################################################
|
|
pass in quick on lo0 all
|
|
pass out quick on lo0 all
|
|
|
|
#################################################################
|
|
# Interface facing Public Internet (Outbound Section)
|
|
# Interrogate session start requests originating from behind the
|
|
# firewall on the private network
|
|
# or from this gateway server destine for the public Internet.
|
|
#################################################################
|
|
|
|
# Allow out access to my ISP's Domain name server.
|
|
# xxx must be the IP address of your ISP's DNS.
|
|
# Dup these lines if your ISP has more than one DNS server
|
|
# Get the IP addresses from /etc/resolv.conf file
|
|
pass out quick on dc0 proto tcp from any to xxx port = 53 flags S keep state
|
|
pass out quick on dc0 proto udp from any to xxx port = 53 keep state
|
|
|
|
# Allow out access to my ISP's DHCP server for cable or DSL networks.
|
|
# This rule is not needed for 'user ppp' type connection to the
|
|
# public Internet, so you can delete this whole group.
|
|
# Use the following rule and check log for IP address.
|
|
# Then put IP address in commented out rule & delete first rule
|
|
pass out log quick on dc0 proto udp from any to any port = 67 keep state
|
|
#pass out quick on dc0 proto udp from any to z.z.z.z port = 67 keep state
|
|
|
|
|
|
# Allow out non-secure standard www function
|
|
pass out quick on dc0 proto tcp from any to any port = 80 flags S keep state
|
|
|
|
# Allow out secure www function https over TLS SSL
|
|
pass out quick on dc0 proto tcp from any to any port = 443 flags S keep state
|
|
|
|
# Allow out send & get email function
|
|
pass out quick on dc0 proto tcp from any to any port = 110 flags S keep state
|
|
pass out quick on dc0 proto tcp from any to any port = 25 flags S keep state
|
|
|
|
# Allow out Time
|
|
pass out quick on dc0 proto tcp from any to any port = 37 flags S keep state
|
|
|
|
# Allow out nntp news
|
|
pass out quick on dc0 proto tcp from any to any port = 119 flags S keep state
|
|
|
|
# Allow out gateway & LAN users non-secure FTP ( both passive & active modes)
|
|
# This function uses the IP<acronym>NAT</acronym> built in FTP proxy function coded in
|
|
# the nat rules file to make this single rule function correctly.
|
|
# If you want to use the pkg_add command to install application packages
|
|
# on your gateway system you need this rule.
|
|
pass out quick on dc0 proto tcp from any to any port = 21 flags S keep state
|
|
|
|
# Allow out secure FTP, Telnet, and SCP
|
|
# This function is using SSH (secure shell)
|
|
pass out quick on dc0 proto tcp from any to any port = 22 flags S keep state
|
|
|
|
# Allow out non-secure Telnet
|
|
pass out quick on dc0 proto tcp from any to any port = 23 flags S keep state
|
|
|
|
# Allow out FBSD CVSUP function
|
|
pass out quick on dc0 proto tcp from any to any port = 5999 flags S keep state
|
|
|
|
# Allow out ping to public Internet
|
|
pass out quick on dc0 proto icmp from any to any icmp-type 8 keep state
|
|
|
|
# Allow out whois for LAN PC to public Internet
|
|
pass out quick on dc0 proto tcp from any to any port = 43 flags S keep state
|
|
|
|
# Block and log only the first occurrence of everything
|
|
# else that's trying to get out.
|
|
# This rule enforces the block all by default logic.
|
|
block out log first quick on dc0 all
|
|
|
|
#################################################################
|
|
# Interface facing Public Internet (Inbound Section)
|
|
# Interrogate packets originating from the public Internet
|
|
# destine for this gateway server or the private network.
|
|
#################################################################
|
|
|
|
# Block all inbound traffic from non-routable or reserved address spaces
|
|
block in quick on dc0 from 192.168.0.0/16 to any #RFC 1918 private IP
|
|
block in quick on dc0 from 172.16.0.0/12 to any #RFC 1918 private IP
|
|
block in quick on dc0 from 10.0.0.0/8 to any #RFC 1918 private IP
|
|
block in quick on dc0 from 127.0.0.0/8 to any #loopback
|
|
block in quick on dc0 from 0.0.0.0/8 to any #loopback
|
|
block in quick on dc0 from 169.254.0.0/16 to any #DHCP auto-config
|
|
block in quick on dc0 from 192.0.2.0/24 to any #reserved for docs
|
|
block in quick on dc0 from 204.152.64.0/23 to any #Sun cluster interconnect
|
|
block in quick on dc0 from 224.0.0.0/3 to any #Class D & E multicast
|
|
|
|
##### Block a bunch of different nasty things. ############
|
|
# That I do not want to see in the log
|
|
|
|
# Block frags
|
|
block in quick on dc0 all with frags
|
|
|
|
# Block short tcp packets
|
|
block in quick on dc0 proto tcp all with short
|
|
|
|
# block source routed packets
|
|
block in quick on dc0 all with opt lsrr
|
|
block in quick on dc0 all with opt ssrr
|
|
|
|
# Block nmap OS fingerprint attempts
|
|
# Log first occurrence of these so I can get their IP address
|
|
block in log first quick on dc0 proto tcp from any to any flags FUP
|
|
|
|
# Block anything with special options
|
|
block in quick on dc0 all with ipopts
|
|
|
|
# Block public pings
|
|
block in quick on dc0 proto icmp all icmp-type 8
|
|
|
|
# Block ident
|
|
block in quick on dc0 proto tcp from any to any port = 113
|
|
|
|
# Block all Netbios service. 137=name, 138=datagram, 139=session
|
|
# Netbios is MS/Windows sharing services.
|
|
# Block MS/Windows hosts2 name server requests 81
|
|
block in log first quick on dc0 proto tcp/udp from any to any port = 137
|
|
block in log first quick on dc0 proto tcp/udp from any to any port = 138
|
|
block in log first quick on dc0 proto tcp/udp from any to any port = 139
|
|
block in log first quick on dc0 proto tcp/udp from any to any port = 81
|
|
|
|
# Allow traffic in from ISP's DHCP server. This rule must contain
|
|
# the IP address of your ISP's DHCP server as it's the only
|
|
# authorized source to send this packet type. Only necessary for
|
|
# cable or DSL configurations. This rule is not needed for
|
|
# 'user ppp' type connection to the public Internet.
|
|
# This is the same IP address you captured and
|
|
# used in the outbound section.
|
|
pass in quick on dc0 proto udp from z.z.z.z to any port = 68 keep state
|
|
|
|
# Allow in standard www function because I have apache server
|
|
pass in quick on dc0 proto tcp from any to any port = 80 flags S keep state
|
|
|
|
# Allow in non-secure Telnet session from public Internet
|
|
# labeled non-secure because ID/PW passed over public Internet as clear text.
|
|
# Delete this sample group if you do not have telnet server enabled.
|
|
#pass in quick on dc0 proto tcp from any to any port = 23 flags S keep state
|
|
|
|
# Allow in secure FTP, Telnet, and SCP from public Internet
|
|
# This function is using SSH (secure shell)
|
|
pass in quick on dc0 proto tcp from any to any port = 22 flags S keep state
|
|
|
|
# Block and log only first occurrence of all remaining traffic
|
|
# coming into the firewall. The logging of only the first
|
|
# occurrence stops a .denial of service. attack targeted
|
|
# at filling up your log file space.
|
|
# This rule enforces the block all by default logic.
|
|
block in log first quick on dc0 all
|
|
################### End of rules file #####################################</programlisting>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title><acronym>NAT</acronym></title>
|
|
|
|
<indexterm><primary>NAT</primary></indexterm>
|
|
|
|
<indexterm>
|
|
<primary>IP masquerading</primary>
|
|
|
|
<see>NAT</see>
|
|
</indexterm>
|
|
|
|
<indexterm>
|
|
<primary>network address translation</primary>
|
|
|
|
<see>NAT</see>
|
|
</indexterm>
|
|
|
|
<para><acronym>NAT</acronym> stands for Network Address
|
|
Translation. To those familiar with &linux;, this concept is
|
|
called IP Masquerading; <acronym>NAT</acronym> and IP
|
|
Masquerading are the same thing. One of the many things the
|
|
IPF <acronym>NAT</acronym> function enables is the ability to
|
|
have a private Local Area Network (LAN) behind the firewall
|
|
sharing a single ISP assigned IP address on the public
|
|
Internet.</para>
|
|
|
|
<para>You may ask why would someone want to do this. ISPs
|
|
normally assign a dynamic IP address to their non-commercial
|
|
users. Dynamic means that the IP address can be different each
|
|
time you dial in and log on to your ISP, or for cable and DSL
|
|
modem users when you power off and then power on your modems
|
|
you can get assigned a different IP address. This IP address
|
|
is how you are known to the public Internet.</para>
|
|
|
|
<para>Now lets say you have five PCs at home and each one needs
|
|
Internet access. You would have to pay your ISP for an
|
|
individual Internet account for each PC and have five phone
|
|
lines.</para>
|
|
|
|
<para>With <acronym>NAT</acronym> you only need a single account
|
|
with your ISP, then cable your other four PCs to a switch and
|
|
the switch to the NIC in your &os; system which is going to
|
|
service your LAN as a gateway. <acronym>NAT</acronym> will
|
|
automatically translate the private LAN IP address for each
|
|
separate PC on the LAN to the single public IP address as it
|
|
exits the firewall bound for the public Internet. It also does
|
|
the reverse translation for returning packets.</para>
|
|
|
|
<para><acronym>NAT</acronym> is most often accomplished without
|
|
the approval, or knowledge, of your ISP and in most cases is
|
|
grounds for your ISP terminating your account if found out.
|
|
Commercial users pay a lot more for their Internet connection
|
|
and usually get assigned a block of static IP address which
|
|
never change. The ISP also expects and consents to their
|
|
Commercial customers using <acronym>NAT</acronym> for their
|
|
internal private LANs.</para>
|
|
|
|
<para>There is a special range of IP addresses reserved for
|
|
<acronym>NAT</acronym>ed private LAN IP address. According to
|
|
RFC 1918, you can use the following IP ranges for private nets
|
|
which will never be routed directly to the public
|
|
Internet:</para>
|
|
|
|
<informaltable frame="none" pgwide="1">
|
|
<tgroup cols="3">
|
|
<colspec colwidth="1*"/>
|
|
|
|
<colspec colwidth="1*"/>
|
|
|
|
<colspec colwidth="1*"/>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry>Start IP <hostid role="ipaddr">10.0.0.0</hostid></entry>
|
|
|
|
<entry>-</entry>
|
|
|
|
<entry>Ending IP <hostid role="ipaddr">10.255.255.255</hostid></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>Start IP <hostid role="ipaddr">172.16.0.0</hostid></entry>
|
|
|
|
<entry>-</entry>
|
|
|
|
<entry>Ending IP <hostid role="ipaddr">172.31.255.255</hostid></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>Start IP <hostid role="ipaddr">192.168.0.0</hostid></entry>
|
|
|
|
<entry>-</entry>
|
|
|
|
<entry>Ending IP <hostid role="ipaddr">192.168.255.255</hostid></entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>IP<acronym>NAT</acronym></title>
|
|
|
|
<indexterm>
|
|
<primary>NAT</primary>
|
|
|
|
<secondary>and IPFILTER</secondary>
|
|
</indexterm>
|
|
|
|
<indexterm><primary><command>ipnat</command></primary></indexterm>
|
|
|
|
<para><acronym>NAT</acronym> rules are loaded by using the
|
|
<command>ipnat</command> command. Typically the
|
|
<acronym>NAT</acronym> rules are stored in
|
|
<filename>/etc/ipnat.rules</filename>. See &man.ipnat.1; for
|
|
details.</para>
|
|
|
|
<para>When changing the <acronym>NAT</acronym> rules after
|
|
<acronym>NAT</acronym> has been started, make your changes to
|
|
the file containing the NAT rules, then run ipnat command with
|
|
the <option>-CF</option> flags to delete the internal in use
|
|
<acronym>NAT</acronym> rules and flush the contents of the
|
|
translation table of all active entries.</para>
|
|
|
|
<para>To reload the <acronym>NAT</acronym> rules issue a command
|
|
like this:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ipnat -CF -f /etc/ipnat.rules</userinput></screen>
|
|
|
|
<para>To display some statistics about your
|
|
<acronym>NAT</acronym>, use this command:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ipnat -s</userinput></screen>
|
|
|
|
<para>To list the <acronym>NAT</acronym> table's current
|
|
mappings, use this command:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ipnat -l</userinput></screen>
|
|
|
|
<para>To turn verbose mode on, and display information relating
|
|
to rule processing and active rules/table entries:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ipnat -v</userinput></screen>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>IP<acronym>NAT</acronym> Rules</title>
|
|
|
|
<para><acronym>NAT</acronym> rules are very flexible and can
|
|
accomplish many different things to fit the needs of commercial
|
|
and home users.</para>
|
|
|
|
<para>The rule syntax presented here has been simplified to what
|
|
is most commonly used in a non-commercial environment. For a
|
|
complete rule syntax description see the &man.ipnat.5; manual
|
|
page.</para>
|
|
|
|
<para>The syntax for a <acronym>NAT</acronym> rule looks
|
|
something like this:</para>
|
|
|
|
<programlisting>map <replaceable>IF</replaceable> <replaceable>LAN_IP_RANGE</replaceable> -> <replaceable>PUBLIC_ADDRESS</replaceable></programlisting>
|
|
|
|
<para>The keyword <literal>map</literal> starts the rule.</para>
|
|
|
|
<para>Replace <replaceable>IF</replaceable> with the external
|
|
interface.</para>
|
|
|
|
<para>The <replaceable>LAN_IP_RANGE</replaceable> is what your
|
|
internal clients use for IP Addressing, usually this is
|
|
something like <hostid
|
|
role="ipaddr">192.168.1.0/24</hostid>.</para>
|
|
|
|
<para>The <replaceable>PUBLIC_ADDRESS</replaceable> can either
|
|
be the external IP address or the special keyword
|
|
<literal>0/32</literal>, which means to use the IP address
|
|
assigned to <replaceable>IF</replaceable>.</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>How <acronym>NAT</acronym> works</title>
|
|
|
|
<para>A packet arrives at the firewall from the LAN with a public
|
|
destination. It passes through the outbound filter rules,
|
|
<acronym>NAT</acronym> gets his turn at the packet and applies
|
|
its rules top down, first matching rule wins.
|
|
<acronym>NAT</acronym> tests each of its rules against the
|
|
packets interface name and source IP address. When a packets
|
|
interface name matches a <acronym>NAT</acronym> rule then the
|
|
[source IP address, i.e. private LAN IP address] of the packet
|
|
is checked to see if it falls within the IP address range
|
|
specified to the left of the arrow symbol on the
|
|
<acronym>NAT</acronym> rule. On a match the packet has its
|
|
source IP address rewritten with the public IP address
|
|
obtained by the <literal>0/32</literal> keyword.
|
|
<acronym>NAT</acronym> posts a entry in its internal
|
|
<acronym>NAT</acronym> table so when the packet returns from
|
|
the public Internet it can be mapped back to its original
|
|
private IP address and then passed to the filter rules for
|
|
processing.</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Enabling IP<acronym>NAT</acronym></title>
|
|
|
|
<para>To enable IP<acronym>NAT</acronym> add these statements to
|
|
<filename>/etc/rc.conf</filename>.</para>
|
|
|
|
<para>To enable your machine to route traffic between
|
|
interfaces:</para>
|
|
|
|
<programlisting>gateway_enable="YES"</programlisting>
|
|
|
|
<para>To start IP<acronym>NAT</acronym> automatically each
|
|
time:</para>
|
|
|
|
<programlisting>ipnat_enable="YES"</programlisting>
|
|
|
|
<para>To specify where to load the IP<acronym>NAT</acronym> rules
|
|
from:</para>
|
|
|
|
<programlisting>ipnat_rules="/etc/ipnat.rules"</programlisting>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title><acronym>NAT</acronym> for a very large LAN</title>
|
|
|
|
<para>For networks that have large numbers of PC's on the LAN or
|
|
networks with more than a single LAN, the process of funneling
|
|
all those private IP addresses into a single public IP address
|
|
becomes a resource problem that may cause problems with the
|
|
same port numbers being used many times across many
|
|
<acronym>NAT</acronym>ed LAN PC's, causing collisions. There
|
|
are two ways to relieve this resource problem.</para>
|
|
|
|
<sect3>
|
|
<title>Assigning Ports to Use</title>
|
|
|
|
<!-- What does it mean ? Is there something missing ?-->
|
|
<!-- XXXBLAH <- Apparently you can't start a sect
|
|
with a <programlisting> tag ?-->
|
|
|
|
<para>A normal NAT rule would look like:</para>
|
|
|
|
<programlisting>map dc0 192.168.1.0/24 -> 0/32</programlisting>
|
|
|
|
<para>In the above rule the packet's source port is unchanged
|
|
as the packet passes through IP<acronym>NAT</acronym>. By
|
|
adding the portmap keyword you can tell
|
|
IP<acronym>NAT</acronym> to only use source ports in a range.
|
|
For example the following rule will tell
|
|
IP<acronym>NAT</acronym> to modify the source port to be
|
|
within that range:</para>
|
|
|
|
<programlisting>map dc0 192.168.1.0/24 -> 0/32 portmap tcp/udp 20000:60000</programlisting>
|
|
|
|
<para>Additionally we can make things even easier by using the
|
|
<literal>auto</literal> keyword to tell
|
|
IP<acronym>NAT</acronym> to determine by itself which ports
|
|
are available to use:</para>
|
|
|
|
<programlisting>map dc0 192.168.1.0/24 -> 0/32 portmap tcp/udp auto</programlisting>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>Using a pool of public addresses</title>
|
|
|
|
<para>In very large LANs there comes a point where there are just too
|
|
many LAN addresses to fit into a single public address. If a block
|
|
of public IP addresses is available, you can use these addresses as
|
|
a <quote>pool</quote>, and let IP<acronym>NAT</acronym> pick one of
|
|
the public IP addresses as packet-addresses are mapped on their way
|
|
out.</para>
|
|
|
|
<para>For example, instead of mapping all packets through a single
|
|
public IP address, as in:</para>
|
|
|
|
<programlisting>map dc0 192.168.1.0/24 -> 204.134.75.1</programlisting>
|
|
|
|
<para>A range of public IP addresses can be specified either with a
|
|
netmask:</para>
|
|
|
|
<programlisting>map dc0 192.168.1.0/24 -> 204.134.75.0/255.255.255.0</programlisting>
|
|
|
|
<para>or using CIDR notation:</para>
|
|
|
|
<programlisting>map dc0 192.168.1.0/24 -> 204.134.75.0/24</programlisting>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Port Redirection</title>
|
|
|
|
<para>A very common practice is to have a web server, email
|
|
server, database server and DNS server each segregated to a
|
|
different PC on the LAN. In this case the traffic from these
|
|
servers still have to be <acronym>NAT</acronym>ed, but there
|
|
has to be some way to direct the inbound traffic to the
|
|
correct LAN PCs. IP<acronym>NAT</acronym> has the redirection
|
|
facilities of <acronym>NAT</acronym> to solve this problem.
|
|
Lets say you have your web server on LAN address <hostid
|
|
role="ipaddr">10.0.10.25</hostid> and your single public IP
|
|
address is <hostid role="ipaddr">20.20.20.5</hostid> you would
|
|
code the rule like this:</para>
|
|
|
|
<programlisting>rdr dc0 20.20.20.5/32 port 80 -> 10.0.10.25 port 80</programlisting>
|
|
|
|
<para>or:</para>
|
|
|
|
<programlisting>rdr dc0 0/32 port 80 -> 10.0.10.25 port 80</programlisting>
|
|
|
|
<para>or for a LAN DNS Server on LAN address of <hostid
|
|
role="ipaddr">10.0.10.33</hostid> that needs to receive
|
|
public DNS requests:</para>
|
|
|
|
<programlisting>rdr dc0 20.20.20.5/32 port 53 -> 10.0.10.33 port 53 udp</programlisting>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>FTP and <acronym>NAT</acronym></title>
|
|
|
|
<para>FTP is a dinosaur left over from the time before the
|
|
Internet as it is known today, when research universities were
|
|
leased lined together and FTP was used to share files among
|
|
research Scientists. This was a time when data security was
|
|
not a consideration. Over the years the FTP protocol became
|
|
buried into the backbone of the emerging Internet and its
|
|
username and password being sent in clear text was never
|
|
changed to address new security concerns. FTP has two flavors,
|
|
it can run in active mode or passive mode. The difference is
|
|
in how the data channel is acquired. Passive mode is more
|
|
secure as the data channel is acquired be the ordinal ftp
|
|
session requester. For a real good explanation of FTP and the
|
|
different modes see <ulink
|
|
url="http://www.slacksite.com/other/ftp.html"></ulink>.</para>
|
|
|
|
<sect3>
|
|
<title>IP<acronym>NAT</acronym> Rules</title>
|
|
|
|
<para>IP<acronym>NAT</acronym> has a special built in FTP proxy
|
|
option which can be specified on the <acronym>NAT</acronym>
|
|
map rule. It can monitor all outbound packet traffic for FTP
|
|
active or passive start session requests and dynamically
|
|
create temporary filter rules containing only the port number
|
|
really in use for the data channel. This eliminates the
|
|
security risk FTP normally exposes the firewall to from
|
|
having large ranges of high order port numbers open.</para>
|
|
|
|
<para>This rule will handle all the traffic for the internal
|
|
LAN:</para>
|
|
|
|
<programlisting>map dc0 10.0.10.0/29 -> 0/32 proxy port 21 ftp/tcp</programlisting>
|
|
|
|
<para>This rule handles the FTP traffic from the
|
|
gateway:</para>
|
|
|
|
<programlisting>map dc0 0.0.0.0/0 -> 0/32 proxy port 21 ftp/tcp</programlisting>
|
|
|
|
<para>This rule handles all non-FTP traffic from the internal
|
|
LAN:</para>
|
|
|
|
<programlisting>map dc0 10.0.10.0/29 -> 0/32</programlisting>
|
|
|
|
<para>The FTP map rule goes before our regular map rule. All
|
|
packets are tested against the first rule from the top.
|
|
Matches on interface name, then private LAN source IP
|
|
address, and then is it a FTP packet. If all that matches
|
|
then the special FTP proxy creates temp filter rules to let
|
|
the FTP session packets pass in and out, in addition to also
|
|
<acronym>NAT</acronym>ing the FTP packets. All LAN packets
|
|
that are not FTP do not match the first rule and fall
|
|
through to the third rule and are tested, matching on
|
|
interface and source IP, then are
|
|
<acronym>NAT</acronym>ed.</para>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>IP<acronym>NAT</acronym> FTP Filter Rules</title>
|
|
|
|
<para>Only one filter rule is needed for FTP if the
|
|
<acronym>NAT</acronym> FTP proxy is used.</para>
|
|
|
|
<para>Without the FTP Proxy you will need the following three
|
|
rules:</para>
|
|
|
|
<programlisting># Allow out LAN PC client FTP to public Internet
|
|
# Active and passive modes
|
|
pass out quick on rl0 proto tcp from any to any port = 21 flags S keep state
|
|
|
|
# Allow out passive mode data channel high order port numbers
|
|
pass out quick on rl0 proto tcp from any to any port > 1024 flags S keep state
|
|
|
|
# Active mode let data channel in from FTP server
|
|
pass in quick on rl0 proto tcp from any to any port = 20 flags S keep state</programlisting>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>FTP <acronym>NAT</acronym> Proxy Bug</title>
|
|
|
|
<para>As of IPFILTER version 3.4.31
|
|
the FTP proxy works as documented during the FTP session
|
|
until the session is told to close. When the close happens
|
|
packets returning from the remote FTP server are blocked and
|
|
logged coming in on port 21. The <acronym>NAT</acronym>
|
|
FTP/proxy appears to remove its temp rules prematurely,
|
|
before receiving the response from the remote FTP server
|
|
acknowledging the close. A problem report was posted to the
|
|
IPF mailing list.</para>
|
|
|
|
<para>The solution is to add a filter rule to get rid of these
|
|
unwanted log messages or do nothing and ignore FTP inbound
|
|
error messages in your log. Most people do not use outbound
|
|
FTP too often.</para>
|
|
|
|
<programlisting>block in quick on rl0 proto tcp from any to any port = 21</programlisting>
|
|
</sect3>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 id="firewalls-ipfw">
|
|
<title>IPFW</title>
|
|
|
|
<indexterm>
|
|
<primary>firewall</primary>
|
|
|
|
<secondary>IPFW</secondary>
|
|
</indexterm>
|
|
|
|
<note>
|
|
<para>This section is work in progress. The contents might
|
|
not be accurate at all times.</para>
|
|
</note>
|
|
|
|
<para>The IPFIREWALL (IPFW) is a &os; sponsored firewall software
|
|
application authored and maintained by &os; volunteer staff
|
|
members. It uses the legacy stateless rules and a legacy rule
|
|
coding technique to achieve what is referred to as Simple
|
|
Stateful logic.</para>
|
|
|
|
<para>The IPFW sample rule set (found in
|
|
<filename>/etc/rc.firewall</filename>) in the standard &os;
|
|
install is rather simple and it is not expected that it used
|
|
directly without modifications. The example does not use
|
|
stateful filtering, which is beneficial in most setups, so it
|
|
will not be used as base for this section.</para>
|
|
|
|
<para>The IPFW stateless rule syntax is empowered with technically
|
|
sophisticated selection capabilities which far surpasses the
|
|
knowledge level of the customary firewall installer. IPFW is
|
|
targeted at the professional user or the advanced technical
|
|
computer hobbyist who have advanced packet selection
|
|
requirements. A high degree of detailed knowledge into how
|
|
different protocols use and create their unique packet header
|
|
information is necessary before the power of the IPFW rules can
|
|
be unleashed. Providing that level of explanation is out of the
|
|
scope of this section of the handbook.</para>
|
|
|
|
<para>IPFW is composed of seven components, the primary component
|
|
is the kernel firewall filter rule processor and its integrated
|
|
packet accounting facility, the logging facility, the 'divert'
|
|
rule which triggers the <acronym>NAT</acronym> facility, and the
|
|
advanced special purpose facilities, the dummynet traffic shaper
|
|
facilities, the 'fwd rule' forward facility, the bridge
|
|
facility, and the ipstealth facility.</para>
|
|
|
|
<sect2 id="firewalls-ipfw-enable">
|
|
<title>Enabling IPFW</title>
|
|
|
|
<indexterm>
|
|
<primary>IPFW</primary>
|
|
|
|
<secondary>enabling</secondary>
|
|
</indexterm>
|
|
|
|
<para>IPFW is included in the basic &os; install as a separate
|
|
run time loadable module. The system will dynamically load the
|
|
kernel module when the <filename>rc.conf</filename> statement
|
|
<literal>firewall_enable="YES"</literal> is used. You do not
|
|
need to compile IPFW into the &os; kernel unless you want
|
|
<acronym>NAT</acronym> function enabled.</para>
|
|
|
|
<para>After rebooting your system with
|
|
<literal>firewall_enable="YES"</literal> in
|
|
<filename>rc.conf</filename> the following white highlighted
|
|
message is displayed on the screen as part of the boot
|
|
process:</para>
|
|
|
|
<screen>ipfw2 initialized, divert disabled, rule-based forwarding disabled, default to deny, logging disabled</screen>
|
|
|
|
<para>The loadable module does have logging ability
|
|
compiled in. To enable logging and set the verbose logging
|
|
limit, there is a knob you can set in
|
|
<filename>/etc/sysctl.conf</filename> by adding these
|
|
statements, logging will be enabled on future reboots:</para>
|
|
|
|
<programlisting>net.inet.ip.fw.verbose=1
|
|
net.inet.ip.fw.verbose_limit=5</programlisting>
|
|
</sect2>
|
|
|
|
<sect2 id="firewalls-ipfw-kernel">
|
|
<title>Kernel Options</title>
|
|
|
|
<indexterm>
|
|
<primary>kernel options</primary>
|
|
|
|
<secondary>IPFIREWALL</secondary>
|
|
</indexterm>
|
|
|
|
<indexterm>
|
|
<primary>kernel options</primary>
|
|
|
|
<secondary>IPFIREWALL_VERBOSE</secondary>
|
|
</indexterm>
|
|
|
|
<indexterm>
|
|
<primary>kernel options</primary>
|
|
|
|
<secondary>IPFIREWALL_VERBOSE_LIMIT</secondary>
|
|
</indexterm>
|
|
|
|
<indexterm>
|
|
<primary>IPFW</primary>
|
|
|
|
<secondary>kernel options</secondary>
|
|
</indexterm>
|
|
|
|
<para>It is not a mandatory requirement that you enable IPFW by
|
|
compiling the following options into the &os; kernel unless
|
|
you need <acronym>NAT</acronym> function. It is presented here
|
|
as background information.</para>
|
|
|
|
<programlisting>options IPFIREWALL</programlisting>
|
|
|
|
<para>This option enables IPFW as part of the kernel</para>
|
|
|
|
<programlisting>options IPFIREWALL_VERBOSE</programlisting>
|
|
|
|
<para>Enables logging of packets that pass through IPFW and have
|
|
the 'log' keyword specified in the rule set.</para>
|
|
|
|
<programlisting>options IPFIREWALL_VERBOSE_LIMIT=5</programlisting>
|
|
|
|
<para>Limits the number of packets logged through &man.syslogd.8;
|
|
on a per entry basis. You may wish to use this option in
|
|
hostile environments which you want to log firewall activity.
|
|
This will close a possible denial of service attack via syslog
|
|
flooding.</para>
|
|
|
|
<indexterm>
|
|
<primary>kernel options</primary>
|
|
|
|
<secondary>IPFIREWALL_DEFAULT_TO_ACCEPT</secondary>
|
|
</indexterm>
|
|
|
|
<programlisting>options IPFIREWALL_DEFAULT_TO_ACCEPT</programlisting>
|
|
|
|
<para>This option will allow everything to pass through the
|
|
firewall by default, which is a good idea when you are first
|
|
setting up your firewall.</para>
|
|
|
|
<programlisting>options IPV6FIREWALL
|
|
options IPV6FIREWALL_VERBOSE
|
|
options IPV6FIREWALL_VERBOSE_LIMIT
|
|
options IPV6FIREWALL_DEFAULT_TO_ACCEPT</programlisting>
|
|
|
|
<para>These options are exactly the same as the IPv4 options but
|
|
they are for IPv6. If you do not use IPv6 you might want to
|
|
use IPV6FIREWALL without any rules to block all IPv6</para>
|
|
|
|
<indexterm>
|
|
<primary>kernel options</primary>
|
|
|
|
<secondary>IPDIVERT</secondary>
|
|
</indexterm>
|
|
|
|
<programlisting>options IPDIVERT</programlisting>
|
|
|
|
<para>This enables the use of <acronym>NAT</acronym>
|
|
functionality.</para>
|
|
|
|
<note>
|
|
<para>If you do not include IPFIREWALL_DEFAULT_TO_ACCEPT or set
|
|
your rules to allow incoming packets you will block all
|
|
packets going to and from this machine.</para>
|
|
</note>
|
|
</sect2>
|
|
|
|
<sect2 id="firewalls-ipfw-rc">
|
|
<title><filename>/etc/rc.conf</filename> Options</title>
|
|
|
|
<para>If you do not have IPFW compiled into your kernel you will
|
|
need to load it with the following statement in your
|
|
<filename>/etc/rc.conf</filename>:</para>
|
|
|
|
<programlisting>firewall_enable="YES"</programlisting>
|
|
|
|
<para>To select one of the default firewall types provided by
|
|
&os;, select one by reading the
|
|
<filename>/etc/rc.firewall</filename> file and place it in
|
|
the following:</para>
|
|
|
|
<programlisting>firewall_type="open"</programlisting>
|
|
|
|
<para>Or load custom rules by setting the following variable to the
|
|
file containing them:</para>
|
|
|
|
<programlisting>firewall_script="/etc/ipfw.rules"</programlisting>
|
|
|
|
<para>Enable logging:</para>
|
|
|
|
<programlisting>firewall_logging="YES"</programlisting>
|
|
|
|
<warning>
|
|
<para>The only thing that the
|
|
<varname>firewall_logging</varname> variable will do is
|
|
setting the <varname>net.inet.ip.fw.verbose</varname> sysctl
|
|
variable to the value of <literal>1</literal> (see <xref
|
|
linkend="firewalls-ipfw-enable"/>). There is no
|
|
<filename>rc.conf</filename> variable to set log limitations,
|
|
but it can be set via sysctl variable, manually or from the
|
|
<filename>/etc/sysctl.conf</filename> file:</para>
|
|
|
|
<programlisting>net.inet.ip.fw.verbose_limit=5</programlisting>
|
|
</warning>
|
|
|
|
<para>If your machine is acting as a gateway, i.e. providing
|
|
Network Address Translation (NAT) via &man.natd.8;, please
|
|
refer to <xref linkend="network-natd"/> for information
|
|
regarding the required <filename>/etc/rc.conf</filename>
|
|
options.</para>
|
|
</sect2>
|
|
|
|
<sect2 id="firewalls-ipfw-cmd">
|
|
<title>The IPFW Command</title>
|
|
|
|
<indexterm><primary><command>ipfw</command></primary></indexterm>
|
|
|
|
<para>The ipfw command is the normal vehicle for making manual
|
|
single rule additions or deletions to the firewall active
|
|
internal rules while it is running. The problem with using
|
|
this method is once your system is shutdown or halted all the
|
|
rules you added or changed or deleted are lost. Writing all
|
|
your rules in a file and using that file to load the rules at
|
|
boot time, or to replace in mass the currently running firewall
|
|
rules with changes you made to the files content is the
|
|
recommended method used here.</para>
|
|
|
|
<para>The ipfw command is still a very useful to display the
|
|
running firewall rules to the console screen. The IPFW
|
|
accounting facility dynamically creates a counter for each
|
|
rule that counts each packet that matches the rule. During the
|
|
process of testing a rule, listing the rule with its counter
|
|
is the one of the ways of determining if the rule is
|
|
functioning.</para>
|
|
|
|
<para>To list all the rules in sequence:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ipfw list</userinput></screen>
|
|
|
|
<para>To list all the rules with a time stamp of when the last
|
|
time the rule was matched:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ipfw -t list</userinput></screen>
|
|
|
|
<para>To list the accounting information, packet count for
|
|
matched rules along with the rules themselves. The first
|
|
column is the rule number, followed by the number of outgoing
|
|
matched packets, followed by the number of incoming matched
|
|
packets, and then the rule itself.</para>
|
|
|
|
<screen>&prompt.root; <userinput>ipfw -a list</userinput></screen>
|
|
|
|
<para>List the dynamic rules in addition to the static
|
|
rules:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ipfw -d list</userinput></screen>
|
|
|
|
<para>Also show the expired dynamic rules:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ipfw -d -e list</userinput></screen>
|
|
|
|
<para>Zero the counters:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ipfw zero</userinput></screen>
|
|
|
|
<para>Zero the counters for just rule
|
|
<replaceable>NUM</replaceable>:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ipfw zero NUM</userinput></screen>
|
|
</sect2>
|
|
|
|
<sect2 id="firewalls-ipfw-rules">
|
|
<title>IPFW Rule Sets</title>
|
|
|
|
<!-- XXX: looks incorrect (and duplicated 2 times in this chapter):
|
|
1. Packet can be processed two times depend of firewall
|
|
firewall configuration, but "return trip back" is
|
|
another packet.
|
|
2. "Each TCP/IP service ... is predefined by its protocol ..."
|
|
- this shold be about packet and it's parameters
|
|
(source/destination address and port). -->
|
|
|
|
<para>A rule set is a group of ipfw rules coded to allow or deny
|
|
packets based on the values contained in the packet. The
|
|
bi-directional exchange of packets between hosts comprises a
|
|
session conversation. The firewall rule set processes the
|
|
packet twice: once on its arrival from the public Internet host
|
|
and again as it leaves for its return trip back to the public
|
|
Internet host. Each tcp/ip service (i.e. telnet, www, mail,
|
|
etc.) is predefined by its protocol, and port number. This is
|
|
the basic selection criteria used to create rules which will
|
|
allow or deny services.</para>
|
|
|
|
<indexterm>
|
|
<primary>IPFW</primary>
|
|
|
|
<secondary>rule processing order</secondary>
|
|
</indexterm>
|
|
|
|
<!-- Needs rewording to include note below -->
|
|
|
|
<para>When a packet enters the firewall it is compared against
|
|
the first rule in the rule set and progress one rule at a time
|
|
moving from top to bottom of the set in ascending rule number
|
|
sequence order. When the packet matches a rule selection
|
|
parameters, the rules action field value is executed and the
|
|
search of the rule set terminates for that packet. This is
|
|
referred to as <quote>the first match wins</quote> search
|
|
method. If the packet does not match any of the rules, it gets
|
|
caught by the mandatory ipfw default rule, number 65535 which
|
|
denies all packets and discards them without any reply back to
|
|
the originating destination.</para>
|
|
|
|
<note>
|
|
<para>The search continues after <literal>count</literal>,
|
|
<literal>skipto</literal> and <literal>tee</literal>
|
|
rules.</para>
|
|
</note>
|
|
|
|
<para>The instructions contained here are based on using rules
|
|
that contain the stateful 'keep state', 'limit', 'in'/'out',
|
|
and via options. This is the basic framework for coding an
|
|
inclusive type firewall rule set.</para>
|
|
|
|
<!-- XXX: something like this already in
|
|
<xref linkend="firewalls-concepts"/>
|
|
AND: the para below is repeated 3 times in this chapter. -->
|
|
|
|
<para>An inclusive firewall only allows services matching the
|
|
rules through. This way you can control what services can
|
|
originate behind the firewall destine for the public Internet
|
|
and also control the services which can originate from the
|
|
public Internet accessing your private network. Everything
|
|
else is denied by default design. Inclusive firewalls are
|
|
much, much more secure than exclusive firewall rule sets and
|
|
is the only rule set type covered here in.</para>
|
|
|
|
<warning>
|
|
<para>When working with the firewall rules be careful, you can
|
|
end up locking your self out.</para>
|
|
</warning>
|
|
|
|
<sect3 id="firewalls-ipfw-rules-syntax">
|
|
<title>Rule Syntax</title>
|
|
|
|
<indexterm>
|
|
<primary>IPFW</primary>
|
|
|
|
<secondary>rule syntax</secondary>
|
|
</indexterm>
|
|
|
|
<para>The rule syntax presented here has been simplified to
|
|
what is necessary to create a standard inclusive type
|
|
firewall rule set. For a complete rule syntax description
|
|
see the &man.ipfw.8; manual page.</para>
|
|
|
|
<para>Rules contain keywords: these keywords have to be coded
|
|
in a specific order from left to right on the line. Keywords
|
|
are identified in bold type. Some keywords have sub-options
|
|
which may be keywords them selves and also include more
|
|
sub-options.</para>
|
|
|
|
<para><literal>#</literal> is used to mark the start of a
|
|
comment and may appear at the end of a rule line or on its
|
|
own lines. Blank lines are ignored.</para>
|
|
|
|
<para><replaceable>CMD RULE_NUMBER ACTION LOGGING SELECTION
|
|
STATEFUL</replaceable></para>
|
|
|
|
<sect4>
|
|
<title>CMD</title>
|
|
|
|
<para>Each new rule has to be prefixed with
|
|
<parameter>add</parameter> to add the
|
|
rule to the internal table.</para>
|
|
</sect4>
|
|
|
|
<sect4>
|
|
<title>RULE_NUMBER</title>
|
|
|
|
<para>Each rule has to have a rule number to go with
|
|
it.</para>
|
|
</sect4>
|
|
|
|
<sect4>
|
|
<title>ACTION</title>
|
|
|
|
<para>A rule can be associated with one of the following
|
|
actions, which will be executed when the packet matches
|
|
the selection criterion of the rule.</para>
|
|
|
|
<para><parameter>allow | accept | pass |
|
|
permit</parameter></para>
|
|
|
|
<para>These all mean the same thing which is to allow packets
|
|
that match the rule to exit the firewall rule processing.
|
|
The search terminates at this rule.</para>
|
|
|
|
<para><parameter>check-state</parameter></para>
|
|
|
|
<para>Checks the packet against the dynamic rules table. If
|
|
a match is found, execute the action associated with the
|
|
rule which generated this dynamic rule, otherwise move to
|
|
the next rule. The check-state rule does not have
|
|
selection criterion. If no check-state rule is present in
|
|
the rule set, the dynamic rules table is checked at the
|
|
first keep-state or limit rule.</para>
|
|
|
|
<para><parameter>deny | drop</parameter></para>
|
|
|
|
<para>Both words mean the same thing which is to discard
|
|
packets that match this rule. The search
|
|
terminates.</para>
|
|
</sect4>
|
|
|
|
<sect4>
|
|
<title>Logging</title>
|
|
|
|
<para><parameter>log</parameter> or
|
|
<parameter>logamount</parameter></para>
|
|
|
|
<para>When a packet matches a rule with the log keyword, a
|
|
message will be logged to syslogd with a facility name of
|
|
SECURITY. The logging only occurs if the number of
|
|
packets logged so far for that particular rule does not
|
|
exceed the logamount parameter. If no logamount is
|
|
specified, the limit is taken from the sysctl variable
|
|
net.inet.ip.fw.verbose_limit. In both cases, a value of
|
|
zero removes the logging limit. Once the limit is
|
|
reached, logging can be re-enabled by clearing the
|
|
logging counter or the packet counter for that rule, see
|
|
the ipfw reset log command.</para>
|
|
|
|
<note>
|
|
<para>Logging is done after
|
|
all other packet matching conditions have been
|
|
successfully verified, and before performing the final
|
|
action (accept, deny) on the packet. It is up to you to
|
|
decide which rules you want to enable logging on.</para>
|
|
</note>
|
|
</sect4>
|
|
|
|
<sect4>
|
|
<title>Selection</title>
|
|
|
|
<para>The keywords described in this section are used to
|
|
describe attributes of the packet to be interrogated when
|
|
determining whether rules match the packet or not.
|
|
The following general-purpose attributes are provided for
|
|
matching, and must be used in this order:</para>
|
|
|
|
<para><parameter>udp | tcp | icmp</parameter></para>
|
|
|
|
<para>or any protocol names found in
|
|
<filename>/etc/protocols</filename> are recognized and may
|
|
be used. The value specified is protocol to be matched
|
|
against. This is a mandatory requirement.</para>
|
|
|
|
<para><parameter>from src to dst</parameter></para>
|
|
|
|
<para>The from and to keywords are used to match against IP
|
|
addresses. Rules must specify BOTH source and destination
|
|
parameters. <literal>any</literal> is a special keyword
|
|
that matches any IP address. <literal>me</literal> is a
|
|
special keyword that matches any IP address configured on
|
|
an interface in your &os; system to represent the PC the
|
|
firewall is running on (i.e. this box) as in 'from me to
|
|
any' or 'from any to me' or 'from 0.0.0.0/0 to any' or
|
|
'from any to 0.0.0.0/0' or 'from 0.0.0.0 to any' or 'from
|
|
any to 0.0.0.0' or 'from me to 0.0.0.0'. IP addresses are
|
|
specified as a dotted IP address numeric form/mask-length,
|
|
or as single dotted IP address numeric form. This is a
|
|
mandatory requirement. See this link for help on writing
|
|
mask-lengths. <ulink
|
|
url="http://jodies.de/ipcalc"></ulink></para>
|
|
|
|
<para><parameter>port number</parameter></para>
|
|
|
|
<para>For protocols which support port numbers (such as
|
|
<acronym>TCP</acronym> and UDP). It is mandatory that you
|
|
code the port number of the service you want to match
|
|
on. Service names (from
|
|
<filename>/etc/services</filename>) may be used instead of
|
|
numeric port values.</para>
|
|
|
|
<para><parameter>in | out</parameter></para>
|
|
|
|
<para>Matches incoming or outgoing packets, respectively.
|
|
The in and out are keywords and it is mandatory that you
|
|
code one or the other as part of your rule matching
|
|
criterion.</para>
|
|
|
|
<para><parameter>via IF</parameter></para>
|
|
|
|
<para>Matches packets going through the interface specified
|
|
by exact name. The <literal>via</literal> keyword causes
|
|
the interface to always be checked as part of the match
|
|
process.</para>
|
|
|
|
<para><parameter>setup</parameter></para>
|
|
|
|
<para>This is a mandatory keyword that identifies the session
|
|
start request for <acronym>TCP</acronym> packets.</para>
|
|
|
|
<para><parameter>keep-state</parameter></para>
|
|
|
|
<para>This is a mandatory> keyword. Upon a match, the
|
|
firewall will create a dynamic rule, whose default behavior
|
|
is to match bidirectional traffic between source and
|
|
destination IP/port using the same protocol.</para>
|
|
|
|
<para><parameter>limit {src-addr | src-port | dst-addr |
|
|
dst-port}</parameter></para>
|
|
|
|
<para>The firewall will only allow
|
|
<replaceable>N</replaceable> connections with the same set
|
|
of parameters as specified in the rule. One or more of
|
|
source and destination addresses and ports can be
|
|
specified. The 'limit' and 'keep-state' can not be used on
|
|
same rule. Limit provides the same stateful function as
|
|
'keep-state' plus its own functions.</para>
|
|
</sect4>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>Stateful Rule Option</title>
|
|
|
|
<indexterm>
|
|
<primary>IPFW</primary>
|
|
|
|
<secondary>stateful filtering</secondary>
|
|
</indexterm>
|
|
|
|
<!-- XXX: duplicated -->
|
|
|
|
<para>Stateful filtering treats traffic as a bi-directional
|
|
exchange of packets comprising a session conversation. It
|
|
has the interrogation abilities to determine if the session
|
|
conversation between the originating sender and the
|
|
destination are following the valid procedure of
|
|
bi-directional packet exchange. Any packets that do not
|
|
properly fit the session conversation template are
|
|
automatically rejected as impostors.</para>
|
|
|
|
<para>'check-state' is used to identify where in the IPFW rules
|
|
set the packet is to be tested against the dynamic rules
|
|
facility. On a match the packet exits the firewall to
|
|
continue on its way and a new rule is dynamic created for
|
|
the next anticipated packet being exchanged during this
|
|
bi-directional session conversation. On a no match the
|
|
packet advances to the next rule in the rule set for
|
|
testing.</para>
|
|
|
|
<para>The dynamic rules facility is vulnerable to resource
|
|
depletion from a SYN-flood attack which would open a huge
|
|
number of dynamic rules. To counter this attack, &os;
|
|
added another new option named limit. This
|
|
option is used to limit the number of simultaneous session
|
|
conversations by interrogating the rules source or
|
|
destinations fields as directed by the limit option and
|
|
using the packet's IP address found there, in a search of
|
|
the open dynamic rules counting the number of times this
|
|
rule and IP address combination occurred, if this count is
|
|
greater that the value specified on the limit option, the
|
|
packet is discarded.</para>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>Logging Firewall Messages</title>
|
|
|
|
<indexterm>
|
|
<primary>IPFW</primary>
|
|
|
|
<secondary>logging</secondary>
|
|
</indexterm>
|
|
|
|
<para>The benefits of logging are obvious: it provides the
|
|
ability to review after the fact the rules you activated
|
|
logging on which provides information like, what packets had
|
|
been dropped, what addresses they came from, where they were
|
|
going, giving you a significant edge in tracking down
|
|
attackers.</para>
|
|
|
|
<para>Even with the logging facility enabled, IPFW will not
|
|
generate any rule logging on it's own. The firewall
|
|
administrator decides what rules in the rule set he wants
|
|
to log and adds the log verb to those rules. Normally only
|
|
deny rules are logged, like the deny rule for incoming
|
|
<acronym>ICMP</acronym> pings. It is very customary to
|
|
duplicate the ipfw default deny everything rule with the
|
|
log verb included as your last rule in the rule set. This
|
|
way you get to see all the packets that did not match any
|
|
of the rules in the rule set.</para>
|
|
|
|
<para>Logging is a two edged sword, if you are not careful, you
|
|
can lose yourself in the over abundance of log data and fill
|
|
your disk up with growing log files. DoS attacks that fill
|
|
up disk drives is one of the oldest attacks around. These
|
|
log message are not only written to syslogd, but also are
|
|
displayed on the root console screen and soon become very
|
|
annoying.</para>
|
|
|
|
<para>The <literal>IPFIREWALL_VERBOSE_LIMIT=5</literal>
|
|
kernel option limits the number of consecutive messages
|
|
sent to the system logger syslogd, concerning the packet
|
|
matching of a given rule. When this option is enabled in
|
|
the kernel, the number of consecutive messages concerning
|
|
a particular rule is capped at the number specified. There
|
|
is nothing to be gained from 200 log messages saying the
|
|
same identical thing. For instance, five consecutive
|
|
messages concerning a particular rule would be logged to
|
|
syslogd, the remainder identical consecutive messages would
|
|
be counted and posted to the syslogd with a phrase like
|
|
this:</para>
|
|
|
|
<programlisting>last message repeated 45 times</programlisting>
|
|
|
|
<para>All logged packets messages are written by default to
|
|
<filename>/var/log/security</filename> file, which is defined
|
|
in the <filename>/etc/syslog.conf</filename> file.</para>
|
|
</sect3>
|
|
|
|
<sect3 id="firewalls-ipfw-rules-script">
|
|
<title>Building a Rule Script</title>
|
|
|
|
<para>Most experienced IPFW users create a file containing the
|
|
rules and code them in a manner compatible with running them
|
|
as a script. The major benefit of doing this is the firewall
|
|
rules can be refreshed in mass without the need of rebooting
|
|
the system to activate the new rules. This method is very
|
|
convenient in testing new rules as the procedure can be
|
|
executed as many times as needed. Being a script, you can
|
|
use symbolic substitution to code frequent used values and
|
|
substitution them in multiple rules. You will see this in
|
|
the following example.</para>
|
|
|
|
<para>The script syntax used here is compatible with the 'sh',
|
|
'csh', 'tcsh' shells. Symbolic substitution fields are
|
|
prefixed with a dollar sign $. Symbolic fields do not
|
|
have the $ prefix. The value to populate the Symbolic
|
|
field must be enclosed to "double quotes".</para>
|
|
|
|
<para>Start your rules file like this:</para>
|
|
|
|
<programlisting>############### start of example ipfw rules script #############
|
|
#
|
|
ipfw -q -f flush # Delete all rules
|
|
# Set defaults
|
|
oif="tun0" # out interface
|
|
odns="192.0.2.11" # ISP's DNS server IP address
|
|
cmd="ipfw -q add " # build rule prefix
|
|
ks="keep-state" # just too lazy to key this each time
|
|
$cmd 00500 check-state
|
|
$cmd 00502 deny all from any to any frag
|
|
$cmd 00501 deny tcp from any to any established
|
|
$cmd 00600 allow tcp from any to any 80 out via $oif setup $ks
|
|
$cmd 00610 allow tcp from any to $odns 53 out via $oif setup $ks
|
|
$cmd 00611 allow udp from any to $odns 53 out via $oif $ks
|
|
################### End of example ipfw rules script ############</programlisting>
|
|
|
|
<para>That is all there is to it. The rules are not important
|
|
in this example, how the Symbolic substitution field are
|
|
populated and used are.</para>
|
|
|
|
<para>If the above example was in
|
|
<filename>/etc/ipfw.rules</filename> file, you could reload
|
|
these rules by entering on the command line.</para>
|
|
|
|
<screen>&prompt.root; <userinput>sh /etc/ipfw.rules</userinput></screen>
|
|
|
|
<para>The <filename>/etc/ipfw.rules</filename> file could be
|
|
located anywhere you want and the file could be named any
|
|
thing you would like.</para>
|
|
|
|
<para>The same thing could also be accomplished by running
|
|
these commands by hand:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ipfw -q -f flush</userinput>
|
|
&prompt.root; <userinput>ipfw -q add check-state</userinput>
|
|
&prompt.root; <userinput>ipfw -q add deny all from any to any frag</userinput>
|
|
&prompt.root; <userinput>ipfw -q add deny tcp from any to any established</userinput>
|
|
&prompt.root; <userinput>ipfw -q add allow tcp from any to any 80 out via tun0 setup keep-state</userinput>
|
|
&prompt.root; <userinput>ipfw -q add allow tcp from any to 192.0.2.11 53 out via tun0 setup keep-state</userinput>
|
|
&prompt.root; <userinput>ipfw -q add 00611 allow udp from any to 192.0.2.11 53 out via tun0 keep-state</userinput></screen>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>Stateful Ruleset</title>
|
|
|
|
<para>The following non-<acronym>NAT</acronym>ed rule set is an
|
|
example of how to code a very secure 'inclusive' type of
|
|
firewall. An inclusive firewall only allows services
|
|
matching pass rules through and blocks all other by default.
|
|
All firewalls have at the minimum two interfaces which have
|
|
to have rules to allow the firewall to function.</para>
|
|
|
|
<para>All &unix; flavored operating systems, &os; included, are
|
|
designed to use interface <devicename>lo0</devicename> and IP
|
|
address <hostid role="ipaddr">127.0.0.1</hostid> for internal
|
|
communication with in the operating system. The firewall
|
|
rules must contain rules to allow free unmolested movement of
|
|
these special internally used packets.</para>
|
|
|
|
<para>The interface which faces the public Internet, is the one
|
|
which you code your rules to authorize and control access out
|
|
to the public Internet and access requests arriving from the
|
|
public Internet. This can be your ppp
|
|
<devicename>tun0</devicename> interface or your NIC that is
|
|
connected to your DSL or cable modem.</para>
|
|
|
|
<para>In cases where one or more than one NIC are connected to
|
|
a private LANs behind the firewall, those interfaces must
|
|
have rules coded to allow free unmolested movement of
|
|
packets originating from those LAN interfaces.</para>
|
|
|
|
<para>The rules should be first organized into three major
|
|
sections, all the free unmolested interfaces, public
|
|
interface outbound, and the public interface inbound.</para>
|
|
|
|
<para>The order of the rules in each of the public interface
|
|
sections should be in order of the most used rules being
|
|
placed before less often used rules with the last rule in
|
|
the section being a block log all packets on that interface
|
|
and direction.</para>
|
|
|
|
<para>The Outbound section in the following rule set only
|
|
contains 'allow' rules which contain selection values that
|
|
uniquely identify the service that is authorized for public
|
|
Internet access. All the rules have the, proto, port,
|
|
in/out, via and keep state option coded. The 'proto tcp'
|
|
rules have the 'setup' option included to identify the start
|
|
session request as the trigger packet to be posted to the
|
|
keep state stateful table.</para>
|
|
|
|
<para>The Inbound section has all the blocking of undesirable
|
|
packets first for two different reasons. First is these
|
|
things being blocked may be part of an otherwise valid packet
|
|
which may be allowed in by the later authorized service
|
|
rules. Second reason is that by having a rule that
|
|
explicitly blocks selected packets that I receive on an
|
|
infrequent bases and do not want to see in the log, this
|
|
keeps them from being caught by the last rule in the section
|
|
which blocks and logs all packets which have fallen through
|
|
the rules. The last rule in the section which blocks and
|
|
logs all packets is how you create the legal evidence needed
|
|
to prosecute the people who are attacking your system.</para>
|
|
|
|
<para>Another thing you should take note of, is there is no
|
|
response returned for any of the undesirable stuff, their
|
|
packets just get dropped and vanish. This way the attackers
|
|
has no knowledge if his packets have reached your system.
|
|
The less the attackers can learn about your system the more
|
|
secure it is. When you log packets with port numbers you do
|
|
not recognize, look the numbers up in
|
|
<filename>/etc/services/</filename> or go to <ulink
|
|
url="http://www.securitystats.com/tools/portsearch.php"></ulink>
|
|
and do a port number lookup to find what the purpose of that
|
|
port number is. Check out this link for port numbers used by
|
|
Trojans: <ulink
|
|
url="http://www.simovits.com/trojans/trojans.html"></ulink>.</para>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>An Example Inclusive Ruleset</title>
|
|
|
|
<para>The following non-<acronym>NAT</acronym>ed rule set is a
|
|
complete inclusive type ruleset. You can not go wrong using
|
|
this rule set for you own. Just comment out any pass rules
|
|
for services you do not want. If you see messages in your
|
|
log that you want to stop seeing just add a deny rule in the
|
|
inbound section. You have to change the 'dc0' interface name
|
|
in every rule to the interface name of the NIC that connects
|
|
your system to the public Internet. For user ppp it would be
|
|
'tun0'.</para>
|
|
|
|
<para>You will see a pattern in the usage of these
|
|
rules.</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>All statements that are a request to start a session
|
|
to the public Internet use keep-state.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>All the authorized services that originate from the
|
|
public Internet have the limit option to stop
|
|
flooding.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>All rules use in or out to clarify direction.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>All rules use via interface name to specify the
|
|
interface the packet is traveling over.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>The following rules go into
|
|
<filename>/etc/ipfw.rules</filename>.</para>
|
|
|
|
<programlisting>################ Start of IPFW rules file ###############################
|
|
# Flush out the list before we begin.
|
|
ipfw -q -f flush
|
|
|
|
# Set rules command prefix
|
|
cmd="ipfw -q add"
|
|
pif="dc0" # public interface name of NIC
|
|
# facing the public Internet
|
|
|
|
#################################################################
|
|
# No restrictions on Inside LAN Interface for private network
|
|
# Not needed unless you have LAN.
|
|
# Change xl0 to your LAN NIC interface name
|
|
#################################################################
|
|
#$cmd 00005 allow all from any to any via xl0
|
|
|
|
#################################################################
|
|
# No restrictions on Loopback Interface
|
|
#################################################################
|
|
$cmd 00010 allow all from any to any via lo0
|
|
|
|
#################################################################
|
|
# Allow the packet through if it has previous been added to the
|
|
# the "dynamic" rules table by a allow keep-state statement.
|
|
#################################################################
|
|
$cmd 00015 check-state
|
|
|
|
#################################################################
|
|
# Interface facing Public Internet (Outbound Section)
|
|
# Interrogate session start requests originating from behind the
|
|
# firewall on the private network or from this gateway server
|
|
# destine for the public Internet.
|
|
#################################################################
|
|
|
|
# Allow out access to my ISP's Domain name server.
|
|
# x.x.x.x must be the IP address of your ISP.s DNS
|
|
# Dup these lines if your ISP has more than one DNS server
|
|
# Get the IP addresses from /etc/resolv.conf file
|
|
$cmd 00110 allow tcp from any to x.x.x.x 53 out via $pif setup keep-state
|
|
$cmd 00111 allow udp from any to x.x.x.x 53 out via $pif keep-state
|
|
|
|
# Allow out access to my ISP's DHCP server for cable/DSL configurations.
|
|
# This rule is not needed for .user ppp. connection to the public Internet.
|
|
# so you can delete this whole group.
|
|
# Use the following rule and check log for IP address.
|
|
# Then put IP address in commented out rule & delete first rule
|
|
$cmd 00120 allow log udp from any to any 67 out via $pif keep-state
|
|
#$cmd 00120 allow udp from any to x.x.x.x 67 out via $pif keep-state
|
|
|
|
# Allow out non-secure standard www function
|
|
$cmd 00200 allow tcp from any to any 80 out via $pif setup keep-state
|
|
|
|
# Allow out secure www function https over TLS SSL
|
|
$cmd 00220 allow tcp from any to any 443 out via $pif setup keep-state
|
|
|
|
# Allow out send & get email function
|
|
$cmd 00230 allow tcp from any to any 25 out via $pif setup keep-state
|
|
$cmd 00231 allow tcp from any to any 110 out via $pif setup keep-state
|
|
|
|
# Allow out FBSD (make install & CVSUP) functions
|
|
# Basically give user root "GOD" privileges.
|
|
$cmd 00240 allow tcp from me to any out via $pif setup keep-state uid root
|
|
|
|
# Allow out ping
|
|
$cmd 00250 allow icmp from any to any out via $pif keep-state
|
|
|
|
# Allow out Time
|
|
$cmd 00260 allow tcp from any to any 37 out via $pif setup keep-state
|
|
|
|
# Allow out nntp news (i.e. news groups)
|
|
$cmd 00270 allow tcp from any to any 119 out via $pif setup keep-state
|
|
|
|
# Allow out secure FTP, Telnet, and SCP
|
|
# This function is using SSH (secure shell)
|
|
$cmd 00280 allow tcp from any to any 22 out via $pif setup keep-state
|
|
|
|
# Allow out whois
|
|
$cmd 00290 allow tcp from any to any 43 out via $pif setup keep-state
|
|
|
|
# deny and log everything else that.s trying to get out.
|
|
# This rule enforces the block all by default logic.
|
|
$cmd 00299 deny log all from any to any out via $pif
|
|
|
|
#################################################################
|
|
# Interface facing Public Internet (Inbound Section)
|
|
# Interrogate packets originating from the public Internet
|
|
# destine for this gateway server or the private network.
|
|
#################################################################
|
|
|
|
# Deny all inbound traffic from non-routable reserved address spaces
|
|
$cmd 00300 deny all from 192.168.0.0/16 to any in via $pif #RFC 1918 private IP
|
|
$cmd 00301 deny all from 172.16.0.0/12 to any in via $pif #RFC 1918 private IP
|
|
$cmd 00302 deny all from 10.0.0.0/8 to any in via $pif #RFC 1918 private IP
|
|
$cmd 00303 deny all from 127.0.0.0/8 to any in via $pif #loopback
|
|
$cmd 00304 deny all from 0.0.0.0/8 to any in via $pif #loopback
|
|
$cmd 00305 deny all from 169.254.0.0/16 to any in via $pif #DHCP auto-config
|
|
$cmd 00306 deny all from 192.0.2.0/24 to any in via $pif #reserved for docs
|
|
$cmd 00307 deny all from 204.152.64.0/23 to any in via $pif #Sun cluster interconnect
|
|
$cmd 00308 deny all from 224.0.0.0/3 to any in via $pif #Class D & E multicast
|
|
|
|
# Deny public pings
|
|
$cmd 00310 deny icmp from any to any in via $pif
|
|
|
|
# Deny ident
|
|
$cmd 00315 deny tcp from any to any 113 in via $pif
|
|
|
|
# Deny all Netbios service. 137=name, 138=datagram, 139=session
|
|
# Netbios is MS/Windows sharing services.
|
|
# Block MS/Windows hosts2 name server requests 81
|
|
$cmd 00320 deny tcp from any to any 137 in via $pif
|
|
$cmd 00321 deny tcp from any to any 138 in via $pif
|
|
$cmd 00322 deny tcp from any to any 139 in via $pif
|
|
$cmd 00323 deny tcp from any to any 81 in via $pif
|
|
|
|
# Deny any late arriving packets
|
|
$cmd 00330 deny all from any to any frag in via $pif
|
|
|
|
# Deny ACK packets that did not match the dynamic rule table
|
|
$cmd 00332 deny tcp from any to any established in via $pif
|
|
|
|
# Allow traffic in from ISP's DHCP server. This rule must contain
|
|
# the IP address of your ISP.s DHCP server as it.s the only
|
|
# authorized source to send this packet type.
|
|
# Only necessary for cable or DSL configurations.
|
|
# This rule is not needed for .user ppp. type connection to
|
|
# the public Internet. This is the same IP address you captured
|
|
# and used in the outbound section.
|
|
#$cmd 00360 allow udp from any to x.x.x.x 67 in via $pif keep-state
|
|
|
|
# Allow in standard www function because I have apache server
|
|
$cmd 00400 allow tcp from any to me 80 in via $pif setup limit src-addr 2
|
|
|
|
# Allow in secure FTP, Telnet, and SCP from public Internet
|
|
$cmd 00410 allow tcp from any to me 22 in via $pif setup limit src-addr 2
|
|
|
|
# Allow in non-secure Telnet session from public Internet
|
|
# labeled non-secure because ID & PW are passed over public
|
|
# Internet as clear text.
|
|
# Delete this sample group if you do not have telnet server enabled.
|
|
$cmd 00420 allow tcp from any to me 23 in via $pif setup limit src-addr 2
|
|
|
|
# Reject & Log all incoming connections from the outside
|
|
$cmd 00499 deny log all from any to any in via $pif
|
|
|
|
# Everything else is denied by default
|
|
# deny and log all packets that fell through to see what they are
|
|
$cmd 00999 deny log all from any to any
|
|
################ End of IPFW rules file ###############################</programlisting>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>An Example <acronym>NAT</acronym> and Stateful
|
|
Ruleset</title>
|
|
|
|
<indexterm>
|
|
<primary>NAT</primary>
|
|
|
|
<secondary>and IPFW</secondary>
|
|
</indexterm>
|
|
|
|
<para>There are some additional configuration statements that
|
|
need to be enabled to activate the <acronym>NAT</acronym>
|
|
function of IPFW. The kernel source needs 'option divert'
|
|
statement added to the other IPFIREWALL statements compiled
|
|
into a custom kernel.</para>
|
|
|
|
<para>In addition to the normal IPFW options in
|
|
<filename>/etc/rc.conf</filename>, the following are
|
|
needed.</para>
|
|
|
|
<programlisting>natd_enable="YES" # Enable <acronym>NAT</acronym>D function
|
|
natd_interface="rl0" # interface name of public Internet NIC
|
|
natd_flags="-dynamic -m" # -m = preserve port numbers if possible</programlisting>
|
|
|
|
<para>Utilizing stateful rules with divert natd rule (Network
|
|
Address Translation) greatly complicates the rule set coding
|
|
logic. The positioning of the check-state, and 'divert natd'
|
|
rules in the rule set becomes very critical. This is no
|
|
longer a simple fall-through logic flow. A new action type
|
|
is used, called 'skipto'. To use the skipto command it is
|
|
mandatory that you number each rule so you know exactly
|
|
where the skipto rule number is you are really jumping
|
|
to.</para>
|
|
|
|
<para>The following is an uncommented example of one coding
|
|
method, selected here to explain the sequence of the packet
|
|
flow through the rule sets.</para>
|
|
|
|
<para>The processing flow starts with the first rule from the
|
|
top of the rule file and progress one rule at a time deeper
|
|
into the file until the end is reach or the packet being
|
|
tested to the selection criteria matches and the packet is
|
|
released out of the firewall. It is important to take notice
|
|
of the location of rule numbers 100 101, 450, 500, and 510.
|
|
These rules control the translation of the outbound and
|
|
inbound packets so their entries in the keep-state dynamic
|
|
table always register the private LAN IP address. Next
|
|
notice that all the allow and deny rules specified the
|
|
direction the packet is going (IE outbound or inbound) and
|
|
the interface. Also notice that all the start outbound
|
|
session requests all skipto rule 500 for the network address
|
|
translation.</para>
|
|
|
|
<para>Lets say a LAN user uses their web browser to get a web
|
|
page. Web pages use port 80 to communicate over. So the
|
|
packet enters the firewall, It does not match 100 because it
|
|
is headed out not in. It passes rule 101 because this is the
|
|
first packet so it has not been posted to the keep-state
|
|
dynamic table yet. The packet finally comes to rule 125 a
|
|
matches. It is outbound through the NIC facing the public
|
|
Internet. The packet still has it's source IP address as a
|
|
private LAN IP address. On the match to this rule, two
|
|
actions take place. The keep-state option will post this
|
|
rule into the keep-state dynamic rules table and the
|
|
specified action is executed. The action is part of the info
|
|
posted to the dynamic table. In this case it is "skipto rule
|
|
500". Rule 500 <acronym>NAT</acronym>s the packet IP address
|
|
and out it goes. Remember this, this is very important.
|
|
This packet makes its way to the destination and returns and
|
|
enters the top of the rule set. This time it does match rule
|
|
100 and has it destination IP address mapped back to its
|
|
corresponding LAN IP address. It then is processed by the
|
|
check-state rule, it's found in the table as an existing
|
|
session conversation and released to the LAN. It goes to the
|
|
LAN PC that sent it and a new packet is sent requesting
|
|
another segment of the data from the remote server. This
|
|
time it gets checked by the check-state rule and its outbound
|
|
entry is found, the associated action, 'skipto 500', is
|
|
executed. The packet jumps to rule 500 gets
|
|
<acronym>NAT</acronym>ed and released on it's way out.</para>
|
|
|
|
<para>On the inbound side, everything coming in that is part
|
|
of an existing session conversation is being automatically
|
|
handled by the check-state rule and the properly placed
|
|
divert natd rules. All we have to address is denying all the
|
|
bad packets and only allowing in the authorized services.
|
|
Lets say there is a apache server running on the firewall box
|
|
and we want people on the public Internet to be able to
|
|
access the local web site. The new inbound start request
|
|
packet matches rule 100 and its IP address is mapped to LAN
|
|
IP for the firewall box. The packet is them matched against
|
|
all the nasty things we want to check for and finally matches
|
|
against rule 425. On a match two things occur. The packet
|
|
rule is posted to the keep-state dynamic table but this time
|
|
any new session requests originating from that source IP
|
|
address is limited to 2. This defends against DoS attacks of
|
|
service running on the specified port number. The action is
|
|
allow so the packet is released to the LAN. On return the
|
|
check-state rule recognizes the packet as belonging to an
|
|
existing session conversation sends it to rule 500 for
|
|
<acronym>NAT</acronym>ing and released to outbound
|
|
interface.</para>
|
|
|
|
<para>Example Ruleset #1:</para>
|
|
|
|
<programlisting>#!/bin/sh
|
|
cmd="ipfw -q add"
|
|
skip="skipto 500"
|
|
pif=rl0
|
|
ks="keep-state"
|
|
good_tcpo="22,25,37,43,53,80,443,110,119"
|
|
|
|
ipfw -q -f flush
|
|
|
|
$cmd 002 allow all from any to any via xl0 # exclude LAN traffic
|
|
$cmd 003 allow all from any to any via lo0 # exclude loopback traffic
|
|
|
|
$cmd 100 divert natd ip from any to any in via $pif
|
|
$cmd 101 check-state
|
|
|
|
# Authorized outbound packets
|
|
$cmd 120 $skip udp from any to xx.168.240.2 53 out via $pif $ks
|
|
$cmd 121 $skip udp from any to xx.168.240.5 53 out via $pif $ks
|
|
$cmd 125 $skip tcp from any to any $good_tcpo out via $pif setup $ks
|
|
$cmd 130 $skip icmp from any to any out via $pif $ks
|
|
$cmd 135 $skip udp from any to any 123 out via $pif $ks
|
|
|
|
|
|
# Deny all inbound traffic from non-routable reserved address spaces
|
|
$cmd 300 deny all from 192.168.0.0/16 to any in via $pif #RFC 1918 private IP
|
|
$cmd 301 deny all from 172.16.0.0/12 to any in via $pif #RFC 1918 private IP
|
|
$cmd 302 deny all from 10.0.0.0/8 to any in via $pif #RFC 1918 private IP
|
|
$cmd 303 deny all from 127.0.0.0/8 to any in via $pif #loopback
|
|
$cmd 304 deny all from 0.0.0.0/8 to any in via $pif #loopback
|
|
$cmd 305 deny all from 169.254.0.0/16 to any in via $pif #DHCP auto-config
|
|
$cmd 306 deny all from 192.0.2.0/24 to any in via $pif #reserved for docs
|
|
$cmd 307 deny all from 204.152.64.0/23 to any in via $pif #Sun cluster
|
|
$cmd 308 deny all from 224.0.0.0/3 to any in via $pif #Class D & E multicast
|
|
|
|
# Authorized inbound packets
|
|
$cmd 400 allow udp from xx.70.207.54 to any 68 in $ks
|
|
$cmd 420 allow tcp from any to me 80 in via $pif setup limit src-addr 1
|
|
|
|
|
|
$cmd 450 deny log ip from any to any
|
|
|
|
# This is skipto location for outbound stateful rules
|
|
$cmd 500 divert natd ip from any to any out via $pif
|
|
$cmd 510 allow ip from any to any
|
|
|
|
######################## end of rules ##################</programlisting>
|
|
|
|
<para>The following is pretty much the same as above, but uses
|
|
a self documenting coding style full of description comments
|
|
to help the inexperienced IPFW rule writer to better
|
|
understand what the rules are doing.</para>
|
|
|
|
<para>Example Ruleset #2:</para>
|
|
|
|
<programlisting>#!/bin/sh
|
|
################ Start of IPFW rules file ###############################
|
|
# Flush out the list before we begin.
|
|
ipfw -q -f flush
|
|
|
|
# Set rules command prefix
|
|
cmd="ipfw -q add"
|
|
skip="skipto 800"
|
|
pif="rl0" # public interface name of NIC
|
|
# facing the public Internet
|
|
|
|
#################################################################
|
|
# No restrictions on Inside LAN Interface for private network
|
|
# Change xl0 to your LAN NIC interface name
|
|
#################################################################
|
|
$cmd 005 allow all from any to any via xl0
|
|
|
|
#################################################################
|
|
# No restrictions on Loopback Interface
|
|
#################################################################
|
|
$cmd 010 allow all from any to any via lo0
|
|
|
|
#################################################################
|
|
# check if packet is inbound and nat address if it is
|
|
#################################################################
|
|
$cmd 014 divert natd ip from any to any in via $pif
|
|
|
|
#################################################################
|
|
# Allow the packet through if it has previous been added to the
|
|
# the "dynamic" rules table by a allow keep-state statement.
|
|
#################################################################
|
|
$cmd 015 check-state
|
|
|
|
#################################################################
|
|
# Interface facing Public Internet (Outbound Section)
|
|
# Interrogate session start requests originating from behind the
|
|
# firewall on the private network or from this gateway server
|
|
# destine for the public Internet.
|
|
#################################################################
|
|
|
|
# Allow out access to my ISP's Domain name server.
|
|
# x.x.x.x must be the IP address of your ISP's DNS
|
|
# Dup these lines if your ISP has more than one DNS server
|
|
# Get the IP addresses from /etc/resolv.conf file
|
|
$cmd 020 $skip tcp from any to x.x.x.x 53 out via $pif setup keep-state
|
|
|
|
|
|
# Allow out access to my ISP's DHCP server for cable/DSL configurations.
|
|
$cmd 030 $skip udp from any to x.x.x.x 67 out via $pif keep-state
|
|
|
|
# Allow out non-secure standard www function
|
|
$cmd 040 $skip tcp from any to any 80 out via $pif setup keep-state
|
|
|
|
# Allow out secure www function https over TLS SSL
|
|
$cmd 050 $skip tcp from any to any 443 out via $pif setup keep-state
|
|
|
|
# Allow out send & get email function
|
|
$cmd 060 $skip tcp from any to any 25 out via $pif setup keep-state
|
|
$cmd 061 $skip tcp from any to any 110 out via $pif setup keep-state
|
|
|
|
# Allow out FreeBSD (make install & CVSUP) functions
|
|
# Basically give user root "GOD" privileges.
|
|
$cmd 070 $skip tcp from me to any out via $pif setup keep-state uid root
|
|
|
|
# Allow out ping
|
|
$cmd 080 $skip icmp from any to any out via $pif keep-state
|
|
|
|
# Allow out Time
|
|
$cmd 090 $skip tcp from any to any 37 out via $pif setup keep-state
|
|
|
|
# Allow out nntp news (i.e. news groups)
|
|
$cmd 100 $skip tcp from any to any 119 out via $pif setup keep-state
|
|
|
|
# Allow out secure FTP, Telnet, and SCP
|
|
# This function is using SSH (secure shell)
|
|
$cmd 110 $skip tcp from any to any 22 out via $pif setup keep-state
|
|
|
|
# Allow out whois
|
|
$cmd 120 $skip tcp from any to any 43 out via $pif setup keep-state
|
|
|
|
# Allow ntp time server
|
|
$cmd 130 $skip udp from any to any 123 out via $pif keep-state
|
|
|
|
#################################################################
|
|
# Interface facing Public Internet (Inbound Section)
|
|
# Interrogate packets originating from the public Internet
|
|
# destine for this gateway server or the private network.
|
|
#################################################################
|
|
|
|
# Deny all inbound traffic from non-routable reserved address spaces
|
|
$cmd 300 deny all from 192.168.0.0/16 to any in via $pif #RFC 1918 private IP
|
|
$cmd 301 deny all from 172.16.0.0/12 to any in via $pif #RFC 1918 private IP
|
|
$cmd 302 deny all from 10.0.0.0/8 to any in via $pif #RFC 1918 private IP
|
|
$cmd 303 deny all from 127.0.0.0/8 to any in via $pif #loopback
|
|
$cmd 304 deny all from 0.0.0.0/8 to any in via $pif #loopback
|
|
$cmd 305 deny all from 169.254.0.0/16 to any in via $pif #DHCP auto-config
|
|
$cmd 306 deny all from 192.0.2.0/24 to any in via $pif #reserved for docs
|
|
$cmd 307 deny all from 204.152.64.0/23 to any in via $pif #Sun cluster
|
|
$cmd 308 deny all from 224.0.0.0/3 to any in via $pif #Class D & E multicast
|
|
|
|
# Deny ident
|
|
$cmd 315 deny tcp from any to any 113 in via $pif
|
|
|
|
# Deny all Netbios service. 137=name, 138=datagram, 139=session
|
|
# Netbios is MS/Windows sharing services.
|
|
# Block MS/Windows hosts2 name server requests 81
|
|
$cmd 320 deny tcp from any to any 137 in via $pif
|
|
$cmd 321 deny tcp from any to any 138 in via $pif
|
|
$cmd 322 deny tcp from any to any 139 in via $pif
|
|
$cmd 323 deny tcp from any to any 81 in via $pif
|
|
|
|
# Deny any late arriving packets
|
|
$cmd 330 deny all from any to any frag in via $pif
|
|
|
|
# Deny ACK packets that did not match the dynamic rule table
|
|
$cmd 332 deny tcp from any to any established in via $pif
|
|
|
|
# Allow traffic in from ISP's DHCP server. This rule must contain
|
|
# the IP address of your ISP's DHCP server as it's the only
|
|
# authorized source to send this packet type.
|
|
# Only necessary for cable or DSL configurations.
|
|
# This rule is not needed for 'user ppp' type connection to
|
|
# the public Internet. This is the same IP address you captured
|
|
# and used in the outbound section.
|
|
$cmd 360 allow udp from x.x.x.x to any 68 in via $pif keep-state
|
|
|
|
# Allow in standard www function because I have Apache server
|
|
$cmd 370 allow tcp from any to me 80 in via $pif setup limit src-addr 2
|
|
|
|
# Allow in secure FTP, Telnet, and SCP from public Internet
|
|
$cmd 380 allow tcp from any to me 22 in via $pif setup limit src-addr 2
|
|
|
|
# Allow in non-secure Telnet session from public Internet
|
|
# labeled non-secure because ID & PW are passed over public
|
|
# Internet as clear text.
|
|
# Delete this sample group if you do not have telnet server enabled.
|
|
$cmd 390 allow tcp from any to me 23 in via $pif setup limit src-addr 2
|
|
|
|
# Reject & Log all unauthorized incoming connections from the public Internet
|
|
$cmd 400 deny log all from any to any in via $pif
|
|
|
|
# Reject & Log all unauthorized out going connections to the public Internet
|
|
$cmd 450 deny log all from any to any out via $pif
|
|
|
|
# This is skipto location for outbound stateful rules
|
|
$cmd 800 divert natd ip from any to any out via $pif
|
|
$cmd 801 allow ip from any to any
|
|
|
|
# Everything else is denied by default
|
|
# deny and log all packets that fell through to see what they are
|
|
$cmd 999 deny log all from any to any
|
|
################ End of IPFW rules file ###############################</programlisting>
|
|
</sect3>
|
|
</sect2>
|
|
</sect1>
|
|
</chapter>
|