How to Build a FreeBSD-STABLE Firewall with IPFILTER
Applicable to: FreeBSD 4.6
Updated: Sep 3, 2002
Author: Marty
Schlacter
Source URL: http://www.schlacter.net/public/FreeBSD-STABLE_and_IPFILTER.html
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 most of a complete day 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 Linux/IPTABLES or OpenBSD/PF 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. His site is a little out of date, due to changing priorities in his life, but the info on his site is still very applicable to any version of FreeBSD 4.X.
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.
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 cards (two) (generic) | Modem | - no CD-ROM drive --------- | | ed0 | --------------- | xx.xx.xx.xx | | | | FreeBSD | | Firewall | | | | 192.168.1.1 | --------------- ed1 | | | ----------- | 10BaseT | | Hub | ----------- | | | | | | | | | | Internal Network (TRUSTED)
Installing FreeBSD
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. 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. In fact, there's actually two different versions of the STABLE branch...one that has all of the patches, bugfixes, and enhancements, and a second that only has the bugfixes and patches (no enhancements). The second version is usually more stable than the first, but not always so. For a production firewall, you'll probably want to install the 2nd version of STABLE (without the enhancements), but it's ultimately your call.
If you've installed FreeBSD-4.6 from CD-ROM (either one that your purchased or 'burned' from a downloaded ISO image), you probably installed 4.6-RELEASE, which is (simplistically) nothing more than a version of the 4.X branch that was exhaustively tested, burned to CD-ROM and made available for sale. After the release date of 4.6-RELEASE, the 4.6 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.6 tree, 4.6-RELEASE is the only one made available for sale on CD, and subsequent snapshots of the 4.6 tree are only available on-line and are labelled '4.6-STABLE'. Once 4.6-STABLE is sufficiently enhanced/patched (perhaps 4-6 months later), the code enters a freeze and will officially become the 'RELEASE' version of the next FreeBSD release (say, 4.7-RELEASE...or 5.0-RELEASE). If you're installing FreeBSD 4.6 well after the release date, you will definitely want to install 4.6-RELEASE, and then immediately update your kernel and binaries to 4.6-STABLE.
So, what are the benefits of upgrading to 4.6-STABLE rather than staying with 4.6-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 a 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 upgraded to 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 upgrading to the latest snapshot from the STABLE branch saves you a lot of time associated with loading individual security-related patches after your OS load is finished. For a complete listing of security-related patches, see the FreeBSD Security Information page.
OK, now that we've talked about the benefits of FreeBSD-STABLE, let's get to work...the installation...
[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>fdimage kern.flp A:
C:\WINDOWS\TEMP>fdimage mfsroot.flp A:
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
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.
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. People have reported success when using this partitioning scheme on a drive this small. But, as always, 'caveat emptor'. You'll probably run out of space if you're not careful. One recommendation is to not install the ports collection at all. That'll save about 160MB in the /usr partition. Another recommendation is to only re-compile the kernel and not all of the system binaries (i.e. only run the "build kernel" command when you get to the appropriate section at the end of this howto). Apply security-related patches to the system binaries manually by following the directions for each patch listed on the FreeBSD Security Information page. Yes, it's a pain...but if your hard drive is too small, then it's too small...
128MB file system mounted as /
512MB file system mounted as /tmp
512MB file system mounted as /var
1,500MB file system mounted as /usr
640MB file system mounted as /usr/local
500MB file system mounted as /usr/home (...the remainder of the hard drive)
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
(System Installs...If the FTP site that you chose isn't heavily loaded,
the install can take as little as 22 minutes (with a cable modem). If your FTP
site is heavily loaded, the install can take as long as 2 hours...or
longer...)
Type: Auto
Port: COM1
Flags: -3
WWW - lynx-ssl-2.8.4.1b_1
Mail - mutt-1.2.5.1_1
Net - cvsup-without-gui-16.1f
Shells - bash-2.0.5a
FTP - ncftp-3.1.2
Then tab over and select "Install", select "OK" to confirm your choices
(Packages are installed...takes about 60 seconds)
Networking:
- Disable "inetd - This machine wants to run the inet daemon" ... then select "No" to confirm
- Enable "ntpdate - Select a clock-synchronization server" ... then select a server near you
Then select Exit and return to the previous menu, and then tab over and select "Exit Install"
(System reboots...)
Upgrading to -STABLE, Compiling IPFILTER into the kernel, & Configuring the System
Now that you have FreeBSD-RELEASE installed on the system, we need to spend a few hours upgrading to FreeBSD-STABLE, 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 & system binaries, and when the system reboots, you're done. That's it.
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'
* * * * * * * * * * * * W A R N I N G * * * * * * * * * * * * *
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
Note #1: After you configure cvsup and update your source and ports collection, you will want to re-run cvsup every once in a while to ensure your sources & ports collection is up-to-date (in case you want to install any new software). Then, you'll want to recompile your kernel & system binaries to ensure you are using the latest versions with security patches applied.
Note #2: We are only updating sections of the ports tree that would be "normal" for a firewall. (i.e. we are not updating the ports collection for games, X-windows, etc.). This will save disk space by not wasting it on ports you won't be installing on a firewall. I'll make the assumption that since you installed packages from the WWW, Mail, Net, and Shells section of the packages collection during the installation (i.e. when you installed lynx, etc.), you'll want the same sections of the ports collection kept up to date. In addition, we'll add to other areas with tools that might be useful on a firewall - the "security" and "sysutils" areas. Add whichever areas you want, but be aware that the more you add...the more hard disk space you'll "eat up." To get a list of which sections of the ports collection are available, do a 'more /usr/share/examples/cvsup/ports-supfile' and browse through the listings of individual ports collection names.
[root@numa /root]# cp /usr/src/share/examples/cvsup/stable-supfile /etc
[root@numa /root]# vi /etc/stable-supfile[root@numa /root]# cvsup /etc/stable-supfile- Run the ":set num" command in vi so that you can see the line numbers on each line of the file.
- 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. 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 different value for this tag that's just for you. In this case, set the tag to "RELENG_4_6". This has ONLY the security fixes...no feature enhancements...so it's arguably the more stable version of the 4.6-STABLE branch. 95% of sysadmin's should change the tag to "RELENG_4_6" to track the security-related "4.6-STABLE" baseline and not mess with new enhancements which might impact the system's stability. It's your system...it's your call... The official information about tag 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-ftp tag=.
ports-security tag=.
ports-sysutils tag=.
- ...and other lines for ports collections you want...(Source tree is synchronized with CVS server...should take 30-60 minutes...)
# This is ssh server systemwide configuration file. See sshd(8)
# for more information
Port 22
Protocol 2
ListenAddress 192.168.1.1 *** Put your internal interface's address here ***
#ListenAddress :: *** Delete this line ***
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 3 unauthenticated connections, refuse 50% of the new ones, and
# refuse any more than 10 total.
MaxStartups 3:50:10
# 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
PrintLastLog yes
KeepAlive yes
# Logging
SyslogFacility AUTH
LogLevel VERBOSE
#obsoletes QuietMode and FascistLogging
RhostsAuthentication no
#
# For this to work you will also need host keys in /etc/ssh_known_hosts
RhostsRSAAuthentication no
# similar for protocol version 2
HostbasedAuthentication no
#
RSAAuthentication yes
# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no
PermitEmptyPasswords no
# Uncomment to disable s/key passwords
ChallengeResponseAuthentication no
# 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
#MaxStartups 10:30:60 *** Delete this line, it's a duplicate ***
Banner /etc/issue.net
#ReverseMappingCheck yes
Subsystem sftp /usr/libexec/sftp-server
AllowUsers newuser *** Substitute 'newuser' with your userid ***
[root@numa /root]# su - testuser *** substitute 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 ***
[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]# cp /home/testuser/.ssh/id_dsa* . *** Copies all of your user's ssh key info to the floppy
[root@numa floppy]# ls *** List the contents of the floppy to verify the files are there
[root@numa floppy]# cd ..
[root@numa mnt]# umount /mnt/floppy *** Unmount 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
# If you want to allow a specific computer on the Internet to SSH into your
# system, replace the 'sshd' line above with one like this...but subsitute
# the X.X.X.X and subnet mask to suit your needs (e.g. one computer, entire subnet
# etc.). Also, make sure you allow inbound SSH from that same host/subnet
# in your /etc/ipf.rules file.
# sshd : 192.168.1.0/255.255.255.0 X.X.X.X/255.255.255.255 : allow
[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]
- Use the down-arrow to move through the hyperlinks until you've selected a mirror site to download from, and then arrow over to the "download" hyperlink for that download site. Hit [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.
[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);
}
(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);
}
# 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/periodic/security -> $(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.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"
ipfilter_flags=""
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"
icmp_drop_redirects="YES"
[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_logsThen, add the entry "local0.none" to the line for /var/log/messages. Add it to the middle of the line, separated from the other entries with a semi-colon. This will ensure that the firewall log entries don't end up in /var/log/messages...they'll only go to your firewall log, configured above.
auth.* /var/log/authlog
/var/log/firewall_logs 600 14 100 * Z
/var/log/authlog 600 14 100 * Z
#################################################################
# Outside Interface
#################################################################
#----------------------------------------------------------------
# Allow out all TCP, UDP, and ICMP traffic & keep state on it
# so that it's allowed back in.
#
# If you wanted to do egress filtering...here's where you'd do it.
# You'd change the lines below so that rather than allowing out any
# arbitrary TCP connection, it would only allow out mail, pop3, and http
# connections (for example). So, the first line, below, would be
# replaced with:
# pass out quick on ed0 proto tcp from any to any port = 25 keep state
# pass out quick on ed0 proto tcp from any to any port = 110 keep state
# pass out quick on ed0 proto tcp from any to any port = 80 keep state
# ...and then do the same for the remaining lines so that you allow
# only specified protocols/ports 'out' of your network
#----------------------------------------------------------------
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
#-----------------------------------------------------------------------
# Block all inbound traffic from non-routable or reserved address spaces
#-----------------------------------------------------------------------
block in log quick on ed0 from 192.168.0.0/16 to any #RFC 1918 private IP
block in log quick on ed0 from 172.16.0.0/12 to any #RFC 1918 private IP
block in log quick on ed0 from 10.0.0.0/8 to any #RFC 1918 private IP
block in log quick on ed0 from 127.0.0.0/8 to any #loopback
block in log quick on ed0 from 0.0.0.0/8 to any #loopback
block in log quick on ed0 from 169.254.0.0/16 to any #DHCP auto-config
block in log quick on ed0 from 192.0.2.0/24 to any #reserved for doc's
block in log quick on ed0 from 204.152.64.0/23 to any #Sun cluster interconnect
block in quick on ed0 from 224.0.0.0/3 to any #Class D & E multicast
#----------------------------------------------------------------
# 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
#----------------------------------------------------------------
# If you wanted to set up a web server or mail server on your box
# (which is outside the scope of this howto), or allow another system
# on the Internet to externally SSH into your firewall, you'd want to
# uncomment the following lines and modify as appropriate. If you
# have other services running that you need to allow external access
# to, just add more lines using these as examples.
#
# If the services are on a box on your internal network (rather than
# the firewall itself), you'll have to add both the filter listed below,
# plus a redirect rule in your /etc/ipnat.rules file.
#----------------------------------------------------------------
# pass in quick on ed0 proto tcp from any to any port = 80 flags S keep state keep frags
# pass in quick on ed0 proto tcp from any to any port = 25 flags S keep state keep frags
# pass in quick on ed0 proto tcp from X.X.X.X/32 to any port = 22 flags S keep state keep frags
#----------------------------------------------------------------
# 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
#--------------------------------------------------------------------
# Do 'normal' IP address translation. This line will take all packets
# going out on your external NIC (ed0) that have a source address coming
# from your internal network (192.168.1.0), and translate it to whatever
# IP address your external NIC happens to have at that time
#--------------------------------------------------------------------
map ed0 192.168.1.0/24 -> 0/32
#--------------------------------------------------------------------
# If you have a system on your internal network that needs to be
# 'reachable' by external systems on the internet, you'll need a rule
# similar to the one below. This one takes all inbound http traffic
# (TCP port 80) that hits the firewall's external interface (ed0) and
# redirects it to port 80 on the 192.168.1.50 system on the internal network.
# Simply uncomment the rule, change the IP address and port number so that
# it does what you need. Remember that you have to enable the corresponding
# inbound filter in your /etc/ipf.rules file, too.
#--------------------------------------------------------------------
# rdr ed0 0.0.0.0/0 port 80 -> 192.168.1.50 port 80 tcp
net.inet.tcp.blackhole=2
net.inet.udp.blackhole=1
root
newuser
*/5 * * * * root /usr/libexec/atrun
[root@numa /etc]# chmod 600 /etc/crontab
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 /]# cd /usr/src
[root@numa src]# echo "KERNCONF=FIREWALL" >> /etc/make.conf
[root@numa src]# make world
[root@numa src]# make kernel
- 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"'
# Device Mountpoint FStype Options Dump Pass#First, copy the original /etc/fstab file to /etc/fstab.original
/dev/ad0s1b none swap sw 0 0
/dev/ad0s1a / ufs rw 1 1
/dev/ad0s1e /tmp ufs rw 2 2
/dev/ad0s1g /usr ufs rw 2 2
/dev/ad0s1d /usr/home ufs rw 2 2
/dev/ad0s1h /usr/local ufs rw 2 2
/dev/ad0s1f /var ufs rw 2 2
proc /proc procfs rw 0 0
# Device Mountpoint FStype Options Dump Pass#Next, copy your new /etc/fstab.restrictive file and over-write the original /etc/fstab...so that your "real" fstab file has the restrictive settings, and you have the two other config files available (the original and restrictive one).
/dev/ad0s1b none swap sw 0 0
/dev/ad0s1a / ufs rw,nosuid 1 1
/dev/ad0s1e /tmp ufs rw,noexec,nosuid,nodev 2 2
/dev/ad0s1g /usr ufs ro 2 2
/dev/ad0s1d /usr/home ufs rw,noexec,nosuid 2 2
/dev/ad0s1h /usr/local ufs ro,nosuid 2 2
/dev/ad0s1f /var ufs rw,noexec,nosuid 2 2
proc /proc procfs rw 0 0
[root@numa etc]# cp /etc/fstab.restrictive /etc/fstabNote 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. So, mounting your partitions in a very restrictive way is a double-edged sword. It limits what the hacker can do on your system, but it makes software installs and kernel upgrades more difficult (or impossible...if the partitions are still mounted in a restrictive way).
[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...
[root@numa /root]# tripwire --init --cfgfile /etc/tripwire/tw.cfgAfter you do this...you should have a completely working firewall...enjoy!