How to Build a FreeBSD-STABLE Firewall with IPFILTER
Applicable to: FreeBSD 4.3
Updated: July 5, 2001
Author: Marty
Schlacter
Source URL: http://www.schlacter.dyndns.org/public/FreeBSD-STABLE_and_IPFILTER.html
http://www.schlacter.dyndns.org/public/FreeBSD-STABLE_and_IPFILTER.pdf
If you have any suggested changes or corrections to this document, please e-mail me with those changes/corrections.
This howto walks
you through the process of building one of the most stable and secure firewalls
available - a FreeBSD-STABLE firewall with IPFILTER. As a part of the
installation process, all services will be disabled except OpenSSH, which will
have its access controlled via TCP-Wrappers. The firewall will be configured to
log through the syslog facility, but will have its own firewall log files
(rather than filling up /var/log/messages). We'll add VESA support into the
kernel so that we can use 132x43 screen resolutions, as well as compile support
into the kernel for a second ISA Ethernet card if you have one. After we add a
warning banner to the system, we'll make BASH the default shell for root,
perform a rudimentary setup for root's BASH environment, and redirect root's
email to your "normal" account so that the root account on the firewall itself
doesn't fill up. Next, we'll download, compile, install, and configure Tripwire,
as well as install cvsup so that your ports collection stays up to date. And,
lastly, we'll modify the /etc/fstab entries so that some of your partitions are
mounted 'nosuid', 'noexec', or 'ro' so that your installation is as secure as
possible.
This is an all-encompassing how-to, and should take 1/2 of a Saturday to
complete, but when you're finished, you'll not only have a great firewall, but
will be better able to compare and contrast FreeBSD/IPFILTER to
Linux2.4/IPTABLES so that you can consider the pros/cons of each on their
merits...and that learning process is what all of this about anyway. So, grab a
cup of coffee, sit down with that old Pentium, and get ready to broaden your
horizons.
Before we start, I'd like to thank Dan O'Connor for the work he put in on his
great site, FreeBSD Cheat Sheets, since
it was his great site that gave me the motivation to start this howto. You will
undoubtedly see some of his tips and tricks sprinkled throughout this document.
For those of you that are new to FreeBSD, I highly
recommend his site.
In addition, there have been several other people on the Internet who have
given me great suggestions & and feedback on this HOWTO. The majority (if
not all) of their comments have been incporporated into this document in some
form or another. There are too many to list here by name, but (rest assured) the
Open Source community has helped to make this the best document it can be.
And, as always, before performing this procedure, I highly recommend that you
review the Installing FreeBSD
chapter of the FreeBSD Handbook.
Network Schematic & System
Configuration The intent of this document is to show you how to build a firewall for your
home network. Just to make sure that we're "working off the same sheet of music"
here's a quick ASCII-schematic of what our notional home network will look like
- to include device names for the Ethernet interfaces. In addition, I'm
including a quick synopsis of the configuration of my own hardware - so that you
can use it as a reference point throughout this procedure.
Installing FreeBSD-STABLE To build the most stable and security-patched system you can, you'll want to
make sure you're running the latest version of FreeBSD-STABLE. When I built my
last system, the April 28, 2001 version of FreeBSD 4.3-STABLE was the latest
version released. For those of you new to FreeBSD, the STABLE branch is the
version of the operating system that has all of the latest patches, bugfixes,
and enhancements after the previous release was made. If you've installed
FreeBSD-4.3 from CD-ROM (either one that your purchased or 'burned' from a
downloaded ISO image), you probably installed 4.3-RELEASE, which is
(simplistically) nothing more than a version of the 4.3 branch that was
exhaustively tested, burned to CD-ROM and made available for sale. After
the release date of 4.3-RELEASE (on April 20, 2001), the 4.3 tree continued to
evolve & be patched (for security reasons) after that point. Since
there's no way the folks at FreeBSD.org can burn & sell CD-ROMs for each
day's version of the 4.3 tree, 4.3-RELEASE is the only one made available for
sale on CD, and subsequent snapshots of the 4.3 tree are only available on-line
and are labelled '4.3-STABLE'. Once 4.3-STABLE is sufficiently enhanced/patched
(perhaps 4 months later), the code enters a freeze and will officially become
the 'RELEASE' version of the next FreeBSD release. If you're installing FreeBSD
4.3 well after the release date, you will definitely want to install 4.3-STABLE,
not 4.3-RELEASE.
So, what are the benefits of loading 4.3-STABLE rather than 4.3-RELEASE?
Well, the biggest answer (if you're building a firewall, like we are here) is
that all of the security patches have been applied to the O/S and the associated
applications. To use the prior baseline of FreeBSD (4.2) as an example,
FreeBSD-4.2-RELEASE (which was released in November 2000) uses OpenSSH-2.2.0,
which is a great product but also has a remote buffer overflow that wasn't
discovered until early February, 2001. If a hacker exploited this
vulnerability on your 4.2-RELEASE box, they would gain remote root access and
ruin your day. The relevant info on this vulnerability can be found on SecurityFocus'
website. When you loaded FreeBSD-4.2-STABLE (if you were following this
HOWTO in mid-March of 2001), by comparison, you would have gotten
FreeBSD-4.2-RELEASE with all of the patches applied after the November 2000
release...so your system would have OpenSSH-2.3.0 (not OpenSSH-2.2.0) which is
not vulnerable to the remote buffer overflow. So loading the latest
snapshot from the STABLE branch saves you a lot of time associated with loading
security-related patches after your OS load is finished.
Note: If you have PCI-based Ethernet cards, you can delete all of the
network cards in the list - yours will be found and configured
automatically. If you're on the other end of the scale (like me) and you
have two old NE2000-compliant ISA network cards, you'll only be able to
configure one of them at this time (ed0). After your installation is
complete, you'll have to build a custom kernel & add in a "placeholder"
for the 2nd generic ISA card, and then run through the kernel configuration
utility again after you reboot. We'll do this at the end of this document. Hit 'Q' then 'Y' to save your changes and exit. (System Installs...If releng4.freebsd.org isn't heavily loaded, the
install can take as little as 22 minutes (with a cable modem). If
releng4.freebsd.org is heavily loaded, the install can take as long as 2
hours...or longer...) Then tab over and select "Install", select "OK" to confirm your choices
(Packages are installed...takes about 60 seconds) Then select Exit and return to the previous menu, and then tab over and
select "Exit Install" (System reboots...) Compiling IPFILTER into the Kernel, & Configuring the
System Now that you have FreeBSD-STABLE installed on the system, we need to spend
about 2-3 hours adding in IPFILTER support as well as finishing the rest of the
configuration. Here's what we're going to do in this section (in no
particular order):
In order to save time, I'm going to do some steps in what will appear to be
an "out of order" sequence. This is being done on purpose so that we will
minimize the number of re-boots you'll have to do. In fact, the goal is to
configure the system, then recompile the kernel, and when the system reboots,
you're done. That's it.
Source URL: http://www.schlacter.dyndns.org/public/FreeBSD-STABLE_and_IPFILTER.html
Notional Network Schematic Machine Configuration
-------------------------- ---------------------
ISP / Internet - 200MHz Pentium-MMX (overclocked to 225MHz)
(UNTRUSTED) - 96MB EDO RAM
| - 4GB UDMA/33 hard drive
| - 2-button serial mouse
--------- - S3 Virge/DX (4MB)
| Cable | - NE2000-compatible ISA Ethernet card (generic)
| Modem | - no CD-ROM drive
---------
|
|
ed0 |
---------------
| xx.xx.xx.xx |
| |
| FreeBSD |
| Firewall |
| |
| 192.168.1.1 |
---------------
ed1 |
|
|
-----------
| 10BaseT |
| Hub |
-----------
| | | | |
| | | | |
Internal Network
(TRUSTED)
[root@yoursys /tmp]# dd
if=/tmp/kern.flp of=/dev/fd0
2880+1 records in
2880+0 records
out
1474560 bytes transferred in 49.931306 secs (30135 bytes/sec)
C:\WINDOWS\TEMP>rawrite
RaWrite 1.3 - Write disk file to raw
floppy diskette
Enter source file name: mfsroot.flp
Enter
destination drive: a:
Please insert a formatted diskette into drive A:
and press -ENTER- :
Number of sectors per track for this disk is
18
Writing image to drive A:. Press ^C to abort.
Track: 79 Head: 1
Sector: 16
Done.
Storage:
ATA/ATAPI compatible
disk controller
ata0
14
0x1f0
ATA/ATAPI compatible
disk controller
ata1
15
0x170
Floppy disk
controller
fdc0
6
0x3f0
Networks:
NE1000,NE2000,3C503,WD/SMC80xx Ethernet
adapters
ed0
10
0x280
Communications:
Parallel Port
chipset
ppc0
7
8250/16450/16550
Serial port
sio0
4
0x3f8
8250/16450/16550
Serial port
sio1
3
0x2f8
Input:
Keyboard
atkbd0
1
Syscons console
driver
sc0
Multimedia:
Miscellaneous:
Math
coprocessor
npx0
13
0xf0
256MB swap partition (or at least 2x
your RAM)
Here's a partition scheme if
you only have one of those old 1.1 GB drives. I haven't tried to install it on
a drive this small, but based on the partition usage after you've completed
this HOWTO, these numbers look about right. The only thing that might make it
not work is if a whole bunch of temp files are created during the kernel
compilation process (which would subsequently fill up /tmp and cause the
compile to abort, etc.). So, 'caveat emptor' on the 1.1 GB configuration. If
you're able to make it work on a drive this small, please email
me & I'll update the HOWTO.
128MB file system mounted as /
512MB file system mounted
as /tmp
512MB file system mounted as /var
1,000MB file system
mounted as /usr
640MB file system mounted as /usr/local
1,000MB file
system mounted as /usr/home 128MB swap partition
128MB file
system mounted as /
64MB file system mounted as /tmp
64MB file
system mounted as /var
640MB file system mounted as /usr
64MB file
system mounted as /usr/local
32MB file system mounted as /usr/home
Type: Auto
Port: COM1
Flags:
-3 WWW - lynx-2.8.3.1
Mail -
mutt-1.2.5
Net - cvsup-bin-16.1
Shells - bash-2.0.5
Networking:
-
Disable "inetd - This machine wants to run the inet daemon"
- Enable "ntpdate - Select a clock-synchronization server"
- Disable "portmap - This machine wants to run the
portmapper daemon"
- Disable "sendmail - This machine
wants to run the sendmail daemon"
umask 077
PS1="[\u@\h \W]\\$ "
alias ls='ls -alFG' PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin:$HOME/bin;
export PATH
umask 077
PS1="[\u@\h \W]\\$ "
alias ls='ls -alFG'
THIS SYSTEM IS RESTRICTED TO AUTHORIZED USERS FOR AUTHORIZED
USE
ONLY. UNAUTHORIZED ACCESS IS STRICTLY PROHIBITED AND MAY BE
PUNISHABLE UNDER THE COMPUTER FRAUD AND ABUSE ACT OF 1986 OR
OTHER
APPLICABLE LAWS. IF NOT AUTHORIZED TO ACCESS THIS SYSTEM,
DISCONNECT NOW.
BY CONTINUING, YOU CONSENT TO YOUR KEYSTROKES
AND DATA CONTENT BEING
MONITORED. ALL PERSONS ARE HEREBY
NOTIFIED THAT THE USE OF THIS SYSTEM
CONSTITUTES CONSENT TO
MONITORING AND AUDITING.
* * * * * * * * * *
* * W A R N I N G * * * * * * * * * * * * *
[root@numa /root]# cp /etc/motd /etc/issue
[root@numa /root]# cp
/usr/share/examples/cvsup/stable-supfile /etc
[root@numa /root]# vi
/etc/stable-supfile
[root@numa
/root]# cvsup /etc/stable-supfile - Change line 66 of the file so that it points cvsup to a
CVS server near you. I change mine to read '*default
host=cvsup2.FreeBSD.org'.
Section A.5.7. (CVSup Sites) of the FreeBSD
Handbook will tell you where the CVSup servers are.
- On line 71, modify the "tag" variable to correspond to
the specific release of the O/S that you want to track. The default
value of the tag in the
example file is "RELENG_4". This will download the source code for
the O/S which will has all of the security updates
as well as general bugfixes and feature enhancements. This is the
true "4.3-STABLE" release. If, however, you're in
a production environment and can't afford even the slightest risk of
feature enhancements causing problems with your production configuration,
there's a new value for this tag that was started with FreeBSD 4.3 that's
just for you. In this case, set the tag to "RELENG_4_3". This has
ONLY the security fixes...no feature enhancements. It's not exactly
the 4.3-STABLE branch, but does contain all of the security fixes
and maintains maximum stability for a production environment. 95% of
sysadmin's will leave the tag set to "RELENG_4" to track the true
"4.3-STABLE" baseline. It's your system...it's your call... The
official information about this recent change was disseminated via
the
FreeBSD Security Advisories mailing list on 11 May 2001 (message
subject, "Changes to FreeBSD security support policy").
- Add these lines at the bottom of the
file:
ports-www
tag=.
ports-mail
tag=.
ports-net
tag=.
ports-shells
tag=.
ports-security
tag=.
ports-sysutils tag=.
- ...and other
lines for ports collections you want... ftp stream tcp nowait
root /usr/libexec/ftpd ftpd
-l
telnet stream tcp nowait
root /usr/libexec/telnetd
telnetd
comsat dgram udp wait tty:tty
/usr/libexec/comsat
comsat
ntalk dgram udp wait tty:tty
/usr/libexec/ntalkd
ntalkd
ftp stream tcp6
nowait root /usr/libexec/ftpd ftpd
-l
telnet stream tcp6 nowait
root /usr/libexec/telnetd telnetd
# This is ssh server systemwide
configuration file.
#
# $FreeBSD: src/crypto/openssh/sshd_config,v
1.4.2.5 2001/01/18 22:36:53 green Exp $
Port 22
Protocol 2
#ListenAddress
0.0.0.0
#ListenAddress ::
HostKey
/etc/ssh/ssh_host_key *** Delete this line
***
HostDsaKey /etc/ssh/ssh_host_dsa_key
ServerKeyBits
768
LoginGraceTime 120
KeyRegenerationInterval
3600
PermitRootLogin no
# ConnectionsPerPeriod has been deprecated
completely
# After 10 unauthenticated connections, refuse 30% of
the new ones, and
# refuse any more than 60 total.
MaxStartups
10:30:60
# Don't read ~/.rhosts and ~/.shosts files
IgnoreRhosts
yes
# Uncomment if you don't trust ~/.ssh/known_hosts for
RhostsRSAAuthentication
#IgnoreUserKnownHosts yes
StrictModes
yes
X11Forwarding no
X11DisplayOffset
10
PrintMotd yes
KeepAlive yes
# Logging
SyslogFacility
AUTH
LogLevel DEBUG
#obsoletes
QuietMode and FascistLogging
RhostsAuthentication no
#
# For
this to work you will also need host keys in
/etc/ssh_known_hosts
RhostsRSAAuthentication
no
#
RSAAuthentication yes
# To disable tunneled clear text
passwords, change to no here!
PasswordAuthentication
no
PermitEmptyPasswords no
# Uncomment to disable s/key
passwords
#SkeyAuthentication no
#KbdInteractiveAuthentication
yes
# To change Kerberos options
#KerberosAuthentication
no
#KerberosOrLocalPasswd yes
#AFSTokenPassing
no
#KerberosTicketCleanup no
# Kerberos TGT Passing does only
work with the AFS kaserver
#KerberosTgtPassing yes
CheckMail
yes
#UseLogin no
# Uncomment if you want to enable
sftp
#Subsystem sftp /usr/libexec/sftp-server[root@numa /root]# su - testuser
*** substituted your
non-privileged userid for 'testuser'
[testuser@numa testuser]$
ssh-keygen -d *** then accept the default DSA key name &
enter a passphrase (twice)
[testuser@numa testuser]$ cd .ssh
[testuser@numa .ssh]$ cat id_dsa.pub > authorized_keys2
[root@numa root]# mkdir /mnt/floppy
*** This will make an empty mount point to mount the floppy to ***
When you're finished with the floppy, you'll need to unmount it and remove it:
[root@numa root]# mount -t msdos /dev/fd0 /mnt/floppy *** Insert a DOS-formatted floppy before you do this ***
[root@numa root]# cd /mnt/floppy
[root@numa floppy]# ls
*** Do whatever you need to at this point... ***
[root@numa floppy]# cd /root
*** Change directory "out" of the floppy mount point ***
[root@numa root]# umount /mnt/floppy
*** ...then eject the floppy ***
#
# hosts.allow access control
file for "tcp wrapped" applications.
#
ALL : localhost 127.0.0.1 :
allow
sshd : 192.168.1.0/255.255.255.0 : allow
ALL : ALL : deny
[root@numa /root]# cd
/usr/ports/devel/gmake
[root@numa gmake]# make && make install
[root@numa gmake]# cd
/root
[root@numa /root]# lynx http://prdownloads.sourceforge.net/tripwire
[root@numa /root]# tar zxvf
tripwire-2.3.1-2.tar.gz - Use the down-arrow to move through the hyperlinks until
the file, tripwire-2.3.1-2.tar.gz, is highlighted, then press
[Enter]
- When asked if you want to D)ownload the file, or C)ancel,
hit 'd'
- ...file downloads...
- After the file downloads,
you'll be presented with lynx's Download Options screen. The 'Save to
disk' hyperlink is automatically highlighted in red, so just hit
[Enter].
- Either accept the original filename by pressing [Enter],
or modify the filename then hit [Enter] to save it.
- After the
file is saved, press 'q' to quit lynx.
Note:
that in several of the following steps, I'll be referring to exact line
numbers in the files (some of which are a few hundred lines down). To
identify each line of a text file with a line number in vi, use the ":set
num" command after you've opened the file. The screen will refresh, and
you'll see all of the line numbers down the left side of the screen.
[root@numa /root]# cd
tripwire-2.3.1-2/src
[root@numa src]# vi Makefile
- Add a comment at the beginning of line 82 (SYSPRE =
i686-pc-linux)
- Remove the '#' comment delimeter at the beginning
of line 84 (SYSPRE = i386-unknown-freebsd)
- Save and exit.
[root@numa src]# gmake release
[root@numa src]# cd
../install/
[root@numa install]# vi install.cfg
- Change line 27 so that it reads
'TWBIN="/usr/local/sbin"'
- Change line 33 so that it reads
'TWMAN="/usr/share/man"'
- Change line 39 so that it reads
'TWDOCS="/usr/share/doc/tripwire"'
- Change line 51 so that it
reads 'TWEDITOR="/usr/bin/vi"'
- Change line 88 so that it reads
'TWMAILPROGRAM="/usr/sbin/sendmail -oi -t"'
- Save and exit.
[root@numa install]# vi
install.sh
- Change line 319 so that it reads
'EULA_PATH="../$TWLICENSEFILE"'
- Change line 491 so that it
reads 'BIN_DIR="../bin/i386-unknown-freebsd_r"'
- Change lines
621-638 so that they read as
follows:
f1=' ff=$README ; d="/.." ;
dd=$TWDOCS ; rr=0444 '
f2=' ff=$REL_NOTES
; d="/.." ; dd=$TWDOCS ; rr=0444 '
f3='
ff=$TWLICENSEFILE ; d="/.." ; dd=$TWDOCS ; rr=0444
'
f4=' ff=tripwire ;
d="/../bin/i386-unknown-freebsd_r" ; dd=$TWBIN ; rr=0550
'
f5=' ff=twadmin ;
d="/../bin/i386-unknown-freebsd_r" ; dd=$TWBIN ; rr=0550
'
f6=' ff=twprint ;
d="/../bin/i386-unknown-freebsd_r" ; dd=$TWBIN ; rr=0550
'
f7=' ff=siggen ;
d="/../bin/i386-unknown-freebsd_r" ; dd=$TWBIN ; rr=0550
'
f8=' ff=TRADEMARK ; d="/.." ;
dd=$TWDOCS ; rr=0444 '
f9='
ff=policyguide.txt ; d="/../policy" ; dd=$TWDOCS ; rr=0444
'
f10=' ff=twpol.txt ; d="/../policy" ;
dd=$TWPOLICY ; rr=0640 '
f11='
ff=twpolicy.4 ; d="/../man/man4" ; dd=$TWMAN/man4 ; rr=0444
'
f12=' ff=twconfig.4 ; d="/../man/man4"
; dd=$TWMAN/man4 ; rr=0444 '
f13='
ff=twfiles.5 ; d="/../man/man5" ; dd=$TWMAN/man5 ; rr=0444
'
f14=' ff=siggen.8 ; d="/../man/man8" ;
dd=$TWMAN/man8 ; rr=0444 '
f15='
ff=tripwire.8 ; d="/../man/man8" ; dd=$TWMAN/man8 ; rr=0444
'
f16=' ff=twadmin.8 ; d="/../man/man8" ;
dd=$TWMAN/man8 ; rr=0444 '
f17='
ff=twintro.8 ; d="/../man/man8" ; dd=$TWMAN/man8 ; rr=0444
'
f18=' ff=twprint.8 ; d="/../man/man8" ;
dd=$TWMAN/man8 ; rr=0444 '
- Save and exit.
[root@numa install]#
./install.sh
- Answer 'y' to continue with the installation
-
Press [Enter] to view the license agreement...when complete, type
'accept' and [Enter]
- The install script will verify that
sendmail and vi are installed, then verify that the tripwire
binaries are available, and then echo back all of the configuration
parameters for the installation script (e.g. TWBIN, TWMAN, etc.). If
everything looks good, answer 'y' to continue with the
installation.
- The install script copies all of the files, the
asks you to enter a new site keyfile passphrase. Enter it, and then
enter it again when asked to verify it.
- The install script then
asks you to enter a new local keyfile passphrase. Enter it, and then
enter it again when asked to verify it.
- The install script will
then create a signed configuration file, but will need you to enter
the site passphrase you just set, above. Enter it.
- The install
script will then create a signed policy file, but will need you to
enter the site passphrase you just set, above. Enter it.
-
...installation is complete.
@@section
GLOBAL
TWROOT="/usr/local";
TWBIN="/usr/local/sbin";
TWPOL="/etc/tripwire";
TWDB="/var/lib/tripwire";
TWSKEY="/etc/tripwire";
TWLKEY="/etc/tripwire";
TWREPORT="/var/lib/tripwire/report";
HOSTNAME=hostname.domain;
@@section
FS
SEC_CRIT = $(IgnoreNone)-SHa; # Critical files - we can't afford to
miss any changes.
SEC_SUID = $(IgnoreNone)-SHa; # Binaries with the
SUID or SGID flags set.
SEC_TCB = $(ReadOnly); # Members of the Trusted
Computing Base.
SEC_BIN = $(ReadOnly); # Binaries that shouldn't
change
SEC_CONFIG = $(Dynamic); # Config files that are changed
infrequently but accessed often.
SEC_LOG = $(Growing); # Files that
grow, but that should never change ownership.
SEC_INVARIANT = +pug; #
Directories that should never change permission or ownership.
SIG_LOW =
33; # Non-critical files that are of minimal security impact
SIG_MED =
66; # Non-critical files that are of significant security impact
SIG_HI
= 100; # Critical files that are significant points of
vulnerability
# Tripwire Binaries
(rulename = "Tripwire
Binaries", severity = $(SIG_HI))
{
$(TWBIN)/siggen ->
$(SEC_TCB);
$(TWBIN)/tripwire ->
$(SEC_TCB);
$(TWBIN)/twadmin ->
$(SEC_TCB);
$(TWBIN)/twprint ->
$(SEC_TCB);
}
# Tripwire Data Files - Configuration Files,
Policy Files, Keys, Reports, Databases
(rulename = "Tripwire Data
Files", severity = $(SIG_HI))
{
# NOTE: Removing the
inode attribute because when Tripwire creates a backup
# it
does so by renaming the old file and creating a new one (which
will
# have a new inode number). Leaving inode turned on
for keys, which shouldn't
# ever
change.
# NOTE: this rule will trigger on the first
integrity check after database
# initialization, and each
integrity check afterward until a database update
# is
run, since the database file will not exist before that
point.
$(TWDB) -> $(SEC_CONFIG)
-i;
$(TWPOL)/tw.pol -> $(SEC_BIN)
-i;
$(TWPOL)/tw.cfg -> $(SEC_BIN)
-i;
$(TWLKEY)/$(HOSTNAME)-local.key ->
$(SEC_BIN);
$(TWSKEY)/site.key ->
$(SEC_BIN);
#don't scan the individual
reports
$(TWREPORT) -> $(SEC_CONFIG) (recurse=0);
}
# These files are critical to a correct system
boot.
(rulename = "Critical system boot files", severity =
100)
{
/boot -> $(SEC_CRIT);
/kernel
-> $(SEC_CRIT);
}
# These files change the behavior of the
root account and also the authorized_keys2
# file for the user we
created earlier
(rulename = "Root config files", severity =
100)
{
/root ->
$(SEC_CRIT);
/root/.bash_history ->
$(SEC_LOG);
/root/.bash_profile ->
$(SEC_CRIT);
/root/.bashrc -> $(SEC_CRIT);
/home/username/.ssh/authorized_keys2 -> $(SEC_CRIT);
}
# Commonly accessed directories that should remain static
with regards to owner and group
(rulename = "Invariant Directories",
severity = $(SIG_MED))
{
/ -> $(SEC_INVARIANT)
(recurse = 0);
/etc -> $(SEC_INVARIANT) (recurse =
0);
/usr/local/etc -> $(SEC_INVARIANT) (recurse =
0);
}
(rulename = "Shell Binaries", severity =
$(SIG_HI))
{
/usr/local/bin/bash ->
$(SEC_BIN);
/bin/csh ->
$(SEC_BIN);
/bin/sh ->
$(SEC_BIN);
/bin/tcsh -> $(SEC_BIN);
}
# Rest
of critical system binaries
(rulename = "OS executables and libraries",
severity = $(SIG_HI))
{
/bin -> $(SEC_BIN) (recurse =
1);
/usr/bin -> $(SEC_BIN) (recurse =
1);
/usr/lib -> $(SEC_BIN) (recurse =
1);
/sbin -> $(SEC_BIN) (recurse =
1);
/usr/sbin -> $(SEC_BIN) (recurse = 1);
}
#
Local files
(rulename = "User executables and libraries", severity =
$(SIG_MED))
{
/usr/local/bin -> $(SEC_BIN) (recurse =
1);
/usr/local/sbin -> $(SEC_BIN) (recurse =
1);
}
# Temporary directories
(rulename = "Temporary
directories", recurse = false, severity =
$(SIG_LOW))
{
/usr/tmp ->
$(SEC_INVARIANT);
/var/tmp ->
$(SEC_INVARIANT);
/tmp ->
$(SEC_INVARIANT);
}
# Include
(rulename = "OS Development
Files", severity = $(SIG_MED))
{
/usr/include ->
$(SEC_BIN);
/usr/local/include ->
$(SEC_BIN);
}
# Shared
(rulename = "OS Shared Files",
severity = $(SIG_MED))
{
/usr/share ->
$(SEC_BIN);
!/usr/share/man;
/usr/local/share
-> $(SEC_BIN);
}
# setuid/setgid root programs
(rulename =
"setuid/setgid", severity = $(SIG_HI))
{
/bin/df ->
$(SEC_SUID);
/bin/rcp ->
$(SEC_SUID);
/sbin/ccdconfig ->
$(SEC_SUID);
/sbin/dmesg ->
$(SEC_SUID);
/sbin/dump ->
$(SEC_SUID);
/sbin/ping ->
$(SEC_SUID);
/sbin/ping6 ->
$(SEC_SUID);
/sbin/rdump ->
$(SEC_SUID);
/sbin/restore ->
$(SEC_SUID);
/sbin/route ->
$(SEC_SUID);
/sbin/rrestore ->
$(SEC_SUID);
/sbin/shutdown ->
$(SEC_SUID);
/usr/bin/at ->
$(SEC_SUID);
/usr/bin/atq ->
$(SEC_SUID);
/usr/bin/atrm ->
$(SEC_SUID);
/usr/bin/batch ->
$(SEC_SUID);
/usr/bin/chfn ->
$(SEC_SUID);
/usr/bin/chpass ->
$(SEC_SUID);
/usr/bin/chsh ->
$(SEC_SUID);
/usr/bin/crontab ->
$(SEC_SUID);
/usr/bin/cu ->
$(SEC_SUID);
/usr/bin/fstat ->
$(SEC_SUID);
/usr/bin/ipcs ->
$(SEC_SUID);
/usr/bin/keyinfo ->
$(SEC_SUID);
/usr/bin/keyinit ->
$(SEC_SUID);
/usr/bin/lock ->
$(SEC_SUID);
/usr/bin/login ->
$(SEC_SUID);
/usr/bin/lpq ->
$(SEC_SUID);
/usr/bin/lpr ->
$(SEC_SUID);
/usr/bin/lprm ->
$(SEC_SUID);
/usr/bin/man ->
$(SEC_SUID);
/usr/bin/netstat ->
$(SEC_SUID);
/usr/bin/nfsstat ->
$(SEC_SUID);
/usr/bin/passwd ->
$(SEC_SUID);
/usr/bin/quota ->
$(SEC_SUID);
/usr/bin/rlogin ->
$(SEC_SUID);
/usr/bin/rsh ->
$(SEC_SUID);
/usr/bin/su ->
$(SEC_SUID);
/usr/bin/systat ->
$(SEC_SUID);
/usr/bin/top ->
$(SEC_SUID);
/usr/bin/uucp ->
$(SEC_SUID);
/usr/bin/uuname ->
$(SEC_SUID);
/usr/bin/uustat ->
$(SEC_SUID);
/usr/bin/uux ->
$(SEC_SUID);
/usr/bin/vmstat ->
$(SEC_SUID);
/usr/bin/wall ->
$(SEC_SUID);
/usr/bin/write ->
$(SEC_SUID);
/usr/bin/ypchfn ->
$(SEC_SUID);
/usr/bin/ypchpass ->
$(SEC_SUID);
/usr/bin/ypchsh ->
$(SEC_SUID);
/usr/bin/yppasswd ->
$(SEC_SUID);
/usr/libexec/sendmail/sendmail ->
$(SEC_SUID);
/usr/libexec/uucp/uucico ->
$(SEC_SUID);
/usr/libexec/uucp/uuxqt ->
$(SEC_SUID);
/usr/local/bin/mutt_dotlock ->
$(SEC_SUID);
/usr/sbin/ifmcstat ->
$(SEC_SUID);
/usr/sbin/iostat ->
$(SEC_SUID);
/usr/sbin/lpc ->
$(SEC_SUID);
/usr/sbin/mrinfo ->
$(SEC_SUID);
/usr/sbin/mtrace ->
$(SEC_SUID);
/usr/sbin/ppp ->
$(SEC_SUID);
/usr/sbin/pppd ->
$(SEC_SUID);
/usr/sbin/pstat ->
$(SEC_SUID);
/usr/sbin/sliplogin ->
$(SEC_SUID);
/usr/sbin/swapinfo ->
$(SEC_SUID);
/usr/sbin/timedc ->
$(SEC_SUID);
/usr/sbin/traceroute ->
$(SEC_SUID);
/usr/sbin/traceroute6 ->
$(SEC_SUID);
/usr/sbin/trpt ->
$(SEC_SUID);
}
(rulename = "Configuration Files", severity =
$(SIG_MED))
{
/etc/hosts ->
$(SEC_CONFIG);
/etc/inetd.conf ->
$(SEC_CONFIG);
/etc/resolv.conf ->
$(SEC_CONFIG);
/etc/syslog.conf ->
$(SEC_CONFIG);
/etc/newsyslog.conf ->
$(SEC_CONFIG);
}
(rulename = "Security Control", severity =
$(SIG_HI))
{
/etc/group ->
$(SEC_CRIT);
/etc/security/ ->
$(SEC_CRIT);
}
(rulename = "Login Scripts", severity =
$(SIG_HI))
{
/etc/csh.login ->
$(SEC_CONFIG);
/etc/csh.logout ->
$(SEC_CONFIG);
/etc/csh.cshrc ->
$(SEC_CONFIG);
/etc/profile ->
$(SEC_CONFIG);
}
# These files change every time the system
boots
(rulename = "System boot changes", severity =
$(SIG_HI))
{
/dev/log ->
$(Dynamic);
/dev/cuaa0 ->
$(Dynamic);
/dev/console ->
$(Dynamic);
/dev/ttyv0 -> $(Dynamic);
/dev/ttyv1 -> $(Dynamic);
/dev/ttyv2
-> $(Dynamic);
/dev/ttyv3 ->
$(Dynamic);
/dev/ttyv4 ->
$(Dynamic);
/dev/ttyv5 ->
$(Dynamic);
/dev/ttyv6 ->
$(Dynamic);
/dev/ttyp0 -> $(Dynamic);
/dev/ttyp1 -> $(Dynamic);
/dev/ttyp2
-> $(Dynamic);
/dev/ttyp3 ->
$(Dynamic);
/dev/ttyp4 ->
$(Dynamic);
/dev/ttyp5 ->
$(Dynamic);
/dev/ttyp6 ->
$(Dynamic);
/dev/urandom ->
$(Dynamic);
/var/run ->
$(Dynamic);
/var/log -> $(Dynamic);
}
#
Critical configuration files
(rulename = "Critical configuration
files", severity = $(SIG_HI))
{
/etc/crontab ->
$(ReadOnly);
/etc/periodic/daily ->
$(ReadOnly);
/etc/periodic/weekly ->
$(ReadOnly);
/etc/periodic/monthly ->
$(ReadOnly);
/etc/defaults ->
$(ReadOnly);
/etc/fstab ->
$(ReadOnly);
/etc/hosts.allow ->
$(ReadOnly);
/etc/ttys ->
$(ReadOnly);
/etc/gettytab ->
$(ReadOnly);
/etc/protocols ->
$(ReadOnly);
/etc/services ->
$(ReadOnly);
/etc/rc ->
$(ReadOnly);
/etc/rc.conf ->
$(ReadOnly);
/etc/rc.atm ->
$(ReadOnly);
/etc/rc.devfs ->
$(ReadOnly);
/etc/rc.diskless1 ->
$(ReadOnly);
/etc/rc.diskless2 ->
$(ReadOnly);
/etc/rc.firewall ->
$(ReadOnly);
/etc/rc.firewall6 ->
$(ReadOnly);
/etc/rc.i386 ->
$(ReadOnly);
/etc/rc.isdn ->
$(ReadOnly);
/etc/rc.network ->
$(ReadOnly);
/etc/rc.network6 ->
$(ReadOnly);
/etc/rc.pccard ->
$(ReadOnly);
/etc/rc.resume ->
$(ReadOnly);
/etc/rc.serial ->
$(ReadOnly);
/etc/rc.shutdown ->
$(ReadOnly);
/etc/rc.suspend ->
$(ReadOnly);
/etc/rc.syscons ->
$(ReadOnly);
/etc/rc.sysctl ->
$(ReadOnly);
/etc/motd ->
$(ReadOnly);
/etc/passwd ->
$(ReadOnly);
/etc/master.passwd ->
$(ReadOnly);
/etc/pwd.db ->
$(ReadOnly);
/etc/spwd.db ->
$(ReadOnly);
/etc/rpc ->
$(ReadOnly);
/etc/shells ->
$(ReadOnly);
/etc/ipf.rules ->
$(ReadOnly);
/etc/ipnat.rules ->
$(ReadOnly);
/etc/ssh/sshd_config ->
$(ReadOnly);
}
# Critical devices
(rulename = "Critical
devices", severity = $(SIG_HI), recurse =
false)
{
/dev/kmem ->
$(Device);
/dev/mem ->
$(Device);
/dev/null ->
$(Device);
/dev/zero ->
$(Device);
}[root@numa /root]# twadmin
--create-polfile --cfgfile /etc/tripwire/tw.cfg /etc/tripwire/twpol.txt
[root@numa /root]# tripwire --init --cfgfile /etc/tripwire/tw.cfg
*** Note: You will receive an error
that says that two files do
not exist yet.
These two files are /etc/ipf.rules and /etc/ipnat.rules.
That's OK
because we haven't created them yet. We won't until another
5-10 steps from
now. After you have completed this HOWTO, simply
re-initialize
the tripwire database & everything will be OK. [root@numa /root]# cd
/etc
[root@numa /etc]# vi crontab
- Add the following line to the file:
0 4 * * *
root /usr/local/sbin/tripwire --check
--cfgfile /etc/tripwire/tw.cfg[root@numa /root]# tripwire
--check --interactive --cfgfile
/etc/tripwire/tw.cfg
font8x8="/usr/share/syscons/fonts/iso02-8x8.fnt"
allscreens_flags="132x43"syslogd_flags="-ss"
sshd_flags="-4"
ipfilter_enable="YES"
ipmon_enable="YES"
ipmon_flags="-Dsvn"
ipnat_enable="YES"
network_interfaces="ed0 ed1 lo0"
ifconfig_ed1="inet 192.168.1.1 netmask 255.255.255.0"
ifconfig_lo0="inet 127.0.0.1"
ifconfig_ed0="DHCP"
[root@numa /root]# touch
/var/log/firewall_logs
[root@numa /root]# touch /var/log/authlog
[root@numa /root]# chmod 600 /var/log/firewall_logs
[root@numa
/root]# chmod 600 /var/log/authlog local0.* /var/log/firewall_logs
Modify the following line (at about line 14) and add the
'local0.none' part to it (like I have it, below):
*.notice;news.err;local0.none root
auth.*
/var/log/authlog
/var/log/firewall_logs 600 5 100 * Z
/var/log/authlog 600 5 100 * Z
For those new to egress
filtering...all it means is that you only allow out of your network traffic
that you explicitly want to let out. For example, you'd change the line that
allows unrestricted outbound tcp traffic (the first rule in the ruleset)
into 5 or more different rules. One which allows outbound traffic as long as
it's going to port 80 (http). The second allows outbound traffic as long as
it's going to port 25 (smtp), etc. Add as many rules as you need to define
the outbound traffic that you're allowing. Then, add a rule before all of
these that blocks all outbound traffic to broadcast addresses (i.e. anything
that ends with a 255...like x.x.x.255). And you'd add another rule that
blocks all outbound traffic if the source address isn't on the 192.168.1.0
network or the IP address of your ed0 interface (the one that's connected to
your ISP). So, you'd be blocking all packets that aren't coming from your
network or your own system. In other words, you know that your users will
only need to go out to web sites, send mail, etc. And they'll never need to
send broadcast packets out to the Internet, etc. And they better not be
spoofing their source IP address. This is only a sample of what egress
filtering is all about. Good (read as 'restrictive') egress filtering can be
quite complex, but is in the best interest of the Internet because it
doesn't allow your box (in the off-chance that it does get hacked) to be
used maliciously for things like "smurf" attacks and other broadcast
amplification attacks (where your system sends out broadcast packets to a
target network to get as many systems to respond as possible...which eats up
their bandwidth). In addition, it lets you know if you have any systems on
the inside of your network that are trying to access the internet over
unauthorized protocols & services (read as "misbehaving users...").
And as a final note, since we're using IPFILTER's stateful packet
inspection abilities, we don't need to reject traffic spoofing non-routable
or reserved addresses...they'll be blocked automatically since they don't
match a corresponding packet in the state table. If you do allow certain
services into your firewall (say, SSH access from the Internet so that you
can manage the firewall remotely), then you'll have to add these filters in.
To do so, block all incoming traffic on your ed0 interface that claims to
have a source IP address of 192.168.0.0/16, 10.0.0.0/8, or any of the other
reserved addresses, etc.
Use this IPFILTER ruleset as a starting
point. After you have everything running, add in whatever you want (egress
filtering, protection from non-routable addresses, IP spoofing protection,
etc.) to complete the job. This is only a starting point.
Note: Remember to modify the bold red text (below) so that it
matches the IP address of your ISP's DHCP server
#################################################################
#
Outside Interface
#################################################################
#----------------------------------------------------------------
#
Allow out all TCP, UDP, and ICMP traffic & keep state on it
# so
that it's allowed back
in.
#----------------------------------------------------------------
pass
out quick on ed0 proto tcp from any to any keep state
pass out quick on
ed0 proto udp from any to any keep state
pass out quick on ed0 proto
icmp from any to any keep state
block out quick on ed0
all
#----------------------------------------------------------------
#
Allow bootp traffic in from your ISP's DHCP server only.
#----------------------------------------------------------------
pass
in quick on ed0 proto udp from X.X.X.X/32 to any port = 68 keep
state
#----------------------------------------------------------------
#
Block and log all remaining traffic coming into the firewall
# - Block
TCP with a RST (to make it appear as if the service
# isn't
listening)
# - Block UDP with an ICMP Port Unreachable (to make it
appear
# as if the service isn't listening)
# - Block all remaining
traffic the good 'ol fashioned
way
#----------------------------------------------------------------
block
return-rst in log quick on ed0 proto tcp from any to any
block
return-icmp-as-dest(port-unr) in log quick on ed0 proto udp from any to
any
block in log quick on ed0
all
#################################################################
# Inside Interface
#################################################################
#----------------------------------------------------------------
# Allow out all TCP, UDP, and ICMP traffic & keep state
#----------------------------------------------------------------
pass out quick on ed1 proto tcp from any to any keep state
pass
out quick on ed1 proto udp from any to any keep state
pass out quick
on ed1 proto icmp from any to any keep state
block out quick on ed1
all
#----------------------------------------------------------------
#
Allow in all TCP, UDP, and ICMP traffic & keep state
#----------------------------------------------------------------
pass in quick on ed1 proto tcp from any to any keep state
pass in
quick on ed1 proto udp from any to any keep state
pass in quick on ed1
proto icmp from any to any keep state
block in quick on ed1 all
#################################################################
# Loopback Interface
#################################################################
#----------------------------------------------------------------
# Allow everything to/from your loopback interface so you
# can ping yourself (e.g. ping localhost)
#----------------------------------------------------------------
pass in quick on lo0 all
pass out quick on lo0 all
map ed0 192.168.1.0/24 -> 0/32
cd /usr/src/sys/i386/conf
cp GENERIC FIREWALL
options IPFILTER
options
IPFILTER_LOG
options IPFILTER_DEFAULT_BLOCK options VESA
device ed1 at isa? port 0x280
irq 10 iomem 0xd8000
[root@numa conf]# /usr/sbin/config
-g FIREWALL
[root@numa conf]# cd ../../compile/FIREWALL
[root@numa
FIREWALL]# make depend
[root@numa FIREWALL]# make
[root@numa
FIREWALL]# make install - Modify the line that reads
'kern_securelevel_enable="NO"' and change the value to "YES"
- Add a
line beneath it that reads 'kern_securelevel="2"' /
ufs rw 1 1
Modify the /etc/fstab file so that it reads as
follows:
/tmp
ufs rw 2 2
/usr
ufs rw 2 2
/usr/home ufs rw 2
2
/usr/local ufs rw 2 2
/var ufs
rw 2 2 /
ufs rw,nosuid
1 1
Note that this will make adding new software, etc.
much more difficult since /usr and /usr/local are mounted read-only. This
means that programs which try to install their user-land programs in
/usr/local/bin will fail during their install programs. And cvsup...which will
try to update the kernel's source code in /usr/src and the ports in
/usr/ports...well, they're now read-only because they fall under /usr.
/tmp
ufs rw,noexec,nosuid 2 2
/usr
ufs ro
2
2
/usr/home ufs rw,noexec,nosuid 2 2
/usr/local ufs ro,nosuid
2 2
/var
ufs rw,noexec,nosuid 2 2
If you want to add new software or upgrade the kernel & ports tree
source code, you'll need to
A pain, I know, but this is your
firewall, not a desktop workstation. This is the price you pay for a VERY,
VERY secure machine. If you want an even more secure machine than this, then
you can start setting the immutable flag on files in the filesystem by using
the chflags command with the schg flag...but I won't cover that in this howto.
[root@numa /etc]# shutdown -r now
Hit [Enter] to boot immediately, or any other key for command prompt.
Hit the [space bar] (anything except the "enter" key), and you'll get to an "ok" prompt.
Booting [kernel] in 9 seconds...
ok unload kernel
ok load kernel.old
/kernel.old text=0xdf...bunch of stuff on the line...
ok boot
Hit [Enter] to boot immediately,
or any other key for command prompt.
Booting [kernel] in 9 seconds...
Questions or Comments? E-mail: Marty
Schlacter