SecurityDES, MD5, and CryptContributed by &a.wollman;24 September
1995.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.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 libcrypt because the name of
the C function to implement it is crypt. 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.Meanwhile, work was also underway on the DES-based password hash
function. First, a version of the crypt 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 libcrypt contains only the code involved in
performing the one-way password hash, and a separate libcipher 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.Recognizing your crypt
mechanismIt 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 $1$. 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 $ character, so a relatively short
string which doesn't begin with a dollar sign is very likely a DES
password.Determining which library is being used on your system is
fairly easy for most programs, except for those like init 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 crypt are linked against libcrypt, which for each type of library is
a symbolic link to the appropriate implementation. For example,
on a system using the DES versions:&prompt.user; cd /usr/lib
&prompt.user; ls -l /usr/lib/libcrypt*
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.aOn a system using the MD5-based libraries, the same links will
be present, but the target will be libscrypt
rather than libdescrypt.S/KeyContributed by &a.wollman;25 September
1995.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.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
key program and accepted by the
keyinit 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 key program (and sometimes the keyinit program) which it uses to generate
one-time passwords; we will call it a “secret password” or just
unqualified “password”.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.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 login and su 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.)There are four programs involved in the S/Key system which we
will discuss below. The key program
accepts an iteration count, a seed, and a secret password, and
generates a one-time password. The keyinit 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 keyinfo program
examines the /etc/skeykeys file and prints out
the invoking user's current iteration count and seed. Finally, the
login and su programs contain the necessary logic to
accept S/Key one-time passwords for authentication. The login program is also capable of disallowing
the use of UNIX passwords on connections coming from specified
addresses.There are four different sorts of operations we will cover. The
first is using the keyinit 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
keyinit program over an insecure
connection, in conjunction with the key program over a secure connection, to do
the same. The third is using the key program to log in over an insecure
connection. The fourth is using the key 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).Secure connection initializationTo 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 keyinit
command without any parameters while logged in as yourself:&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.
Enter secret password: ) I typed my pass phrase here
Again secret password: ) I typed it again ID
wollman s/key is 99 ha73896 ) discussed below SAG
HAS FONT GOUT FATE BOOM )There is a lot of information here. At theEnter secret
password: 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.Insecure connection initializationTo 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 key 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
keyinit -s command:&prompt.user; keyinit -s
Updating wollman: Old key: kh94741
Reminder you need the 6 English words from the skey command.
Enter sequence count from 1 to 9999:100 ) I typed this
Enter new key [default kh94742]:
s/key 100 kh94742To accept the default seed (which the keyinit program
confusingly calls a key), press return. Then move over to your
secure connection or S/Key desk accessory, and give it the same
parameters:&prompt.user; key 100 kh94742
Reminder - Do not use this program while logged in via telnet or rlogin.
Enter secret password: ) I typed my secret password
HULL NAY YANG TREE TOUT VETONow switch back over to the insecure connection, and copy the
one-time password generated by key
over to the keyinit
program:s/key access password:HULL NAY YANG TREE TOUT VETO
ID wollman s/key is 100 kh94742
HULL NAY YANG TREE TOUT VETOThe rest of the description from the previous section applies
here as well.Diversion: a login promptBefore explaining how to generate one-time passwords, we
should go over an S/Key login prompt:&prompt.user; telnet himalia
Trying 18.26.0.186...
Connected to himalia.lcs.mit.edu.
Escape character is '^]'.
s/key 92 hi52030
Password: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.If this machine were configured to disallow UNIX passwords
over a connection from my machine, the prompt would have also
included the annotation (s/key
required), indicating that only S/Key one-time
passwords will be accepted.Generating a single one-time passwordNow, to generate the one-time password needed to answer this
login prompt, we use a trusted machine and the key program. (There are versions of the
key program from DOS and Windows
machines, and there is an S/Key desk accessory for Macintosh
computers as well.) The command-line key program takes as its parameters the
iteration count and seed; you can cut-and-paste right from the
login prompt starting at key to
the end of the line. Thus:&prompt.user; key 92 hi52030 ) pasted from previous section
Reminder - Do not use this program while logged in via telnet or rlogin.
Enter secret password: ) I typed my secret password
ADEN BED WOLF HAW HOT STUNAnd in the other window:s/key 92 hi52030 ) from previous section
Password:
(turning echo on)
Password:ADEN BED WOLF HAW HOT STUN
Last login: Wed Jun 28 15:31:00 from halloran-eldar.l
[etc.]This is the easiest mechanism if you have
a trusted machine. There is a Java S/Key key applet, The Java OTP
Calculator, that you can download and run locally on any
Java supporting brower.Generating multiple one-time passwordsSometimes we have to go places where no trusted machines or
connections are available. In this case, it is possible to use
the key command to generate a
number of one-time passwords in the same command; these can then
be printed out. For example:&prompt.user; key -n 25 57 zz99999
Reminder - Do not use this program while logged in via telnet or rlogin.
Enter secret password:
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 BALMThe requests twenty-five keys in
sequence; the indicates the
ending iteration number; and the rest is as
before. Note that these are printed out in
reverse 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 lpr. 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.Restricting use of UNIX passwordsThe configuration file /etc/skey.access
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 skey.access5 manual page; there are
also some security cautions there which should be read before
depending on this file for security.If there is no /etc/skey.access 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 skey.access file. In all cases, UNIX
passwords are permitted on the console.Here is a sample configuration file which illustrates the
three most common sorts of configuration statements:
permit internet 18.26.0.0 255.255.0.0
permit user jrl
permit port ttyd0The first line (permit
internet) 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.The second line (permit user)
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 key
program, like those with dumb terminals, or those who are
uneducable.The third line (permit port)
allows all users logging in on the specified terminal line to use
UNIX passwords; this would be used for dial-ups.KerberosContributed by &a.markm; (based on contribution by
&a.md;).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.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.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.For those needing to get a legal foreign distribution of this
software, please do not get it from a USA or
Canada site. You will get that site in big
trouble! A legal copy of this is available from
ftp.internat.freebsd.org, which is in
South Africa and an official FreeBSD mirror site.Creating the initial databaseThis 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 /etc/kerberosIV and
check that only the following files are present:&prompt.root; cd /etc/kerberosIV
&prompt.root; ls
README krb.conf krb.realmsIf any additional files (such as
principal.* or master_key)
exist, then use the kdb_destroy command to
destroy the old Kerberos database, of if Kerberos is not running,
simply delete the extra files.You should now edit the krb.conf and
krb.realms files to define your Kerberos
realm. In this case the realm will be
GRONDAR.ZA and the server is
grunt.grondar.za. We edit or create the
krb.conf file:&prompt.root; cat krb.conf
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.govIn 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.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 admin server
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.Now we have to add grunt.grondar.za to
the GRONDAR.ZA realm and also add an entry to
put all hosts in the .grondar.za domain in
the GRONDAR.ZA realm. The
krb.realms file would be updated as
follows:&prompt.root; cat krb.realms
grunt.grondar.za GRONDAR.ZA
.grondar.za GRONDAR.ZA
.berkeley.edu CS.BERKELEY.EDU
.MIT.EDU ATHENA.MIT.EDU
.mit.edu ATHENA.MIT.EDUAgain, 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.The first line puts the specific
system into the named realm. The rest of the lines show how to
default systems of a particular subdomain to a named realm.Now we are ready to create the database. This only needs to
run on the Kerberos server (or Key Distribution Centre). Issue the
kdb_init command to do this:&prompt.root; kdb_initRealm name [default ATHENA.MIT.EDU ]:GRONDAR.ZA
You will be prompted for the database Master Password.
It is important that you NOT FORGET this password.
Enter Kerberos master key:Now we have to save the key so that servers on the local
machine can pick it up. Use the kstash command to do this.&prompt.root; kstashEnter Kerberos master key:
Current Kerberos master key version is 1.
Master key entered. BEWARE!This saves the encrypted master password in
/etc/kerberosIV/master_key.Making it all runTwo principals need to be added to the database for each system that will be secured with
Kerberos. Their names are kpasswd
and rcmd These two principals are
made for each system, with the instance being the name of the
individual system.These daemons, kpasswd and
rcmd allow other systems to change
Kerberos passwords and run commands like rcp, rlogin
and rsh.Now let's add these entries:&prompt.root; kdb_edit
Opening database...
Enter Kerberos master key:
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.
Principal name:passwdInstance:grunt
<Not found>, Create [y] ?y
Principal: passwd, Instance: grunt, kdc_key_ver: 1
New Password: <---- enter RANDOM here
Verifying password
New Password: <---- enter RANDOM here
Random password [y] ?y
Principal's new key version = 1
Expiration date (enter yyyy-mm-dd) [ 2000-01-01 ] ?Max ticket lifetime (*5 minutes) [ 255 ] ?Attributes [ 0 ] ?
Edit O.K.
Principal name:rcmdInstance:grunt
<Not found>, Create [y] ?
Principal: rcmd, Instance: grunt, kdc_key_ver: 1
New Password: <---- enter RANDOM here
Verifying password
New Password: <---- enter RANDOM here
Random password [y] ?
Principal's new key version = 1
Expiration date (enter yyyy-mm-dd) [ 2000-01-01 ] ?Max ticket lifetime (*5 minutes) [ 255 ] ?Attributes [ 0 ] ?
Edit O.K.
Principal name: <---- null entry here will cause an exitCreating the server fileWe now have to extract all the instances which define the
services on each machine. For this we use the
ext_srvtab command. This will create a file which
must be copied or moved by secure
means 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.&prompt.root; ext_srvtab gruntEnter Kerberos master key:
Current Kerberos master key version is 1.
Master key entered. BEWARE!
Generating 'grunt-new-srvtab'....Now, this command only generates a temporary file which must
be renamed to srvtab so that all the
server can pick it up. Use the mv
command to move it into place on the original system:&prompt.root; mv grunt-new-srvtab srvtabIf the file is for a client system, and the network is not
deemed safe, then copy the client-new-srvtab to removable media
and transport it by secure physical means. Be sure to rename it to
srvtab in the client's
/etc/kerberosIV directory, and make sure it
is mode 600:&prompt.root; mv grumble-new-srvtab srvtab
&prompt.root; chmod 600 srvtabPopulating the databaseWe now have to add some user entries into the database. First
let's create an entry for the user jane. Use
the kdb_edit command to do this:&prompt.root; kdb_edit
Opening database...
Enter Kerberos master key:
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.
Principal name:janeInstance:
<Not found>, Create [y] ?y
Principal: jane, Instance: , kdc_key_ver: 1
New Password: <---- enter a secure password here
Verifying password
New Password: <---- re-enter the password here
Principal's new key version = 1
Expiration date (enter yyyy-mm-dd) [ 2000-01-01 ] ?Max ticket lifetime (*5 minutes) [ 255 ] ?Attributes [ 0 ] ?
Edit O.K.
Principal name: <---- null entry here will cause an exitTesting it all outFirst we have to start the Kerberos daemons. NOTE that if you
have correctly edited your /etc/rc.conf 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
/etc/kerberosIV directory.&prompt.root; kerberos &
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; kadmind -n &
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!Now we can try using the kinit
command to get a ticket for the id jane that we created above:&prompt.user; kinit jane
MIT Project Athena (grunt.grondar.za)
Kerberos Initialization for "jane"
Password:Try listing the tokens using klist to see if we really have them:&prompt.user; klist
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.ZANow try changing the password using passwd to check if the kpasswd daemon can
get authorization to the Kerberos database:&prompt.user; passwd
realm GRONDAR.ZA
Old password for jane:New Password for jane:
Verifying password
New Password for jane:
Password changed.Adding su privilegesKerberos allows us to give each
user who needs root privileges their own separatesupassword. We could now add an id which is
authorized to su to root. This is controlled by having an
instance of root associated with a
principal. Using kdb_edit we can create the
entry jane.root in the Kerberos
database:&prompt.root; kdb_edit
Opening database...
Enter Kerberos master key:
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.
Principal name:janeInstance:root
<Not found>, Create [y] ? y
Principal: jane, Instance: root, kdc_key_ver: 1
New Password: <---- enter a SECURE password here
Verifying password
New Password: <---- re-enter the password here
Principal's new key version = 1
Expiration date (enter yyyy-mm-dd) [ 2000-01-01 ] ?Max ticket lifetime (*5 minutes) [ 255 ] ?12 <--- Keep this short!
Attributes [ 0 ] ?
Edit O.K.
Principal name: <---- null entry here will cause an exitNow try getting tokens for it to make sure it works:&prompt.root; kinit jane.root
MIT Project Athena (grunt.grondar.za)
Kerberos Initialization for "jane.root"
Password:Now we need to add the user to root's
.klogin file:&prompt.root; cat /root/.klogin
jane.root@GRONDAR.ZANow try doing the su:&prompt.user; suPassword:and take a look at what tokens we have:&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.ZAUsing other commandsIn an earlier example, we created a principal called
jane with an instance root. This was based on a user with the same
name as the principal, and this is a Kerberos default; that a
<principal>.<instance> of the
form <username>.root will allow that
<username> to su to root if the necessary entries are in
the .klogin file in root's home directory:&prompt.root; cat /root/.klogin
jane.root@GRONDAR.ZALikewise, if a user has in their own home directory lines of
the form:&prompt.user; cat ~/.klogin
jane@GRONDAR.ZA
jack@GRONDAR.ZAThis allows anyone in the GRONDAR.ZA
realm who has authenticated themselves to
jane or jack (via
kinit, see above) access to
rlogin to
jane's account or files on this system
(grunt) via rlogin, rsh or
rcp.For example, Jane now logs into another system, using
Kerberos:&prompt.user; kinit
MIT Project Athena (grunt.grondar.za)
Password:
%prompt.user; rlogin grunt
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 1995Or Jack logs into Jane's account on the same machine (Jane
having set up the .klogin file as above, and
the person in charge of Kerberos having set up principal
jack with a null instance:&prompt.user; kinit
&prompt.user; rlogin grunt -l jane
MIT Project Athena (grunt.grondar.za)
Password:
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 1995FirewallsContributed by &a.gpalmer; and
&a.alex;.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.People often think that having a firewall between your
companies internal network and the “Big Bad Internet”
will solve all your security problems.It may help, but a poorly setup firewall system is more of a
security risk than not having one at all. A firewall can only add
another layer of security to your systems, but they will not be
able to stop a really determined 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.What is a firewall?There are currently two distinct types of firewalls in common
use on the Internet today. The first type is more properly called
a packet filtering router, 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
proxy servers, rely on daemons to
provide authentication and to forward packets, possibly on a
multi-homed machine which has kernel packet forwarding
disabled.Sometimes sites combine the two types of firewalls, so that
only a certain machine (known as a bastion
host) 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.FreeBSD comes with a kernel packet filter (known as
IPFW), 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.Packet filtering routersA 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.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”.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).Proxy serversProxy servers are machines which have had the normal system
daemons (telnetd, ftpd, etc) replaced with special servers.
These servers are called proxy
servers 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).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.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.What does IPFW allow me to do?IPFW, the software supplied with FreeBSD,
is a packet filtering and accounting system which resides in the
kernel, and has a user-land control utility,
ipfw8. Together, they allow you to define and
query the rules currently used by the kernel in its routing
decisions.There are two related parts to IPFW. 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.As a result of the way that IPFW is
designed, you can use IPFW on non-router
machines to perform packet filtering on incoming and outgoing
connections. This is a special case of the more general use of
IPFW, and the same commands and techniques
should be used in this situation.Enabling IPFW on FreeBSDAs the main part of the IPFW 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
reconfiguring the kernel for
more details on how to recompile your kernel.There are currently three kernel configuration options
relevant to IPFW:options IPFIREWALLCompiles into the kernel the code for packet
filtering.options IPFIREWALL_VERBOSEEnables code to allow logging of packets through
syslogd8. Without this option, even
if you specify that packets should be logged in the filter
rules, nothing will happen.options IPFIREWALL_VERBOSE_LIMIT=10Limits the number of packets logged through
syslogd8 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.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 ipfw8
utility:&prompt.root; ipfw zero 4500Where 4500 is the chain entry you wish to continue
logging.Previous versions of FreeBSD contained an
IPFIREWALL_ACCT option. This is now obsolete as
the firewall code automatically includes accounting
facilities.Configuring IPFWThe configuration of the IPFW software is
done through the ipfw8 utility. The syntax
for this command looks quite complicated, but it is relatively
simple once you understand its structure.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.Altering the IPFW rulesThe syntax for this form of the command is:
ipfw-NcommandindexactionlogprotocoladdressesoptionsThere is one valid flag when using this form of the
command:-NResolve addresses and service names in
output.The command given can be shortened to
the shortest unique form. The valid
commands are:addAdd an entry to the firewall/accounting rule
listdeleteDelete an entry from the firewall/accounting rule
listPrevious versions of IPFW used separate
firewall and accounting entries. The present version provides
packet accounting with each firewall entry.If an index 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).The log option causes matching
rules to be output to the system console if the kernel was
compiled with IPFIREWALL_VERBOSE.Valid actions are:rejectDrop the packet, and send an ICMP host or port
unreachable (as appropriate) packet to the
source.allowPass the packet on as normal. (aliases:
pass and accept)denyDrop the packet. The source is not notified via an
ICMP message (thus it appears that the packet never
arrived at the destination).countUpdate packet counters but do not allow/deny the
packet based on this rule. The search continues with
the next chain entry.Each action will be recognized by the
shortest unambiguous prefix.The protocols which can be specified
are:allMatches any IP packeticmpMatches ICMP packetstcpMatches TCP packetsudpMatches UDP packetsThe address specification is:fromaddress/maskporttoaddress/markportvia interfaceYou can only specify port in
conjunction with protocols which support
ports (UDP and TCP).The is optional and may
specify the IP address or domain name of a local IP interface,
or an interface name (e.g. ed0) to
match only packets coming through this interface. Interface unit
numbers can be specified with an optional wildcard. For example,
ppp* would match all kernel PPP
interfaces.The syntax used to specify an
address/mask is:
address
or
address/mask-bits
or
address:mask-patternA valid hostname may be specified in place of the IP
address. is a decimal
number representing how many bits in the address mask should be
set. e.g. specifying 192.216.222.1/24 will create a mask which will allow any
address in a class C subnet (in this case, 192.216.222) to be
matched. is an IP
address which will be logically AND'ed with the address given.
The keyword any may be used to
specify “any IP address”.The port numbers to be blocked are specified as:
port,port,port…to specify either a single port or a list of
ports, or
port-port to specify a range of ports. You may also
combine a single range with a list, but the range must always be
specified first.The options available are:fragMatches if the packet is not the first fragment of
the datagram.inMatches if the packet is on the way in.outMatches if the packet is on the way out.ipoptions specMatches if the IP header contains the comma
separated list of options specified in
spec. The supported list of IP
options are: ssrr (strict
source route), lsrr (loose
source route), rr (record
packet route), and ts
(timestamp). The absence of a particular option may be
denoted with a leading !.establishedMatches 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 established
rules early in the chain.setupMatches if the packet is an attempt to establish a
TCP connection (the SYN bit set is set but the ACK bit
is not).tcpflags flagsMatches if the TCP header contains the comma
separated list of flags. The
supported flags are fin,
syn, rst,
psh, ack, and
urg. The absence of a particular
flag may be indicated by a leading !.icmptypes typesMatches if the ICMP type is present in the list
types. The list may be specified
as any combination of ranges and/or individual types
separated by commas. Commonly used ICMP types are:
0 echo reply (ping reply),
3 destination unreachable,
5 redirect, 8 echo request (ping request), and
11 time exceeded (used to
indicate TTL expiration as with
traceroute8).Listing the IPFW rulesThe syntax for this form of the command is:
ipfw-a-t-NlThere are three valid flags when using this form of the
command:-aWhile listing, show counter values. This option is
the only way to see accounting counters.-tDisplay the last match times for each chain entry.
The time listing is incompatible with the input syntax
used by the ipfw8 utility.-NAttempt to resolve given addresses and service
names.Flushing the IPFW rulesThe syntax for flushing the chain is:
ipfwflushThis 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.Clearing the IPFW packet countersThe syntax for clearing one or more packet counters is:
ipfwzeroindexWhen used without an index argument,
all packet counters are cleared. If an
index is supplied, the clearing operation
only affects a specific chain entry.Example commands for ipfwThis command will deny all packets from the host
evil.crackers.org to the telnet port of the
host nice.people.org by being forwarded by
the router:&prompt.root ipfw add deny tcp from evil.crackers.org to nice.people.org 23The next example denies and logs any TCP traffic from the
entire crackers.org network (a class C) to the
nice.people.org machine (any port).&prompt.root; ipfw add deny log tcp from evil.crackers.org/24 to nice.people.orgIf 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:&prompt.root; ipfw add deny tcp from any to my.org/28 6000 setupTo see the accounting records:
&prompt.root; ipfw -a list
or in the short form
&prompt.root; ipfw -a lYou can also see the last time a chain entry
was matched with:&prompt.root; ipfw -at lBuilding a packet filtering firewallThe 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.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.If you use the logging versions of the accept command, it can generate
large 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
/var/log is located on.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 /etc/netstart
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.The actual script used to load the rules is entirely up to
you. There is currently no support in the ipfw utility for loading multiple rules in
the one command. The system I use is to use the command:&prompt.root; ipfw listto write a list of the current rules out to a file, and then
use a text editor to prepend ipfw
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.The next problem is what your firewall should actually
do! 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: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.Block all 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.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 xhost + 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.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.Another checklist for firewall configuration is available from
CERT at ftp://ftp.cert.org/pub/tech_tips/packet_filteringAs I said above, these are only
guidelines. 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.