<informalexample> <screen> ... </screen> </informalexample> need the <informalexample> element. So remove it. Simple search and replace does the trick.
1711 lines
66 KiB
Text
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
|
|
“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> 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 -> libdescrypt.a
|
|
lrwxr-xr-x 1 bin bin 18 Sep 5 12:50 libcrypt.so.2.0 -> libdescrypt.so.2.0
|
|
lrwxr-xr-x 1 bin bin 15 Sep 5 12:50 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">
|
|
<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 “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 <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 “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,
|
|
<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 “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
|
|
<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:
|
|
-->
|
|
|