doc/en/handbook/security/chapter.sgml
Nik Clayton 7321b94099 Suddenly realised none of the
<informalexample>
    <screen>
      ...
    </screen>
  </informalexample>

need the <informalexample> element. So remove it. Simple search and
replace does the trick.
1999-01-30 23:35:05 +00:00

1711 lines
66 KiB
Text

<chapter id="security">
<title>Security</title>
<sect1 id="crypt">
<title>DES, MD5, and Crypt</title>
<para><emphasis>Contributed by &a.wollman;<!-- <br> -->24 September
1995.</emphasis></para>
<para>In order to protect the security of passwords on UN*X systems
from being easily exposed, passwords have traditionally been
scrambled in some way. Starting with Bell Labs' Seventh Edition
Unix, passwords were encrypted using what the security people call a
&ldquo;one-way hash function&rdquo;. That is to say, the password is
transformed in such a way that the original password cannot be
regained except by brute-force searching the space of possible
passwords. Unfortunately, the only secure method that was available
to the AT&amp;T researchers at the time was based on DES, the Data
Encryption Standard. This causes only minimal difficulty for
commercial vendors, but is a serious problem for an operating system
like FreeBSD where all the source code is freely available, because
national governments in many places like to place restrictions on
cross-border transport of DES and other encryption software.</para>
<para>So, the FreeBSD team was faced with a dilemma: how could we
provide compatibility with all those UNIX systems out there while
still not running afoul of the law? We decided to take a dual-track
approach: we would make distributions which contained only a
non-regulated password scrambler, and then provide as a separate
add-on library the DES-based password hash. The password-scrambling
function was moved out of the C library to a separate library,
called <filename>libcrypt</filename> because the name of
the C function to implement it is <function>crypt</function>. In FreeBSD 1.x and some pre-release
2.0 snapshots, the non-regulated scrambler uses an insecure function
written by Nate Williams; in subsequent releases this was replaced
by a mechanism using the RSA Data Security, Inc., MD5 one-way hash
function. Because neither of these functions involve encryption,
they are believed to be exportable from the US and importable into
many other countries.</para>
<para>Meanwhile, work was also underway on the DES-based password hash
function. First, a version of the <function>crypt</function> function which was written outside the
US was imported, thus synchronizing the US and non-US code. Then,
the library was modified and split into two; the DES <filename>libcrypt</filename> contains only the code involved in
performing the one-way password hash, and a separate <filename>libcipher</filename> was created with the entry points
to actually perform encryption. The code was partitioned in this
way to make it easier to get an export license for the compiled
library.</para>
<sect2>
<title>Recognizing your <command>crypt</command>
mechanism</title>
<para>It is fairly easy to recognize whether a particular password
string was created using the DES- or MD5-based hash function. MD5
password strings always begin with the characters <literal>&#36;1&#36;</literal>. DES password strings do not
have any particular identifying characteristics, but they are
shorter than MD5 passwords, and are coded in a 64-character
alphabet which does not include the <literal>&#36;</literal> character, so a relatively short
string which doesn't begin with a dollar sign is very likely a DES
password.</para>
<para>Determining which library is being used on your system is
fairly easy for most programs, except for those like <command>init</command> which are statically linked. (For
those programs, the only way is to try them on a known password
and see if it works.) Programs which use <function>crypt</function> are linked against <filename>libcrypt</filename>, which for each type of library is
a symbolic link to the appropriate implementation. For example,
on a system using the DES versions:</para>
<screen>&prompt.user;<userinput> cd /usr/lib</userinput>
&prompt.user; <userinput>ls -l /usr/lib/libcrypt*</userinput>
lrwxr-xr-x 1 bin bin 13 Sep 5 12:50 libcrypt.a -&gt; libdescrypt.a
lrwxr-xr-x 1 bin bin 18 Sep 5 12:50 libcrypt.so.2.0 -&gt; libdescrypt.so.2.0
lrwxr-xr-x 1 bin bin 15 Sep 5 12:50 libcrypt_p.a -&gt; libdescrypt_p.a</screen>
<para>On a system using the MD5-based libraries, the same links will
be present, but the target will be <filename>libscrypt</filename>
rather than <filename>libdescrypt</filename>.</para>
</sect2>
</sect1>
<sect1 id="skey">
<title>S/Key</title>
<para><emphasis>Contributed by &a.wollman;<!-- <br> -->25 September
1995.</emphasis></para>
<para>S/Key is a one-time password scheme based on a one-way hash
function (in our version, this is MD4 for compatibility; other
versions have used MD5 and DES-MAC). S/Key has been a standard part
of all FreeBSD distributions since version 1.1.5, and is also
implemented on a large and growing number of other systems. S/Key
is a registered trademark of Bell Communications Research,
Inc.</para>
<para>There are three different sorts of passwords which we will talk
about in the discussion below. The first is your usual UNIX-style
or Kerberos password; we will call this a &ldquo;UNIX password&rdquo;. The
second sort is the one-time password which is generated by the S/Key
<command>key</command> program and accepted by the
<command>keyinit</command> program and the login
prompt; we will call this a &ldquo;one-time password&rdquo;. The final sort
of password is the secret password which you give to the <command>key</command> program (and sometimes the <command>keyinit</command> program) which it uses to generate
one-time passwords; we will call it a &ldquo;secret password&rdquo; or just
unqualified &ldquo;password&rdquo;.</para>
<para>The secret password does not necessarily have anything to do
with your UNIX password (while they can be the same, this is not
recommended). While UNIX passwords are limited to eight characters
in length, your S/Key secret password can be as long as you like; I
use seven-word phrases. In general, the S/Key system operates
completely independently of the UNIX password system.</para>
<para>There are in addition two other sorts of data involved in the
S/Key system; one is called the &ldquo;seed&rdquo; or (confusingly) &ldquo;key&rdquo;,
and consists of two letters and five digits, and the other is the
&ldquo;iteration count&rdquo; and is a number between 100 and 1. S/Key
constructs a one-time password from these components by
concatenating the seed and the secret password, then applying a
one-way hash (the RSA Data Security, Inc., MD4 secure hash function)
iteration-count times, and turning the result into six short English
words. The <command>login</command> and <command>su</command> programs keep track of the last one-time
password used, and the user is authenticated if the hash of the
user-provided password is equal to the previous password. Because a
one-way hash function is used, it is not possible to generate future
one-time passwords having overheard one which was successfully used;
the iteration count is decremented after each successful login to
keep the user and login program in sync. (When you get the
iteration count down to 1, it is time to reinitialize S/Key.)</para>
<para>There are four programs involved in the S/Key system which we
will discuss below. The <command>key</command> program
accepts an iteration count, a seed, and a secret password, and
generates a one-time password. The <command>keyinit</command> program is used to initialized S/Key,
and to change passwords, iteration counts, or seeds; it takes either
a secret password, or an iteration count, seed, and one-time
password. The <command>keyinfo</command> program
examines the <filename>/etc/skeykeys</filename> file and prints out
the invoking user's current iteration count and seed. Finally, the
<command>login</command> and <command>su</command> programs contain the necessary logic to
accept S/Key one-time passwords for authentication. The <command>login</command> program is also capable of disallowing
the use of UNIX passwords on connections coming from specified
addresses.</para>
<para>There are four different sorts of operations we will cover. The
first is using the <command>keyinit</command> program
over a secure connection to set up S/Key for the first time, or to
change your password or seed. The second operation is using the
<command>keyinit</command> program over an insecure
connection, in conjunction with the <command>key</command> program over a secure connection, to do
the same. The third is using the <command>key</command> program to log in over an insecure
connection. The fourth is using the <command>key</command> program to generate a number of keys
which can be written down or printed out to carry with you when
going to some location without secure connections to anywhere (like
at a conference).</para>
<sect2>
<title>Secure connection initialization</title>
<para>To initialize S/Key, change your password, or change your seed
while logged in over a secure connection (e.g., on the console of
a machine), use the <command>keyinit</command>
command without any parameters while logged in as yourself:</para>
<screen>&prompt.user; keyinit
Updating wollman: ) these will not appear if you
Old key: ha73895 ) have not used S/Key before
Reminder - Only use this method if you are directly connected.
If you are using telnet or rlogin exit with no password and use keyinit -s.
<prompt>Enter secret password:</prompt> ) I typed my pass phrase here
<prompt>Again secret password:</prompt> ) I typed it again ID
wollman s/key is 99 ha73896 ) discussed below SAG
HAS FONT GOUT FATE BOOM )</screen>
<para>There is a lot of information here. At the<prompt>Enter secret
password:</prompt> prompt, you should enter some password or phrase (I use
phrases of minimum seven words) which will be needed to generate
login keys. The line starting `ID' gives the parameters of your
particular S/Key instance: your login name, the iteration count,
and seed. When logging in with S/Key, the system will remember
these parameters and present them back to you so you do not have
to remember them. The last line gives the particular one-time
password which corresponds to those parameters and your secret
password; if you were to re-login immediately, this one-time
password is the one you would use.</para>
</sect2>
<sect2>
<title>Insecure connection initialization</title>
<para>To initialize S/Key or change your password or seed over an
insecure connection, you will need to already have a secure
connection to some place where you can run the <command>key</command> program; this might be in the form of a
desk accessory on a Macintosh, or a shell prompt on a machine you
trust (we will show the latter). You will also need to make up an
iteration count (100 is probably a good value), and you may make
up your own seed or use a randomly-generated one. Over on the
insecure connection (to the machine you are initializing), use the
<command>keyinit -s</command> command:</para>
<screen>&prompt.user; <userinput>keyinit -s</userinput>
Updating wollman: Old key: kh94741
Reminder you need the 6 English words from the skey command.
<prompt>Enter sequence count from 1 to 9999:</prompt> <userinput>100</userinput> ) I typed this
<prompt>Enter new key [default kh94742]:</prompt>
s/key 100 kh94742</screen>
<para>To accept the default seed (which the <command>keyinit</command> program
confusingly calls a <literal>key</literal>), press return. Then move over to your
secure connection or S/Key desk accessory, and give it the same
parameters:</para>
<screen>&prompt.user; <userinput>key 100 kh94742</userinput>
Reminder - Do not use this program while logged in via telnet or rlogin.
<prompt>Enter secret password:</prompt> ) I typed my secret password
HULL NAY YANG TREE TOUT VETO</screen>
<para>Now switch back over to the insecure connection, and copy the
one-time password generated by <command>key</command>
over to the <command>keyinit</command>
program:</para>
<screen><prompt>s/key access password:</prompt> <userinput>HULL NAY YANG TREE TOUT VETO</userinput>
ID wollman s/key is 100 kh94742
HULL NAY YANG TREE TOUT VETO</screen>
<para>The rest of the description from the previous section applies
here as well.</para>
</sect2>
<sect2>
<title>Diversion: a login prompt</title>
<para>Before explaining how to generate one-time passwords, we
should go over an S/Key login prompt:</para>
<screen>&prompt.user; <userinput>telnet himalia</userinput>
Trying 18.26.0.186...
Connected to himalia.lcs.mit.edu.
Escape character is '^]'.
s/key 92 hi52030
<prompt>Password:</prompt></screen>
<para>Note that, before prompting for a password, the login program
prints out the iteration number and seed which you will need in
order to generate the appropriate key. You will also find a
useful feature (not shown here): if you press return at the
password prompt, the login program will turn echo on, so you can
see what you are typing. This can be extremely useful if you are
attempting to type in an S/Key by hand, such as from a
printout.</para>
<para>If this machine were configured to disallow UNIX passwords
over a connection from my machine, the prompt would have also
included the annotation <literal>(s/key
required)</literal>, indicating that only S/Key one-time
passwords will be accepted.</para>
</sect2>
<sect2>
<title>Generating a single one-time password</title>
<para>Now, to generate the one-time password needed to answer this
login prompt, we use a trusted machine and the <command>key</command> program. (There are versions of the
<command>key</command> program from DOS and Windows
machines, and there is an S/Key desk accessory for Macintosh
computers as well.) The command-line <command>key</command> program takes as its parameters the
iteration count and seed; you can cut-and-paste right from the
login prompt starting at <literal>key</literal> to
the end of the line. Thus:</para>
<screen>&prompt.user; <userinput>key 92 hi52030</userinput> ) pasted from previous section
Reminder - Do not use this program while logged in via telnet or rlogin.
<prompt>Enter secret password:</prompt> ) I typed my secret password
ADEN BED WOLF HAW HOT STUN</screen>
<para>And in the other window:</para>
<screen>s/key 92 hi52030 ) from previous section
<prompt>Password:</prompt>
(turning echo on)
<prompt>Password:</prompt>ADEN BED WOLF HAW HOT STUN
Last login: Wed Jun 28 15:31:00 from halloran-eldar.l
[etc.]</screen>
<para>This is the easiest mechanism <emphasis>if</emphasis> you have
a trusted machine. There is a Java S/Key <command>key</command> applet, <ulink
URL="http://www.cs.umd.edu/~harry/jotp/src.html">The Java OTP
Calculator</ulink>, that you can download and run locally on any
Java supporting brower.</para>
</sect2>
<sect2>
<title>Generating multiple one-time passwords</title>
<para>Sometimes we have to go places where no trusted machines or
connections are available. In this case, it is possible to use
the <command>key</command> command to generate a
number of one-time passwords in the same command; these can then
be printed out. For example:</para>
<screen>&prompt.user; <userinput>key -n 25 57 zz99999</userinput>
Reminder - Do not use this program while logged in via telnet or rlogin.
<prompt>Enter secret password:</prompt>
33: WALT THY MALI DARN NIT HEAD
34: ASK RICE BEAU GINA DOUR STAG
&hellip;
56: AMOS BOWL LUG FAT CAIN INCH
57: GROW HAYS TUN DISH CAR BALM</screen>
<para>The <option>-n 25</option> requests twenty-five keys in
sequence; the <option>57</option> indicates the
<emphasis>ending</emphasis> iteration number; and the rest is as
before. Note that these are printed out in
<emphasis>reverse</emphasis> order of eventual use. If you are
really paranoid, you might want to write the results down by hand;
otherwise you can cut-and-paste into <command>lpr</command>. Note that each line shows both the
iteration count and the one-time password; you may still find it
handy to scratch off passwords as you use them.</para>
</sect2>
<sect2>
<title>Restricting use of UNIX passwords</title>
<para>The configuration file <filename>/etc/skey.access</filename>
can be used to configure restrictions on the use of UNIX passwords
based on the host name, user name, terminal port, or IP address of
a login session. The complete format of the file is documented in
the <citerefentry><refentrytitle>skey.access</refentrytitle><manvolnum>5</manvolnum></citerefentry> manual page; there are
also some security cautions there which should be read before
depending on this file for security.</para>
<para>If there is no <filename>/etc/skey.access</filename> file
(which is the default state as FreeBSD is shipped), then all users
will be allowed to use UNIX passwords. If the file exists,
however, then all users will be required to use S/Key unless
explicitly permitted to do otherwise by configuration statements
in the <filename>skey.access</filename> file. In all cases, UNIX
passwords are permitted on the console.</para>
<para>Here is a sample configuration file which illustrates the
three most common sorts of configuration statements:</para>
<programlisting>
permit internet 18.26.0.0 255.255.0.0
permit user jrl
permit port ttyd0</programlisting>
<para>The first line (<literal>permit
internet</literal>) allows users whose IP source address
(which is vulnerable to spoofing) matches the specified value and
mask, to use UNIX passwords. This should not be considered a
security mechanism, but rather, a means to remind authorized users
that they are using an insecure network and need to use S/Key for
authentication.</para>
<para>The second line (<literal>permit user</literal>)
allows the specified user to use UNIX passwords at any time.
Generally speaking, this should only be used for people who are
either unable to use the <command>key</command>
program, like those with dumb terminals, or those who are
uneducable.</para>
<para>The third line (<literal>permit port</literal>)
allows all users logging in on the specified terminal line to use
UNIX passwords; this would be used for dial-ups.</para>
</sect2>
</sect1>
<sect1 id="kerberos">
<title>Kerberos</title>
<para><emphasis>Contributed by &a.markm; (based on contribution by
&a.md;).</emphasis></para>
<para>Kerberos is a network add-on system/protocol that allows users
to authenticate themselves through the services of a secure server.
Services such as remote login, remote copy, secure inter-system file
copying and other high-risk tasks are made considerably safer and
more controllable.</para>
<para>The following instructions can be used as a guide on how to set
up Kerberos as distributed for FreeBSD. However, you should refer to
the relevant manual pages for a complete description.</para>
<para>In FreeBSD, the Kerberos is not that from the original
4.4BSD-Lite, distribution, but eBones, which had been previously
ported to FreeBSD 1.1.5.1, and was sourced from outside the
USA/Canada, and is thus available to system owners outside those
countries.</para>
<para>For those needing to get a legal foreign distribution of this
software, please <emphasis>do not</emphasis> get it from a USA or
Canada site. You will get that site in <emphasis>big</emphasis>
trouble! A legal copy of this is available from
<hostid role="fqdn">ftp.internat.freebsd.org</hostid>, which is in
South Africa and an official FreeBSD mirror site.</para>
<sect2>
<title>Creating the initial database</title>
<para>This is done on the Kerberos server only. First make sure that
you do not have any old Kerberos databases around. You should
change to the directory <filename>/etc/kerberosIV</filename> and
check that only the following files are present:</para>
<screen>&prompt.root; <userinput>cd /etc/kerberosIV</userinput>
&prompt.root; <userinput>ls</userinput>
README krb.conf krb.realms</screen>
<para>If any additional files (such as
<filename>principal.*</filename> or <filename>master_key</filename>)
exist, then use the <command>kdb_destroy</command> command to
destroy the old Kerberos database, of if Kerberos is not running,
simply delete the extra files.</para>
<para>You should now edit the <filename>krb.conf</filename> and
<filename>krb.realms</filename> files to define your Kerberos
realm. In this case the realm will be
<filename>GRONDAR.ZA</filename> and the server is
<filename>grunt.grondar.za</filename>. We edit or create the
<filename>krb.conf</filename> file:</para>
<screen>&prompt.root; <userinput>cat krb.conf</userinput>
GRONDAR.ZA
GRONDAR.ZA grunt.grondar.za admin server
CS.BERKELEY.EDU okeeffe.berkeley.edu
ATHENA.MIT.EDU kerberos.mit.edu
ATHENA.MIT.EDU kerberos-1.mit.edu
ATHENA.MIT.EDU kerberos-2.mit.edu
ATHENA.MIT.EDU kerberos-3.mit.edu
LCS.MIT.EDU kerberos.lcs.mit.edu
TELECOM.MIT.EDU bitsy.mit.edu
ARC.NASA.GOV trident.arc.nasa.gov</screen>
<para>In this case, the other realms do not need to be there. They
are here as an example of how a machine may be made aware of
multiple realms. You may wish to not include them for
simplicity.</para>
<para>The first line names the realm in which this system works. The
other lines contain realm/host entries. The first item on a line
is a realm, and the second is a host in that realm that is acting
as a &ldquo;key distribution centre&rdquo;. The words <literal>admin server</literal>
following a hosts name means that host also provides an
administrative database server. For further explanation of these
terms, please consult the Kerberos man pages.</para>
<para>Now we have to add <hostid role="fqdn">grunt.grondar.za</hostid> to
the <filename>GRONDAR.ZA</filename> realm and also add an entry to
put all hosts in the <hostid role="domainname">.grondar.za</hostid> domain in
the <filename>GRONDAR.ZA</filename> realm. The
<filename>krb.realms</filename> file would be updated as
follows:</para>
<screen>&prompt.root; <userinput>cat krb.realms</userinput>
grunt.grondar.za GRONDAR.ZA
.grondar.za GRONDAR.ZA
.berkeley.edu CS.BERKELEY.EDU
.MIT.EDU ATHENA.MIT.EDU
.mit.edu ATHENA.MIT.EDU</screen>
<para>Again, the other realms do not need to be there. They are here
as an example of how a machine may be made aware of multiple
realms. You may wish to remove them to simplify things.</para>
<para>The first line puts the <emphasis>specific</emphasis>
system into the named realm. The rest of the lines show how to
default systems of a particular subdomain to a named realm.</para>
<para>Now we are ready to create the database. This only needs to
run on the Kerberos server (or Key Distribution Centre). Issue the
<command>kdb_init</command> command to do this:</para>
<screen>&prompt.root; <userinput>kdb_init</userinput>
<prompt>Realm name [default ATHENA.MIT.EDU ]:</prompt> <userinput>GRONDAR.ZA</userinput>
You will be prompted for the database Master Password.
It is important that you NOT FORGET this password.
<prompt>Enter Kerberos master key:</prompt> </screen>
<para>Now we have to save the key so that servers on the local
machine can pick it up. Use the <command>kstash</command> command to do this.</para>
<screen>&prompt.root; <userinput>kstash</userinput>
<prompt>Enter Kerberos master key:</prompt>
Current Kerberos master key version is 1.
Master key entered. BEWARE!</screen>
<para>This saves the encrypted master password in
<filename>/etc/kerberosIV/master_key</filename>.</para>
</sect2>
<sect2>
<title>Making it all run</title>
<para>Two principals need to be added to the database for <emphasis>each</emphasis> system that will be secured with
Kerberos. Their names are <literal>kpasswd</literal>
and <literal>rcmd</literal> These two principals are
made for each system, with the instance being the name of the
individual system.</para>
<para>These daemons, <command>kpasswd</command> and
<command>rcmd</command> allow other systems to change
Kerberos passwords and run commands like <command>rcp</command>, <command>rlogin</command>
and <command>rsh</command>.</para>
<para>Now let's add these entries:</para>
<screen>&prompt.root; <userinput>kdb_edit</userinput>
Opening database...
<prompt>Enter Kerberos master key:</prompt>
Current Kerberos master key version is 1.
Master key entered. BEWARE!
Previous or default values are in [brackets] ,
enter return to leave the same, or new value.
<prompt>Principal name:</prompt> <userinput>passwd</userinput>
<prompt>Instance:</prompt> <userinput>grunt</userinput>
&lt;Not found&gt;, <prompt>Create [y] ?</prompt> <userinput>y</userinput>
Principal: passwd, Instance: grunt, kdc_key_ver: 1
<prompt>New Password:</prompt> &lt;---- enter RANDOM here
Verifying password
<prompt>New Password:</prompt> &lt;---- enter RANDOM here
<prompt>Random password [y] ?</prompt> <userinput>y</userinput>
Principal's new key version = 1
<prompt>Expiration date (enter yyyy-mm-dd) [ 2000-01-01 ] ?</prompt>
<prompt>Max ticket lifetime (*5 minutes) [ 255 ] ?</prompt>
<prompt>Attributes [ 0 ] ?</prompt>
Edit O.K.
<prompt>Principal name:</prompt> <userinput>rcmd</userinput>
<prompt>Instance:</prompt> <userinput>grunt</userinput>
&lt;Not found&gt;, <prompt>Create [y] ?</prompt>
Principal: rcmd, Instance: grunt, kdc_key_ver: 1
<prompt>New Password:</prompt> &lt;---- enter RANDOM here
Verifying password
<prompt>New Password:</prompt> &lt;---- enter RANDOM here
<prompt>Random password [y] ?</prompt>
Principal's new key version = 1
<prompt>Expiration date (enter yyyy-mm-dd) [ 2000-01-01 ] ?</prompt>
<prompt>Max ticket lifetime (*5 minutes) [ 255 ] ?</prompt>
<prompt>Attributes [ 0 ] ?</prompt>
Edit O.K.
<prompt>Principal name:</prompt> &lt;---- null entry here will cause an exit</screen>
</sect2>
<sect2>
<title>Creating the server file</title>
<para>We now have to extract all the instances which define the
services on each machine. For this we use the
<command>ext_srvtab</command> command. This will create a file which
must be copied or moved <emphasis>by secure
means</emphasis> to each Kerberos client's /etc/kerberosIV
directory. This file must be present on each server and client,
and is crucial to the operation of Kerberos.</para>
<screen>&prompt.root; <userinput>ext_srvtab grunt</userinput>
<prompt>Enter Kerberos master key:</prompt>
Current Kerberos master key version is 1.
Master key entered. BEWARE!
Generating 'grunt-new-srvtab'....</screen>
<para>Now, this command only generates a temporary file which must
be renamed to <filename>srvtab</filename> so that all the
server can pick it up. Use the <command>mv</command>
command to move it into place on the original system:</para>
<screen>&prompt.root; <userinput>mv grunt-new-srvtab srvtab</userinput></screen>
<para>If the file is for a client system, and the network is not
deemed safe, then copy the <filename><replaceable>client</replaceable>-new-srvtab</filename> to removable media
and transport it by secure physical means. Be sure to rename it to
<filename>srvtab</filename> in the client's
<filename>/etc/kerberosIV</filename> directory, and make sure it
is mode 600:</para>
<screen>&prompt.root; <userinput>mv grumble-new-srvtab srvtab</userinput>
&prompt.root; <userinput>chmod 600 srvtab</userinput></screen>
</sect2>
<sect2>
<title>Populating the database</title>
<para>We now have to add some user entries into the database. First
let's create an entry for the user <username>jane</username>. Use
the <command>kdb_edit</command> command to do this:</para>
<screen>&prompt.root; <userinput>kdb_edit</userinput>
Opening database...
<prompt>Enter Kerberos master key:</prompt>
Current Kerberos master key version is 1.
Master key entered. BEWARE!
Previous or default values are in [brackets] ,
enter return to leave the same, or new value.
<prompt>Principal name:</prompt> <userinput>jane</userinput>
<prompt>Instance:</prompt>
&lt;Not found&gt;, <prompt>Create [y] ?</prompt> <userinput>y</userinput>
Principal: jane, Instance: , kdc_key_ver: 1
<prompt>New Password:</prompt> &lt;---- enter a secure password here
Verifying password
<prompt>New Password:</prompt> &lt;---- re-enter the password here
Principal's new key version = 1
<prompt>Expiration date (enter yyyy-mm-dd) [ 2000-01-01 ] ?</prompt>
<prompt>Max ticket lifetime (*5 minutes) [ 255 ] ?</prompt>
<prompt>Attributes [ 0 ] ?</prompt>
Edit O.K.
<prompt>Principal name:</prompt> &lt;---- null entry here will cause an exit</screen>
</sect2>
<sect2>
<title>Testing it all out</title>
<para>First we have to start the Kerberos daemons. NOTE that if you
have correctly edited your <filename>/etc/rc.conf</filename> then
this will happen automatically when you reboot. This is only
necessary on the Kerberos server. Kerberos clients will
automagically get what they need from the
<filename>/etc/kerberosIV</filename> directory.</para>
<screen>&prompt.root; <userinput>kerberos &amp;</userinput>
Kerberos server starting
Sleep forever on error
Log file is /var/log/kerberos.log
Current Kerberos master key version is 1.
Master key entered. BEWARE!
Current Kerberos master key version is 1
Local realm: GRONDAR.ZA
&prompt.root; <userinput>kadmind -n &amp;</userinput>
KADM Server KADM0.0A initializing
Please do not use 'kill -9' to kill this job, use a
regular kill instead
Current Kerberos master key version is 1.
Master key entered. BEWARE!</screen>
<para>Now we can try using the <command>kinit</command>
command to get a ticket for the id <username>jane</username> that we created above:</para>
<screen>&prompt.user; <userinput>kinit jane</userinput>
MIT Project Athena (grunt.grondar.za)
Kerberos Initialization for "jane"
<prompt>Password:</prompt> </screen>
<para>Try listing the tokens using <command>klist</command> to see if we really have them:</para>
<screen>&prompt.user; <userinput>klist</userinput>
Ticket file: /tmp/tkt245
Principal: jane@GRONDAR.ZA
Issued Expires Principal
Apr 30 11:23:22 Apr 30 19:23:22 krbtgt.GRONDAR.ZA@GRONDAR.ZA</screen>
<para>Now try changing the password using <command>passwd</command> to check if the kpasswd daemon can
get authorization to the Kerberos database:</para>
<screen>&prompt.user; <userinput>passwd</userinput>
realm GRONDAR.ZA
<prompt>Old password for jane:</prompt>
<prompt>New Password for jane:</prompt>
Verifying password
<prompt>New Password for jane:</prompt>
Password changed.</screen>
</sect2>
<sect2>
<title>Adding <command>su</command> privileges</title>
<para>Kerberos allows us to give <emphasis>each</emphasis>
user who needs root privileges their own <emphasis>separate</emphasis> <command>su</command>password. We could now add an id which is
authorized to <command>su</command> to <username>root</username>. This is controlled by having an
instance of <username>root</username> associated with a
principal. Using <command>kdb_edit</command> we can create the
entry <literal>jane.root</literal> in the Kerberos
database:</para>
<screen>&prompt.root; <userinput>kdb_edit</userinput>
Opening database...
<prompt>Enter Kerberos master key:</prompt>
Current Kerberos master key version is 1.
Master key entered. BEWARE!
Previous or default values are in [brackets] ,
enter return to leave the same, or new value.
<prompt>Principal name:</prompt> <userinput>jane</userinput>
<prompt>Instance:</prompt> <userinput>root</userinput>
&lt;Not found&gt;, Create [y] ? y
Principal: jane, Instance: root, kdc_key_ver: 1
<prompt>New Password:</prompt> &lt;---- enter a SECURE password here
Verifying password
<prompt>New Password:</prompt> &lt;---- re-enter the password here
Principal's new key version = 1
<prompt>Expiration date (enter yyyy-mm-dd) [ 2000-01-01 ] ?</prompt>
<prompt>Max ticket lifetime (*5 minutes) [ 255 ] ?</prompt> <userinput>12</userinput> &lt;--- Keep this short!
<prompt>Attributes [ 0 ] ?</prompt>
Edit O.K.
<prompt>Principal name:</prompt> &lt;---- null entry here will cause an exit</screen>
<para>Now try getting tokens for it to make sure it works:</para>
<screen>&prompt.root; <userinput>kinit jane.root</userinput>
MIT Project Athena (grunt.grondar.za)
Kerberos Initialization for "jane.root"
<prompt>Password:</prompt></screen>
<para>Now we need to add the user to root's
<filename>.klogin</filename> file:</para>
<screen>&prompt.root; <userinput>cat /root/.klogin</userinput>
jane.root@GRONDAR.ZA</screen>
<para>Now try doing the <command>su</command>:</para>
<screen>&prompt.user; <prompt>su</prompt>
<prompt>Password:</prompt></screen>
<para>and take a look at what tokens we have:</para>
<screen>&prompt.root; klist
Ticket file: /tmp/tkt_root_245
Principal: jane.root@GRONDAR.ZA
Issued Expires Principal
May 2 20:43:12 May 3 04:43:12 krbtgt.GRONDAR.ZA@GRONDAR.ZA</screen>
</sect2>
<sect2>
<title>Using other commands</title>
<para>In an earlier example, we created a principal called
<literal>jane</literal> with an instance <literal>root</literal>. This was based on a user with the same
name as the principal, and this is a Kerberos default; that a
<literal>&lt;principal&gt;.&lt;instance&gt;</literal> of the
form <literal>&lt;username&gt;.</literal><literal>root</literal> will allow that
<literal>&lt;username&gt;</literal> to <command>su</command> to root if the necessary entries are in
the <filename>.klogin</filename> file in <username>root</username>'s home directory:</para>
<screen>&prompt.root; <userinput>cat /root/.klogin</userinput>
jane.root@GRONDAR.ZA</screen>
<para>Likewise, if a user has in their own home directory lines of
the form:</para>
<screen>&prompt.user; <userinput>cat ~/.klogin</userinput>
jane@GRONDAR.ZA
jack@GRONDAR.ZA</screen>
<para>This allows anyone in the <filename>GRONDAR.ZA</filename>
realm who has authenticated themselves to
<username>jane</username> or <username>jack</username> (via
<command>kinit</command>, see above) access to
<command>rlogin</command> to
<username>jane</username>'s account or files on this system
(<hostid>grunt</hostid>) via <command>rlogin</command>, <command>rsh</command> or
<command>rcp</command>.</para>
<para>For example, Jane now logs into another system, using
Kerberos:</para>
<screen>&prompt.user; <userinput>kinit</userinput>
MIT Project Athena (grunt.grondar.za)
<prompt>Password:</prompt>
%prompt.user; <userinput>rlogin grunt</userinput>
Last login: Mon May 1 21:14:47 from grumble
Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
The Regents of the University of California. All rights reserved.
FreeBSD BUILT-19950429 (GR386) #0: Sat Apr 29 17:50:09 SAT 1995</screen>
<para>Or Jack logs into Jane's account on the same machine (Jane
having set up the <filename>.klogin</filename> file as above, and
the person in charge of Kerberos having set up principal
<emphasis>jack</emphasis> with a null instance:</para>
<screen>&prompt.user; <userinput>kinit</userinput>
&prompt.user; <userinput>rlogin grunt -l jane</userinput>
MIT Project Athena (grunt.grondar.za)
<prompt>Password:</prompt>
Last login: Mon May 1 21:16:55 from grumble
Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
The Regents of the University of California. All rights reserved.
FreeBSD BUILT-19950429 (GR386) #0: Sat Apr 29 17:50:09 SAT 1995</screen>
</sect2>
</sect1>
<sect1 id="firewalls">
<title>Firewalls</title>
<para><emphasis>Contributed by &a.gpalmer; and
&a.alex;.</emphasis></para>
<para>Firewalls are an area of increasing interest for people who are
connected to the Internet, and are even finding applications on
private networks to provide enhanced security. This section will
hopefully explain what firewalls are, how to use them, and how to
use the facilities provided in the FreeBSD kernel to implement
them.</para>
<note>
<para>People often think that having a firewall between your
companies internal network and the &ldquo;Big Bad Internet&rdquo;
will solve all your security problems.</para>
<para>It may help, but a poorly setup firewall system is more of a
security risk than not having one at all. A firewall can only add
another layer of security to your systems, but they will not be
able to stop a really determined cracker from penetrating your
internal network. If you let internal security lapse because you
believe your firewall to be impenetrable, you have just made the
crackers job that bit easier.</para>
</note>
<sect2>
<title>What is a firewall?</title>
<para>There are currently two distinct types of firewalls in common
use on the Internet today. The first type is more properly called
a <emphasis>packet filtering router</emphasis>, where the
kernel on a multi-homed machine chooses whether to forward or
block packets based on a set of rules. The second type, known as
<emphasis>proxy servers</emphasis>, rely on daemons to
provide authentication and to forward packets, possibly on a
multi-homed machine which has kernel packet forwarding
disabled.</para>
<para>Sometimes sites combine the two types of firewalls, so that
only a certain machine (known as a <emphasis>bastion
host</emphasis>) is allowed to send packets through a packet
filtering router onto an internal network. Proxy services are run
on the bastion host, which are generally more secure than normal
authentication mechanisms.</para>
<para>FreeBSD comes with a kernel packet filter (known as
<application>IPFW</application>), which is what the rest of this section
will concentrate on. Proxy servers can be built on FreeBSD from
third party software, but there is such a variety of proxy servers
available that it would be impossible to cover them in this
document.</para>
<sect3 id="firewalls-packet-filters">
<title>Packet filtering routers</title>
<para>A router is a machine which forwards packets between two or
more networks. A packet filtering router has an extra piece of
code in its kernel, which compares each packet to a list of
rules before deciding if it should be forwarded or not. Most
modern IP routing software has packet filtering code in it,
which defaults to forwarding all packets. To enable the filters,
you need to define a set of rules for the filtering code, so
that it can decide if the packet should be allowed to pass or
not.</para>
<para>To decide if a packet should be passed on or not, the code
looks through its set of rules for a rule which matches the
contents of this packets headers. Once a match is found, the
rule action is obeyed. The rule action could be to drop the
packet, to forward the packet, or even to send an ICMP message
back to the originator. Only the first match counts, as the
rules are searched in order. Hence, the list of rules can be
referred to as a &ldquo;rule chain&rdquo;.</para>
<para>The packet matching criteria varies depending on the
software used, but typically you can specify rules which depend
on the source IP address of the packet, the destination IP
address, the source port number, the destination port number
(for protocols which support ports), or even the packet type
(UDP, TCP, ICMP, etc).</para>
</sect3>
<sect3 id="firewalls-proxy-servers">
<title>Proxy servers</title>
<para>Proxy servers are machines which have had the normal system
daemons (telnetd, ftpd, etc) replaced with special servers.
These servers are called <emphasis>proxy
servers</emphasis> as they normally only allow onward
connections to be made. This enables you to run (for example) a
proxy telnet server on your firewall host, and people can telnet
in to your firewall from the outside, go through some
authentication mechanism, and then gain access to the internal
network (alternatively, proxy servers can be used for signals
coming from the internal network and heading out).</para>
<para>Proxy servers are normally more secure than normal servers,
and often have a wider variety of authentication mechanisms
available, including &ldquo;one-shot&rdquo; password systems so that even
if someone manages to discover what password you used, they will
not be able to use it to gain access to your systems as the
password instantly expires. As they do not actually give users
access to the host machine, it becomes a lot more difficult for
someone to install backdoors around your security system.</para>
<para>Proxy servers often have ways of restricting access further,
so that only certain hosts can gain access to the servers, and
often they can be set up so that you can limit which users can
talk to which destination machine. Again, what facilities are
available depends largely on what proxy software you
choose.</para>
</sect3>
</sect2>
<sect2>
<title>What does IPFW allow me to do?</title>
<para><application>IPFW</application>, the software supplied with FreeBSD,
is a packet filtering and accounting system which resides in the
kernel, and has a user-land control utility,
<citerefentry><refentrytitle>ipfw</refentrytitle><manvolnum>8</manvolnum></citerefentry>. Together, they allow you to define and
query the rules currently used by the kernel in its routing
decisions.</para>
<para>There are two related parts to <application>IPFW</application>. The
firewall section allows you to perform packet filtering. There is
also an IP accounting section which allows you to track usage of
your router, based on similar rules to the firewall section. This
allows you to see (for example) how much traffic your router is
getting from a certain machine, or how much WWW (World Wide Web)
traffic it is forwarding.</para>
<para>As a result of the way that <application>IPFW</application> is
designed, you can use <application>IPFW</application> on non-router
machines to perform packet filtering on incoming and outgoing
connections. This is a special case of the more general use of
<application>IPFW</application>, and the same commands and techniques
should be used in this situation.</para>
</sect2>
<sect2>
<title>Enabling IPFW on FreeBSD</title>
<para>As the main part of the <application>IPFW</application> system lives
in the kernel, you will need to add one or more options to your
kernel configuration file, depending on what facilities you want,
and recompile your kernel. See
<link linkend="kernelconfig">reconfiguring the kernel</link> for
more details on how to recompile your kernel.</para>
<para>There are currently three kernel configuration options
relevant to IPFW:</para>
<variablelist>
<varlistentry><term><literal>options IPFIREWALL</literal></term>
<listitem>
<para>Compiles into the kernel the code for packet
filtering.</para>
</listitem>
</varlistentry>
<varlistentry><term><literal>options IPFIREWALL_VERBOSE</literal></term>
<listitem>
<para>Enables code to allow logging of packets through
<citerefentry><refentrytitle>syslogd</refentrytitle><manvolnum>8</manvolnum></citerefentry>. Without this option, even
if you specify that packets should be logged in the filter
rules, nothing will happen.</para>
</listitem>
</varlistentry>
<varlistentry><term><literal>options IPFIREWALL_VERBOSE_LIMIT=10</literal></term>
<listitem>
<para>Limits the number of packets logged through
<citerefentry><refentrytitle>syslogd</refentrytitle><manvolnum>8</manvolnum></citerefentry> on a per entry basis. You
may wish to use this option in hostile environments in
which you want to log firewall activity, but do not want
to be open to a denial of service attack via syslog
flooding.</para>
<para>When a chain entry reaches the packet limit specified,
logging is turned off for that particular entry. To
resume logging, you will need to reset the associated
counter using the <citerefentry><refentrytitle>ipfw</refentrytitle><manvolnum>8</manvolnum></citerefentry>
utility:</para>
<screen>&prompt.root; <userinput>ipfw zero 4500</userinput></screen>
<para>Where 4500 is the chain entry you wish to continue
logging.</para>
</listitem>
</varlistentry>
</variablelist>
<para>Previous versions of FreeBSD contained an
<literal>IPFIREWALL_ACCT</literal> option. This is now obsolete as
the firewall code automatically includes accounting
facilities.</para>
</sect2>
<sect2>
<title>Configuring IPFW</title>
<para>The configuration of the <application>IPFW</application> software is
done through the <citerefentry><refentrytitle>ipfw</refentrytitle><manvolnum>8</manvolnum></citerefentry> utility. The syntax
for this command looks quite complicated, but it is relatively
simple once you understand its structure.</para>
<para>There are currently four different command categories used by
the utility: addition/deletion, listing, flushing, and clearing.
Addition/deletion is used to build the rules that control how
packets are accepted, rejected, and logged. Listing is used to
examine the contents of your rule set (otherwise known as the
chain) and packet counters (accounting). Flushing is used to
remove all entries from the chain. Clearing is used to zero out
one or more accounting entries.</para>
<sect3>
<title>Altering the IPFW rules</title>
<para>The syntax for this form of the command is:
<cmdsynopsis>
<command>ipfw</command>
<arg>-N</arg>
<arg choice="plain">command</arg>
<arg>index</arg>
<arg choice="plain">action</arg>
<arg>log</arg>
<arg choice="plain">protocol</arg>
<arg choice="plain">addresses</arg>
<arg>options</arg>
</cmdsynopsis></para>
<para>There is one valid flag when using this form of the
command:</para>
<variablelist>
<varlistentry><term>-N</term>
<listitem>
<para>Resolve addresses and service names in
output.</para>
</listitem>
</varlistentry>
</variablelist>
<para>The <emphasis>command</emphasis> given can be shortened to
the shortest unique form. The valid
<emphasis>commands</emphasis> are:</para>
<variablelist>
<varlistentry><term>add</term>
<listitem>
<para>Add an entry to the firewall/accounting rule
list</para>
</listitem>
</varlistentry>
<varlistentry><term>delete</term>
<listitem>
<para>Delete an entry from the firewall/accounting rule
list</para>
</listitem>
</varlistentry>
</variablelist>
<para>Previous versions of <application>IPFW</application> used separate
firewall and accounting entries. The present version provides
packet accounting with each firewall entry.</para>
<para>If an <emphasis>index</emphasis> value is supplied,
it used to place the entry at a specific point in the chain.
Otherwise, the entry is placed at the end of the chain at an
index 100 greater than the last chain entry (this does not
include the default policy, rule 65535, deny).</para>
<para>The <literal>log</literal> option causes matching
rules to be output to the system console if the kernel was
compiled with <literal>IPFIREWALL_VERBOSE</literal>.</para>
<para>Valid <emphasis>actions</emphasis> are:</para>
<variablelist>
<varlistentry><term>reject</term>
<listitem>
<para>Drop the packet, and send an ICMP host or port
unreachable (as appropriate) packet to the
source.</para>
</listitem>
</varlistentry>
<varlistentry><term>allow</term>
<listitem>
<para>Pass the packet on as normal. (aliases:
<literal>pass</literal> and <literal>accept</literal>)</para>
</listitem>
</varlistentry>
<varlistentry><term>deny</term>
<listitem>
<para>Drop the packet. The source is not notified via an
ICMP message (thus it appears that the packet never
arrived at the destination).</para>
</listitem>
</varlistentry>
<varlistentry><term>count</term>
<listitem>
<para>Update packet counters but do not allow/deny the
packet based on this rule. The search continues with
the next chain entry.</para>
</listitem>
</varlistentry>
</variablelist>
<para>Each <emphasis>action</emphasis> will be recognized by the
shortest unambiguous prefix.</para>
<para>The <emphasis>protocols</emphasis> which can be specified
are:</para>
<variablelist>
<varlistentry><term>all</term>
<listitem>
<para>Matches any IP packet</para>
</listitem>
</varlistentry>
<varlistentry><term>icmp</term>
<listitem>
<para>Matches ICMP packets</para>
</listitem>
</varlistentry>
<varlistentry><term>tcp</term>
<listitem>
<para>Matches TCP packets</para>
</listitem>
</varlistentry>
<varlistentry><term>udp</term>
<listitem>
<para>Matches UDP packets</para>
</listitem>
</varlistentry>
</variablelist>
<para>The <emphasis>address</emphasis> specification is:</para>
<cmdsynopsis>
<arg choice="plain">from</arg>
<arg choice="plain"><replaceable>address/mask</replaceable></arg><arg><replaceable>port</replaceable></arg>
<arg choice="plain">to</arg>
<arg choice="plain"><replaceable>address/mark</replaceable></arg><arg><replaceable>port</replaceable></arg>
<arg>via <replaceable>interface</replaceable></arg>
</cmdsynopsis>
<para>You can only specify <replaceable>port</replaceable> in
conjunction with <emphasis>protocols</emphasis> which support
ports (UDP and TCP).</para>
<para>The <option>via</option> is optional and may
specify the IP address or domain name of a local IP interface,
or an interface name (e.g. <devicename>ed0</devicename>) to
match only packets coming through this interface. Interface unit
numbers can be specified with an optional wildcard. For example,
<literal>ppp*</literal> would match all kernel PPP
interfaces.</para>
<para>The syntax used to specify an
<replaceable>address/mask</replaceable> is:
<screen><replaceable>address</replaceable></screen>
or
<screen><replaceable>address</replaceable>/<replaceable>mask-bits</replaceable></screen>
or
<screen><replaceable>address</replaceable>:<replaceable>mask-pattern</replaceable></screen>
</para>
<para>A valid hostname may be specified in place of the IP
address. <option><replaceable>mask-bits</replaceable></option> is a decimal
number representing how many bits in the address mask should be
set. e.g. specifying <literal>192.216.222.1/24</literal> will create a mask which will allow any
address in a class C subnet (in this case, 192.216.222) to be
matched. <option><replaceable>mask-pattern</replaceable></option> is an IP
address which will be logically AND'ed with the address given.
The keyword <literal>any</literal> may be used to
specify &ldquo;any IP address&rdquo;.</para>
<para>The port numbers to be blocked are specified as:
<cmdsynopsis>
<arg choice="plain"><replaceable>port</replaceable><arg>,<replaceable>port</replaceable><arg>,<replaceable>port</replaceable><arg>&hellip;</arg></arg></arg></arg>
</cmdsynopsis>to specify either a single port or a list of
ports, or
<cmdsynopsis>
<arg choice="plain"><replaceable>port</replaceable>-<replaceable>port</replaceable></arg>
</cmdsynopsis> to specify a range of ports. You may also
combine a single range with a list, but the range must always be
specified first.</para>
<para>The <emphasis>options</emphasis> available are:</para>
<variablelist>
<varlistentry><term>frag</term>
<listitem>
<para>Matches if the packet is not the first fragment of
the datagram.</para>
</listitem>
</varlistentry>
<varlistentry><term>in</term>
<listitem>
<para>Matches if the packet is on the way in.</para>
</listitem>
</varlistentry>
<varlistentry><term>out</term>
<listitem>
<para>Matches if the packet is on the way out.</para>
</listitem>
</varlistentry>
<varlistentry><term>ipoptions <replaceable>spec</replaceable></term>
<listitem>
<para>Matches if the IP header contains the comma
separated list of options specified in
<replaceable>spec</replaceable>. The supported list of IP
options are: <literal>ssrr</literal> (strict
source route), <literal>lsrr</literal> (loose
source route), <literal>rr</literal> (record
packet route), and <literal>ts</literal>
(timestamp). The absence of a particular option may be
denoted with a leading <literal>!</literal>.</para>
</listitem>
</varlistentry>
<varlistentry><term>established</term>
<listitem>
<para>Matches if the packet is part of an already
established TCP connection (i.e. it has the RST or ACK
bits set). You can optimize the performance of the
firewall by placing <emphasis>established</emphasis>
rules early in the chain.</para>
</listitem>
</varlistentry>
<varlistentry><term>setup</term>
<listitem>
<para>Matches if the packet is an attempt to establish a
TCP connection (the SYN bit set is set but the ACK bit
is not).</para>
</listitem>
</varlistentry>
<varlistentry><term>tcpflags <replaceable>flags</replaceable></term>
<listitem>
<para>Matches if the TCP header contains the comma
separated list of <replaceable>flags</replaceable>. The
supported flags are <literal>fin</literal>,
<literal>syn</literal>, <literal>rst</literal>,
<literal>psh</literal>, <literal>ack</literal>, and
<literal>urg</literal>. The absence of a particular
flag may be indicated by a leading <literal>!</literal>.</para>
</listitem>
</varlistentry>
<varlistentry><term>icmptypes <replaceable>types</replaceable></term>
<listitem>
<para>Matches if the ICMP type is present in the list
<replaceable>types</replaceable>. The list may be specified
as any combination of ranges and/or individual types
separated by commas. Commonly used ICMP types are:
<literal>0</literal> echo reply (ping reply),
<literal>3</literal> destination unreachable,
<literal>5</literal> redirect, <literal>8</literal> echo request (ping request), and
<literal>11</literal> time exceeded (used to
indicate TTL expiration as with
<citerefentry><refentrytitle>traceroute</refentrytitle><manvolnum>8</manvolnum></citerefentry>).</para>
</listitem>
</varlistentry>
</variablelist>
</sect3>
<sect3>
<title>Listing the IPFW rules</title>
<para>The syntax for this form of the command is:
<cmdsynopsis>
<command>ipfw</command>
<arg>-a</arg>
<arg>-t</arg>
<arg>-N</arg>
<arg choice="plain">l</arg>
</cmdsynopsis></para>
<para>There are three valid flags when using this form of the
command:</para>
<variablelist>
<varlistentry><term>-a</term>
<listitem>
<para>While listing, show counter values. This option is
the only way to see accounting counters.</para>
</listitem>
</varlistentry>
<varlistentry><term>-t</term>
<listitem>
<para>Display the last match times for each chain entry.
The time listing is incompatible with the input syntax
used by the <citerefentry><refentrytitle>ipfw</refentrytitle><manvolnum>8</manvolnum></citerefentry> utility.</para>
</listitem>
</varlistentry>
<varlistentry><term>-N</term>
<listitem>
<para>Attempt to resolve given addresses and service
names.</para>
</listitem>
</varlistentry>
</variablelist>
</sect3>
<sect3>
<title>Flushing the IPFW rules</title>
<para>The syntax for flushing the chain is:
<cmdsynopsis>
<command>ipfw</command>
<arg choice="plain">flush</arg>
</cmdsynopsis></para>
<para>This causes all entries in the firewall chain to be removed
except the fixed default policy enforced by the kernel (index
65535). Use caution when flushing rules, the default deny
policy will leave your system cut off from the network until
allow entries are added to the chain.</para>
</sect3>
<sect3>
<title>Clearing the IPFW packet counters</title>
<para>The syntax for clearing one or more packet counters is:
<cmdsynopsis>
<command>ipfw</command>
<arg choice="plain">zero</arg>
<arg choice="opt"><replaceable>index</replaceable></arg>
</cmdsynopsis></para>
<para>When used without an <replaceable>index</replaceable> argument,
all packet counters are cleared. If an
<replaceable>index</replaceable> is supplied, the clearing operation
only affects a specific chain entry.</para>
</sect3>
</sect2>
<sect2>
<title>Example commands for ipfw</title>
<para>This command will deny all packets from the host
<hostid role="fqdn">evil.crackers.org</hostid> to the telnet port of the
host <hostid role="fqdn">nice.people.org</hostid> by being forwarded by
the router:</para>
<screen>&prompt.root <userinput>ipfw add deny tcp from evil.crackers.org to nice.people.org 23</userinput></screen>
<para>The next example denies and logs any TCP traffic from the
entire <hostid role="domainname">crackers.org</hostid> network (a class C) to the
<hostid role="fqdn">nice.people.org</hostid> machine (any port).</para>
<screen>&prompt.root; <userinput>ipfw add deny log tcp from evil.crackers.org/24 to nice.people.org</userinput></screen>
<para>If you do not want people sending X sessions to your internal
network (a subnet of a class C), the following command will do the
necessary filtering:</para>
<screen>&prompt.root; <userinput>ipfw add deny tcp from any to my.org/28 6000 setup</userinput></screen>
<para>To see the accounting records:
<screen>&prompt.root; <userinput>ipfw -a list</userinput></screen>
or in the short form
<screen>&prompt.root; <userinput>ipfw -a l</userinput></screen>
</para>
<para>You can also see the last time a chain entry
was matched with:</para>
<screen>&prompt.root; <userinput>ipfw -at l</userinput></screen>
</sect2>
<sect2>
<title>Building a packet filtering firewall</title>
<note>
<para>The following suggestions are just that: suggestions. The
requirements of each firewall are different and I cannot tell
you how to build a firewall to meet your particular
requirements.</para>
</note>
<para>When initially setting up your firewall, unless you have a
test bench setup where you can configure your firewall host in a
controlled environment, I strongly recommend you use the logging
version of the commands and enable logging in the kernel. This
will allow you to quickly identify problem areas and cure them
without too much disruption. Even after the initial setup phase is
complete, I recommend using the logging for of `deny' as it allows
tracing of possible attacks and also modification of the firewall
rules if your requirements alter.</para>
<note>
<para>If you use the logging versions of the <command>accept</command> command, it can generate
<emphasis>large</emphasis> amounts of log data as one log line
will be generated for every packet that passes through the
firewall, so large ftp/http transfers, etc, will really slow the
system down. It also increases the latencies on those packets as
it requires more work to be done by the kernel before the packet
can be passed on. syslogd with also start using up a lot more
processor time as it logs all the extra data to disk, and it
could quite easily fill the partition
<filename>/var/log</filename> is located on.</para>
</note>
<para>As currently supplied, FreeBSD does not have the ability to
load firewall rules at boot time. My suggestion is to put a call
to a shell script in the <filename>/etc/netstart</filename>
script. Put the call early enough in the netstart file so that the
firewall is configured before any of the IP interfaces are
configured. This means that there is no window during which time
your network is open.</para>
<para>The actual script used to load the rules is entirely up to
you. There is currently no support in the <command>ipfw</command> utility for loading multiple rules in
the one command. The system I use is to use the command:</para>
<screen>&prompt.root; <userinput>ipfw list</userinput></screen>
<para>to write a list of the current rules out to a file, and then
use a text editor to prepend <literal>ipfw
</literal> before all the lines. This will allow the script to
be fed into /bin/sh and reload the rules into the kernel. Perhaps
not the most efficient way, but it works.</para>
<para>The next problem is what your firewall should actually
<emphasis>do</emphasis>! This is largely dependent on what access to
your network you want to allow from the outside, and how much
access to the outside world you want to allow from the inside.
Some general rules are:</para>
<itemizedlist>
<listitem>
<para>Block all incoming access to ports below 1024 for TCP.
This is where most of the security sensitive services are,
like finger, SMTP (mail) and telnet.</para>
</listitem>
<listitem>
<para>Block <emphasis>all</emphasis> incoming UDP
traffic. There are very few useful services that travel over
UDP, and what useful traffic there is is normally a security
threat (e.g. Suns RPC and NFS protocols). This has its
disadvantages also, since UDP is a connectionless protocol,
denying incoming UDP traffic also blocks the replies to
outgoing UDP traffic. This can cause a problem for people
(on the inside) using external archie (prospero) servers.
If you want to allow access to archie, you'll have to allow
packets coming from ports 191 and 1525 to any internal UDP
port through the firewall. ntp is another service you may
consider allowing through, which comes from port 123.</para>
</listitem>
<listitem>
<para>Block traffic to port 6000 from the outside. Port 6000
is the port used for access to X11 servers, and can be a
security threat (especially if people are in the habit of
doing <command>xhost +</command> on their
workstations). X11 can actually use a range of ports
starting at 6000, the upper limit being how many X displays
you can run on the machine. The upper limit as defined by
RFC 1700 (Assigned Numbers) is 6063.</para>
</listitem>
<listitem>
<para>Check what ports any internal servers use (e.g. SQL
servers, etc). It is probably a good idea to block those as
well, as they normally fall outside the 1-1024 range
specified above.</para>
</listitem>
</itemizedlist>
<para>Another checklist for firewall configuration is available from
CERT at <ulink
URL="ftp://ftp.cert.org/pub/tech_tips/packet_filtering">ftp://ftp.cert.org/pub/tech_tips/packet_filtering</ulink></para>
<para>As I said above, these are only
<emphasis>guidelines</emphasis>. You will have to decide what
filter rules you want to use on your firewall yourself. I cannot
accept ANY responsibility if someone breaks into your network,
even if you follow the advice given above.</para>
</sect2>
</sect1>
</chapter>
<!--
Local Variables:
mode: sgml
sgml-declaration: "../chapter.decl"
sgml-indent-data: t
sgml-omittag: nil
sgml-always-quote-attributes: t
sgml-parent-document: ("../handbook.sgml" "part" "chapter")
End:
-->