FreeBSD, Inc. now owes me a new keyboard as I've seemed to have worn out my "shift" and "`" key from sending vi so many "~"s. :->
1612 lines
66 KiB
Text
1612 lines
66 KiB
Text
<!--
|
|
The FreeBSD Documentation Project
|
|
|
|
$Id: chapter.sgml,v 1.16 1999-06-20 21:19:37 billf Exp $
|
|
-->
|
|
|
|
<chapter id="security">
|
|
<title>Security</title>
|
|
|
|
<sect1 id="crypt">
|
|
<title>DES, MD5, and Crypt</title>
|
|
|
|
<para><emphasis>Contributed by &a.wollman; 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 “one-way hash
|
|
function”. 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&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>$1$</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>$</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>ls -l /usr/lib/libcrypt*</userinput>
|
|
lrwxr-xr-x 1 root wheel 13 Mar 19 06:56 libcrypt.a -> libdescrypt.a
|
|
lrwxr-xr-x 1 root wheel 18 Mar 19 06:56 libcrypt.so.2.0 -> libdescrypt.so.2.0
|
|
lrwxr-xr-x 1 root wheel 15 Mar 19 06:56 libcrypt_p.a -> 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">
|
|
<!--
|
|
Copyright 1995 Massachusetts Institute of Technology
|
|
|
|
Permission to use, copy, modify, and distribute this software and
|
|
its documentation for any purpose and without fee is hereby
|
|
granted, provided that both the above copyright notice and this
|
|
permission notice appear in all copies, that both the above
|
|
copyright notice and this permission notice appear in all
|
|
supporting documentation, and that the name of M.I.T. not be used
|
|
in advertising or publicity pertaining to distribution of the
|
|
software without specific, written prior permission. M.I.T. makes
|
|
no representations about the suitability of this software for any
|
|
purpose. It is provided "as is" without express or implied
|
|
warranty.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
|
|
ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
|
|
SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
|
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
SUCH DAMAGE.
|
|
-->
|
|
|
|
<title>S/Key</title>
|
|
|
|
<para><emphasis>Contributed by &a.wollman; 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 “UNIX password”. 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 “one-time password”. 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 “secret
|
|
password” or just unqualified “password”.</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 “seed” or (confusingly)
|
|
“key”, and consists of two letters and five digits, and the
|
|
other is the “iteration count” 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
|
|
…
|
|
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
|
|
&man.skey.access.5; 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
|
|
“key distribution centre”. 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>
|
|
|
|
<Not found>, <prompt>Create [y] ?</prompt> <userinput>y</userinput>
|
|
|
|
Principal: passwd, Instance: grunt, kdc_key_ver: 1
|
|
<prompt>New Password:</prompt> <---- enter RANDOM here
|
|
Verifying password
|
|
|
|
<prompt>New Password:</prompt> <---- 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>
|
|
|
|
<Not found>, <prompt>Create [y] ?</prompt>
|
|
|
|
Principal: rcmd, Instance: grunt, kdc_key_ver: 1
|
|
<prompt>New Password:</prompt> <---- enter RANDOM here
|
|
Verifying password
|
|
|
|
<prompt>New Password:</prompt> <---- 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> <---- 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>
|
|
|
|
<Not found>, <prompt>Create [y] ?</prompt> <userinput>y</userinput>
|
|
|
|
Principal: jane, Instance: , kdc_key_ver: 1
|
|
<prompt>New Password:</prompt> <---- enter a secure password here
|
|
Verifying password
|
|
|
|
<prompt>New Password:</prompt> <---- 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> <---- 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 &</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 &</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>
|
|
|
|
<Not found>, Create [y] ? y
|
|
|
|
Principal: jane, Instance: root, kdc_key_ver: 1
|
|
<prompt>New Password:</prompt> <---- enter a SECURE password here
|
|
Verifying password
|
|
|
|
<prompt>New Password:</prompt> <---- 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> <--- Keep this short!
|
|
<prompt>Attributes [ 0 ] ?</prompt>
|
|
Edit O.K.
|
|
<prompt>Principal name:</prompt> <---- 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><principal>.<instance></literal> of the form
|
|
<literal><username>.</literal><literal>root</literal> will allow
|
|
that <literal><username></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 “Big Bad Internet” 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 “rule
|
|
chain”.</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 “one-shot” password systems so that even if
|
|
someone manages to discover what password you used, they will not be
|
|
able to use it to gain access to your systems as the password
|
|
instantly expires. As they do not actually give users access to the
|
|
host machine, it becomes a lot more difficult for someone to install
|
|
backdoors around your security system.</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,
|
|
&man.ipfw.8;. 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
|
|
&man.syslogd.8;. 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
|
|
&man.syslogd.8; 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
|
|
&man.ipfw.8; 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 &man.ipfw.8; 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 “any IP
|
|
address”.</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>…</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 &man.traceroute.8;).</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
|
|
&man.ipfw.8; 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>You should enable your firewall from
|
|
<filename>/etc/rc.conf.local</filename> or
|
|
<filename>/etc/rc.conf</filename>. The associated manpage explains
|
|
which knobs to fiddle and lists some preset firewall configurations.
|
|
If you do not use a preset configuration, <command>ipfw list</command>
|
|
will output the current ruleset into a file that you can
|
|
pass to <filename>rc.conf</filename>. If you do not use
|
|
<filename>/etc/rc.conf.local</filename> or
|
|
<filename>/etc/rc.conf</filename> to enable your firewall,
|
|
it is important to make sure your firewall is enabled before
|
|
any IP interfaces are configured.
|
|
</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:
|
|
-->
|
|
|