BUY THIS BOOK
Add to Cart

Print Book $39.95


Add to Cart

Print+PDF $51.94

Add to Cart

PDF $31.99

Safari Books Online

What is this?

Add to UK Cart

Print Book £28.50

What is this?

Looking to Reprint or License this content?


Linux Security Cookbook
Linux Security Cookbook

By Daniel J. Barrett, Richard E. Silverman, Robert G. Byrnes
Book Price: $39.95 USD
£28.50 GBP
PDF Price: $31.99

Cover | Table of Contents | Colophon


Table of Contents

Chapter 1: System Snapshots with Tripwire
Suppose your system is infiltrated by the infamous Jack the Cracker. Being a conscientious evildoer, he quickly modifies some system files to create back doors and cover his tracks. For instance, he might substitute a hacked version of /bin/login to admit him without a password, and a bogus /bin/ls could skip over and hide traces of his evil deeds. If these changes go unnoticed, your system could remain secretly compromised for a long time. How can this situation be avoided?
Break-ins of this kind can be detected by an integrity checker : a program that periodically inspects important system files for unexpected changes. The very first security measure you should take when creating a new Linux machine, before you make it available to networks and other users, is to "snapshot" (record) the initial state of your system files with an integrity checker. If you don't, you cannot reliably detect alterations to these files later. This is vitally important!
Tripwire is the best known open source integrity checker. It stores a snapshot of your files in a known state, so you can periodically compare the files against the snapshot to discover discrepancies. In our example, if /bin/login and /bin/ls were in Tripwire's snapshot, then any changes in their size, inode number, permissions, or other attributes would catch Tripwire's attention. Notably, Tripwire detects changes in a file's content, even a single character, by verifying its checksum.
tripwire Version 1.2, supplied in SuSE 8.0, is positively ancient and supports an outdated syntax. Before attempting any recipes in this chapter, upgrade to the latest tripwire (2.3 or higher) at http://sourceforge.org/projects/tripwire or http://www.tripwire.org.
Tripwire is driven by two main components: a policy and a database. The policy lists all files and directories that Tripwire should snapshot, along with rules for identifying violations (unexpected changes). For example, a simple policy could treat any changes in
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Setting Up Tripwire
You want to prepare a computer to use Tripwire for the first time.
After you have installed Tripwire, do the following:
# cd /etc/tripwire
# ./twinstall.sh
# tripwire --init
# rm twcfg.txt twpol.txt
The script twinstall.sh performs the following tasks within the directory /etc/tripwire:
  • Creates the site key and the local key, prompting you to enter their passphrases. (If the keys exist, this step is skipped.) The site key is stored in site.key, and the local key in hostname-local.key, where hostname is the hostname of the machine.
  • Signs the default configuration file, twcfg.txt, with the site key, creating tw.cfg.
  • Signs the default policy file, twpol.txt, with the site key, creating tw.pol.
If for some reason your system doesn't have twinstall.sh, equivalent manual steps are:
               Helpful variables:
DIR=/etc/tripwire
SITE_KEY=$DIR/site.key
LOCAL_KEY=$DIR/`hostname`-local.key

Generate the site key:
# twadmin --generate-keys --site-keyfile $SITE_KEY

Generate the local key:
# twadmin --generate-keys --local-keyfile $LOCAL_KEY

Sign the configuration file:
# twadmin --create-cfgfile --cfgfile $DIR/tw.cfg \
          --site-keyfile $SITE_KEY $DIR/twcfg.txt

Sign the policy file:
# twadmin --create-polfile --cfgfile $DIR/tw.cfg \
          --site-keyfile $SITE_KEY $DIR/twpol.txt

Set appropriate permissions:
# cd $DIR
# chown root:root $SITE_KEY $LOCAL_KEY tw.cfg tw.pol
# chmod 600 $SITE_KEY $LOCAL_KEY tw.cfg tw.pol
(Or chmod 640 to allow a root group to access the files.)
These steps assume that your default configuration and policy files exist: twcfg.txt and twpol.txt, respectively. They should have been supplied with the Tripwire distribution. Undoubtedly you'll need to edit them to match your system. [Recipe 1.3] The names
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Displaying the Policy and Configuration
You want to view Tripwire's policy or configuration, but they are stored in non-human-readable, binary files, or they are missing.
Generate the active configuration file:
# cd /etc/tripwire
# twadmin --print-cfgfile > twcfg.txt
Generate the active policy file:
# cd /etc/tripwire
# twadmin --print-polfile > twpol.txt
Tripwire's active configuration file tw.cfg and policy file tw.pol are encrypted and signed and therefore non-human-readable. To view them, you must first convert them to plaintext.
Tripwire's documentation advises you to delete the plaintext versions of the configuration and policy after re-signing them. If your plaintext files were missing to start with, this is probably why.
Although you can redirect the output of twadmin to any files you like, remember that twinstall.sh requires the plaintext policy and configuration files to have the names we used, twcfg.txt and twpol.txt. [Recipe 1.1]
twadmin(8).
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Modifying the Policy and Configuration
You want to change the set of files and directories that tripwire examines, or change tripwire's default behavior.
Extract the policy and configuration to plaintext files: [Recipe 1.2]
# cd /etc/tripwire
# twadmin --print-polfile > twpol.txt
# twadmin --print-cfgfile > twcfg.txt
Modify the policy file twpol.txt and/or the configuration file twcfg.txt with any text editor. Then re-sign the modified files: [Recipe 1.1]
# twadmin --create-cfgfile --cfgfile /etc/tripwire/tw.cfg \ 
          --site-keyfile site_key etc/tripwire/twcfg.txt
# twadmin --create-polfile --cfgfile /etc/tripwire/tw.cfg \
          --site-keyfile site_key etc/tripwire/twpol.txt
and reinitialize the database: [Recipe 1.1]
# tripwire --init
# rm twcfg.txt twpol.txt
This is much like setting up Tripwire from scratch [Recipe 1.1], except our existing, cryptographically-signed policy and configuration files are first converted to plaintext. [Recipe 1.2]
You'll want to modify the policy if tripwire complains that a file does not exist:
### Error: File could not be opened.
Edit the policy file and remove or comment out the reference to this file if it does not exist on your system. Then re-sign the policy file.
You don't need to follow this procedure if you're simply updating the database after an integrity check [Recipe 1.11], only if you've modified the policy or configuration.
twadmin(8), tripwire(8).
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Basic Integrity Checking
You want to check whether any files have been altered since the last Tripwire snapshot.
# tripwire --check
This command is the lifeblood of Tripwire: has your system changed? It compares the current state of your filesystem against the Tripwire database, according to the rules in your active policy. The results of the comparison are written to standard output and also stored as a timestamped, signed Tripwire report.
You can also perform a limited integrity check against one or more files in the database. If your tripwire policy contains this rule:
(
  rulename = "My funky files",
  severity = 50
)
{
  /sbin/e2fsck                         -> $(SEC_CRIT) ;
  /bin/cp                              -> $(SEC_CRIT) ;
  /usr/tmp                             -> $(SEC_INVARIANT) ;
  /etc/csh.cshrc                       -> $(SEC_CONFIG) ;
}
you can check selected files and directories with:
# tripwire --check /bin/cp /usr/tmp
or all files in the given rule with:
# tripwire --check --rule-name "My funky files"
or all rules with severities greater than or equal to a given value:
# tripwire --check --severity 40
tripwire(8), and the Tripwire manual for policy syntax. You can produce a help message with:
$ tripwire --check --help
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Read-Only Integrity Checking
You want to store Tripwire's most vital files on read-only media, such as a CD-ROM or write-protected disk, to guard against compromise, and then run integrity checks.
  1. Copy the site key, local key, and tripwire binary onto the desired disk, write-protect it, and mount it. Suppose it is mounted at /mnt/cdrom.
    # mount /mnt/cdrom
    # ls -l /mnt/cdrom
    total 2564
    -r--r-----    1 root     root          931 Feb 21 12:20 site.key
    -r--r-----    1 root     root          931 Feb 21 12:20 myhost-local.key
    -r-xr-xr-x    1 root     root      2612200 Feb 21 12:19 tripwire
  2. Generate the Tripwire configuration file in plaintext: [Recipe 1.2]
    # DIR=/etc/tripwire
    # cd $DIR
    # twadmin --print-cfgfile > twcfg.txt
  3. Edit the configuration file to point to these copies: [Recipe 1.3]
                         /etc/tripwire/twcfg.txt:
    ROOT=/mnt/cdrom
    SITEKEYFILE=/mnt/cdrom/site.key
    LOCALKEYFILE=/mnt/cdrom/myhost-local.key
  4. Sign your modified Tripwire configuration file: [Recipe 1.3]
    # SITE_KEY=/mnt/cdrom/site.key
    # twadmin --create-cfgfile --cfgfile $DIR/tw.cfg \
              --site-keyfile $SITE_KEY $DIR/twcfg.txt
  5. Regenerate the tripwire database [Recipe 1.3] and unmount the CD-ROM:
    # /mnt/cdrom/tripwire --init
    # umount /mnt/cdrom
Now, whenever you want to perform an integrity check [Recipe 1.4], insert the read-only disk and run:
# mount /mnt/cdrom
# /mnt/cdrom/tripwire --check
# umount /mnt/cdrom
The site key, local key, and tripwire binary (/usr/sbin/tripwire) are the only files you need to protect from compromise. Other Tripwire-related files, such as the database, policy, and configuration, are signed by the keys, so alterations would be detected. (Back them up frequently, however, in case an attacker deletes them!)
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Remote Integrity Checking
You want to perform an integrity check, but to increase security, you store vital Tripwire files off-host.
In this recipe and others, we use two machines: your original machine to be checked, which we'll call trippy, and a second, trusted machine we'll call trusty. trippy is the untrusted machine whose integrity you want to check with Tripwire. trusty is a secure machine, typically with no incoming network access.
Store copies of the site key, local key, and tripwire binary on a trusted remote machine that has no incoming network access. Use rsync , securely tunneled through ssh, to verify that the originals and copies are identical, and to trigger an integrity check.
The initial setup on remote machine trusty is:
#!/bin/sh
REMOTE_MACHINE=trippy
RSYNC='/usr/bin/rsync -a --progress --rsh=/usr/bin/ssh'
SAFE_DIR=/usr/local/tripwire/${REMOTE_MACHINE}
VITAL_FILES="/usr/sbin/tripwire 
        /etc/tripwire/site.key 
        /etc/tripwire/${REMOTE_MACHINE}-local.key"

mkdir $SAFE_DIR
for file in $VITAL_FILES
do 
        $RSYNC ${REMOTE_MACHINE}:$file $SAFE_DIR/
done
Prior to running every integrity check on the local machine, verify these three files by comparing them to the remote copies. The following code should be run on trusty, assuming the same variables as in the preceding script (REMOTE_MACHINE, etc.):
#!/bin/sh
cd $SAFE_DIR
rm -f log
for file in $VITAL_FILES
do
        base=`basename $file`
        $RSYNC -n ${REMOTE_MACHINE}:$file . | fgrep -x "$base" >> log
done
if [ -s log ] ; then
        echo 'Security alert!'
else
        ssh ${REMOTE_MACHINE} -l root /usr/sbin/tripwire --check
fi
rsync is a handy utility for synchronizing files on two machines. In this recipe we tunnel rsync through ssh, the Secure Shell, to provide secure authentication and to encrypt communication between
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Ultra-Paranoid Integrity Checking
You want highly secure integrity checks, at the expense of speed and convenience.
Securely create a bootable CD-ROM containing a minimal Linux system, the tripwire binary, and your local and site keys. Disconnect your computer from all networks, boot on the CD-ROM, and perform an integrity check of your computer's disks, using executable programs on the CD-ROM only.
Back up your Tripwire database, configuration, and policy frequently, in case an attacker deletes them from your system.
This cumbersome but more secure method requires at least two computers, one of them carefully trusted. As before, we'll call the trusted system trusty and the Tripwire machine trippy. Our goal is to run secure Tripwire checks on trippy.
The first important step is to create a bootable CD-ROM securely. This means:
  • Create the CD-ROM on trusty, a virgin Linux machine built directly from trusted source or binary packages, that has never been on a network or otherwise accessible to third parties. Apply all necessary security patches to bring trusty up to date.
  • Configure the CD-ROM's startup scripts to disable all networking.
  • Populate the CD-ROM directly from trusted source or binary packages.
  • Create your Tripwire site key and local key on trusty.
Second, boot trippy on the CD-ROM, mount the local disks, and create trippy's Tripwire database, using the tripwire binary and keys on the CD-ROM. Since the Tripwire database, policy, and configuration files are signed with keys on the CD-ROM, these files may safely reside on trippy, rather than the CD-ROM.
Third, you must boot trippy
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Expensive, Ultra-Paranoid Security Checking
You want highly secure integrity checks and are willing to shell out additional money for them.
Store your files on a dual-ported disk array. Mount the disk array read-only on a second, trusted machine that has no network connection. Run your Tripwire scans on the second machine.
A dual-ported disk array permits two machines to access the same physical disk. If you've got money to spare for increased security, this might be a reasonable approach to securing Tripwire.
Once again, let trippy be your machine in need of Tripwire scans. trusty is a highly secure second machine, built directly from trusted source or binary packages with all necessary security patches applied, that has no network connection and has never been accessible to third parties.
trippy's primary storage is kept on a dual-ported disk array. Mount this array on trusty read-only. Perform all Tripwire-related operations on trusty: initializing the database, running integrity checks, and so forth. The Tripwire database, binaries, keys, policy, and configuration are likewise kept on trusty. Since trusty is inaccessible via any network, your Tripwire checks will be as reliable as the physical security of trusty.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Automated Integrity Checking
You want to schedule integrity checks at specific times or intervals.
Use cron. For example, to perform an integrity check every day at 3:00 a.m.:
               root's crontab file:
0 3 * * * /usr/sbin/tripwire --check
This is not a production-quality recipe. An intruder could compromise cron, substituting another job or simply preventing yours from running. For more reliability, run the cron job on a trusted remote machine:
               Remote crontab entry on trusty:
0 3 * * * ssh -n -l root trippy /usr/sbin/tripwire --check
but if an intruder compromises sshd on trippy, you're again out of luck. Likewise, some rootkits [Recipe 9.12] can subvert the exec call to tripwire even if invoked remotely. For maximum security, run not only the cron job but also the integrity check on a trusted remote machine. [Recipe 1.8]
Red Hat Linux comes preconfigured to run tripwire every night via the cron job /etc/cron.daily/tripwire-check. However, a Tripwire database is not supplied with the operating system: you must initialize one yourself. [Recipe 1.1] If you don't, cron will send daily email to root about a failed tripwire invocation.
tripwire(8), crontab(1), crontab(5), cron(8).
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Printing the Latest Tripwire Report
You want to display the results of the most recent integrity check.
#!/bin/sh
DIR=/var/lib/tripwire/report
HOST=`hostname -s`
LAST_REPORT=`ls -1t $DIR/$HOST-*.twr | head -1`
twprint --print-report --twrfile "$LAST_REPORT"
Tripwire reports are stored in the location indicated by the REPORTFILE variable in the Tripwire configuration file. A common value is:
REPORTFILE = /var/lib/tripwire/report/$(HOSTNAME)-$(DATE).twr
The HOSTNAME variable contains the hostname of your machine (big surprise), and DATE is a numeric timestamp such as 20020409-040521 (April 9, 2002, at 4:05:21). So for host trippy, this report filename would be:
/var/lib/tripwire/report/trippy-20020409-040521.twr
When tripwire runs, it can optionally send reports by email. This notification should not be considered reliable since email can be suppressed, spoofed, or otherwise compromised. Instead, get into the habit of examining the reports yourself.
The twprint program can print reports not only for integrity checks but also for the Tripwire database. To do the latter:
# twprint --print-dbfile --dbfile /var/lib/tripwire/`hostname -s`.twd
Tripwire(R) 2.3.0 Database
Database generated by:        root
Database generated on:        Mon Apr  1 22:33:52 2002
Database last updated on:     Never
... contents follow ...
            
twprint(8).
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Updating the Database
Your latest Tripwire report contains discrepancies that tripwire should ignore in the future.
Update the Tripwire database relative to the most recent integrity check report:
#!/bin/sh
DIR=/var/lib/tripwire/report
HOST=`hostname -s`
LAST_REPORT=`ls -1t $DIR/$HOST-*.twr | head -1`
tripwire --update --twrfile "$LAST_REPORT"
Updates are performed with respect to an integrity check report, not with respect to the current filesystem state. Therefore, if you've modified some files since the last check, you cannot simply run an update: you must run an integrity check first. Otherwise the update won't take the changes into account, and the next integrity check will still flag them.
Updating is significantly faster than reinitializing the database. [Recipe 1.3]
tripwire(8).
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Adding Files to the Database
Tell tripwire to include a file or directory in its database.
Generate the active policy file in human-readable format. [Recipe 1.2] Add the given file or directory to the active policy file.
To mark the file /bin/ls for inclusion:
/bin/ls  -->  $(SEC_BIN) ;
To mark the entire directory tree /etc for inclusion:
/etc     -->  $(SEC_BIN) ;
To mark /etc and its files, but not recurse into subdirectories:
/etc     -->  $(SEC_BIN) (recurse=1) ;
To mark only the /etc directory but none of its files or subdirectories:
/etc     -->  $(SEC_BIN) (recurse=0);
Then reinitialize the database. [Recipe 1.3]
The policy is a list of rules stored in a policy file. A rule looks like:
               filename -> rule ;
which means that the given file (or directory) should be considered compromised if the given rule is broken. For instance,
/bin/login -> +pisug ;
means that /bin/login is suspect if its file permissions (p), inode number (i), size (s), user (u), or group (g) have changed since the last snapshot. We won't document the full policy syntax because Tripwire's manual is quite thorough. Our recipe uses a predefined rule in a global variable, SEC_BIN, designating a binary file that should not change.
The recurse= n attribute for a directory tells tripwire to recurse n levels deep into the filesystem. Zero means to consider only the directory file itself.
It's actually quite likely that you'll need to modify the policy. The default policy supplied with Tripwire is tailored to a specific type of system or Linux distribution, and contains a number of files not necessarily present on yours.
The Tripwire manual has detailed documentation on the policy file format.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Excluding Files from the Database
You want to add some, but not all, files in a given directory to the Tripwire database.
Mark a directory hierarchy for inclusion:
/etc -> rule
            
Immediately after, mark some files to be excluded:
!/etc/not.me
!/etc/not.me.either
You can exclude a subdirectory too:
!/etc/dirname
The exclamation mark (!) prevents the given file or subdirectory from being added to Tripwire's database.
The Tripwire manual has detailed documentation on the policy file format.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Checking Windows VFAT Filesystems
When checking the integrity of a VFAT filesystem, tripwire always complains that files have changed when they haven't.
Tell tripwire not to compare inode numbers.
               filename -> rule -i ;
For example:
/mnt/windows/system  -> $(SEC_BIN) -i ;
Modern Linux kernels do not assign constant inode numbers in VFAT filesystems.
The Tripwire manual has detailed documentation on the policy file format.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Verifying RPM-Installed Files
You have installed some RPM packages, perhaps long ago, and want to check whether any files have changed since the installation.
# rpm -Va [packages]
Debian Linux has a similar tool called debsums .
If your system uses RPM packages for installing software, this command conveniently compares the installed files against the RPM database. It notices changes in file size, ownership, timestamp, MD5 checksum, and other attributes.
The output is a list of (possibly) problematic files, one per line, each preceded by a string of characters with special meaning. For example:
$ rpm -Va
SM5....T c /etc/syslog.conf
.M......   /var/lib/games/trojka.scores
missing    /usr/lib/perl5/5.6.0/Net/Ping.pm
..?.....   /usr/X11R6/bin/XFree86
.....U..   /dev/audio
S.5....T   /bin/ls
The first line indicates that syslog.conf has an unexpected size (S), permissions (M), checksum (5), and timestamp (T). This is perhaps not surprising, since syslog.conf is a configuration file you'd be likely to change after installation. In fact, that is exactly what the "c" means: a configuration file. Similarly, troijka.scores is a game score file likely to change. The file Ping.pm has apparently been removed, and XFree86 could not be checked (?) because we didn't run rpm as root. The last two files definitely deserve investigation: /dev/audio has a new owner (U), and /bin/ls has been modified.
This technique is valid only if your RPM database and rpm command have not been compromised by an attacker. Also, it checks only those files installed from RPMs.
rpm(8) lists the full set of file attributes checked.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Integrity Checking with rsync
You want to snapshot and check your files but you can't use Tripwire. You have lots of disk space on a remote machine.
Use rsync to copy your important files to the remote machine. Use rsync again to compare the copies on the two machines.
Let trippy and trusty be your two machines as before. You want to ensure the integrity of the files on trippy.
  1. On trippy, store the rsync binary on a CD-ROM mounted at /mnt/cdrom.
  2. On trusty, copy the files from trippy:
    trusty# rsync -a -v --rsync-path=/mnt/cdrom/rsync --rsh=/usr/bin/ssh \
                       trippy:/ /data/trippy-backup
  3. Check integrity from trusty:
    trusty# rsync -a -v -n --rsync-path=/mnt/cdrom/rsync --rsh=/usr/bin/ssh \
                         trippy:/ /data/trippy-backup
The first rsync actually performs copying, while the second merely reports differences, thanks to the -n option. If there are no differences, the output will look something like this:
receiving file list ... done
wrote 16 bytes   read 7478 bytes   4996.00 bytes/sec
total size is 3469510  speedup is 462.97
but if any files differ, their names will appear after the "receiving file list" message:
receiving file list ... done
/bin/ls
/usr/sbin/sshd
wrote 24 bytes   read 7486 bytes   5006.67 bytes/sec
total size is 3469510  speedup is 461.99
Any listed files—in this case /bin/ls and /usr/sbin/sshd—should be treated as suspicious.
This method has important limitations, most notably that it does not check inode numbers or device numbers. A real integrity checker is better.
rsync(1).
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Integrity Checking Manually
You can't use Tripwire for administrative or political reasons, but you want to snapshot your files for later comparison. You don't have enough disk space to mirror your files.
Run a script like the following that stores pertinent information about each file of interest, such as checksum, inode number, and timestamp:
#!/bin/sh
for file
do
    date=`/usr/bin/stat "$file" | /bin/grep '^Modify:' | /usr/bin/cut -f2- -d' '`
    sum=`/usr/bin/md5sum "$file" | /usr/bin/awk '{print $1}'`
    inode=`/bin/ls -id "$file" | /usr/bin/awk '{print $1}'`
    /bin/echo -e "$file\t$inode\t$sum\t$date"
done
Store this script as /usr/local/bin/idfile (for example). Use find to run this script on your important files, creating a snapshot. Store it on read-only media. Periodically create a new snapshot and compare the two with diff .
This is not a production-quality integrity checker. It doesn't track file ownership or permissions. It checks only ordinary files, not directories, device special files, or symbolic links. Its tools (md5sum, stat, etc.) are not protected against tampering.
  1. Run the idfile script to create a snapshot file:
    # find /dir -xdev -type f -print0 | \ 
      xargs -0 -r /usr/local/bin/idfile > /tmp/my_snapshot
    This creates a snapshot file, basically a poor man's Tripwire database.
    /bin/arch   2222   7ba4330c353be9dd527e7eb46d27f923   Wed Aug 30 17:54:25 2000
    /bin/ash    2194   cef0493419ea32a7e26eceff8e5dfa90   Wed Aug 30 17:40:11 2000
    /bin/awk    2171   b5915e362f1a33b7ede6d7965a4611e4   Sat Feb 23 23:37:18 2002
    ...
    Note that idfile will process /tmp/my_snapshot itself, which will almost certainly differ next time you snapshot. You can use grep -v to eliminate the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: Firewalls with iptables and ipchains
Your network's first barrier against unwanted infiltrators is your firewall. You do have a firewall in place, right? If you think you don't need one, monitor your incoming network traffic some time: you might be amazed by the attention you're receiving. For instance, one of our home computers has never run a publicly accessible service, but it's hit 10-150 times per day by Web, FTP, and SSH connection requests from unfamiliar hosts. Some of these could be legitimate, perhaps web crawlers creating an index; but when the hits are coming from dialup12345.nowhere.aq in faraway Antarctica, it's more likely that some script kiddie is probing your ports. (Or the latest Windows worm is trying in vain to break in.)
Linux has a wonderful firewall built right into the kernel, so you have no excuse to be without one. As a superuser, you can configure this firewall with interfaces called ipchains and iptables. ipchains models a stateless packet filter. Each packet reaching the firewall is evaluated against a set of rules. Stateless means that the decision to accept, reject, or forward a packet is not influenced by previous packets.
iptables, in contrast, is stateful: the firewall can make decisions based on previous packets. Consider this firewall rule: "Drop a response packet if its associated request came from server.example.com." iptables can manage this because it can associate requests with responses, but ipchains cannot. Overall, iptables is significantly more powerful, and can express complex rules more simply, than ipchains.
ipchains is found in kernel Versions 2.2 and up, while iptables requires kernel Version 2.4 or higher. The two cannot be used together: one or the other is chosen when the kernel is compiled.
A few caveats before you use the recipes in this chapter:
  • We're definitely not providing a complete course in firewall security. ipchains and iptables can implement complex configurations, and we're just scratching the surface. Our goal, as usual, is to present useful recipes.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Enabling Source Address Verification
You want to prevent remote hosts from spoofing incoming packets as if they had come from your local machine.
Turn on source address verification in the kernel. Place the following code into a system boot file (i.e., linked into the /etc/rc.d hierarchy) that executes before any network devices are enabled:
#!/bin/sh
echo -n "Enabling source address verification..."
echo 1 > /proc/sys/net/ipv4/conf/default/rp_filter
echo "done"
Or, to perform the same task after network devices are enabled:
#!/bin/sh
CONF_DIR=/proc/sys/net/ipv4/conf
CONF_FILE=rp_filter
if [ -e ${CONF_DIR}/all/${CONF_FILE} ]; then
        echo -n "Setting up IP spoofing protection..."
        for f in ${CONF_DIR}/*/${CONF_FILE}; do
                echo 1 > $f
        done
        echo "done"
fi
A quicker method may be to add this line to /etc/sysctl.conf:
net.ipv4.conf.all.rp_filter = 1
and run sysctl to reread the configuration immediately:
# sysctl -p
Source address verification is a kernel-level feature that drops packets that appear to come from your internal network, but do not. Enabling this feature should be your first network-related security task. If your kernel does not support it, you can set up the same effect using firewall rules, but it takes more work. [Recipe 2.2]
sysctl(8). Source address verification is explained in the IPCHAINS-HOWTO at http://www.linux.org/docs/ldp/howto/IPCHAINS-HOWTO-5.html#ss5.7.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Blocking Spoofed Addresses
You want to prevent remote hosts from pretending to be local to your network.
For a single machine, to prevent remote hosts from pretending to be that machine, use the following:
For iptables:
# iptables -A INPUT -i external_interface -s your_IP_address -j REJECT
For ipchains:
# ipchains -A input -i external_interface -s your_IP_address -j REJECT
If you have a Linux machine acting as a firewall for your internal network (say, 192.168.0.*) with two network interfaces, one internal and one external, and you want to prevent remote machines from spoofing internal IP addresses to the external interface, use the following:
For iptables:
# iptables -A INPUT -i external_interface -s 192.168.0.0/24 -j REJECT
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Blocking All Network Traffic
You want to block all network traffic by firewall.
For iptables:
# iptables -F
# iptables -A INPUT -j REJECT
# iptables -A OUTPUT -j REJECT
# iptables -A FORWARD -j REJECT
For ipchains:
# ipchains -F
# ipchains -A input -j REJECT
# ipchains -A output -j REJECT
# ipchains -A forward -j REJECT
You could also stop your network device altogether with ifconfig [Recipe 3.2] or even unplug your network cable. It all depends on what level of control you need.
The target REJECT sends an error packet in response to the incoming packet. You can tailor iptables 's error packet using the option —reject-with. Alternatively, you can specify the targets DROP (iptables) and DENY (ipchains) that simply absorb the packet and produce no response. See Drop Versus Reject.
iptables(8), ipchains(8).
Rules in a chain are evaluated in sequential order.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Blocking Incoming Traffic
You want to block all incoming network traffic, except from your system itself. Do not affect outgoing traffic.
For iptables :
# iptables -F INPUT
# iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT
# iptables -A INPUT -j REJECT
For ipchains :
# ipchains -F input
# ipchains -A input -i lo -j ACCEPT
# ipchains -A input -p tcp --syn -j REJECT
# ipchains -A input -p udp --dport 0:1023 -j REJECT
The iptables recipe takes advantage of statefulness, permitting incoming packets only if they are part of established outgoing connections. All other incoming packets are rejected.
The ipchains recipe accepts all packets from yourself. The source can be either your actual IP address or the loopback address, 127.0.0.1; in either case, the traffic is delivered via the loopback interface, lo. We then reject TCP packets that initiate connections (—syn) and all UDP packets on privileged ports. This recipe has a disadvantage, however, which is that you have to list the UDP port numbers. If you run other UDP services on nonprivileged ports (1024 and up), you'll have to modify the port list. But even so there's a catch: some outgoing services allocate a randomly numbered, nonprivileged port for return packets, and you don't want to block it.
Don't simply drop all input packets, e.g.:
# ipchains -F input
# ipchains -A input -j REJECT
as this will block responses returning from your legitimate outgoing connections.
iptables also supports the —syn flag to process TCP packets:
# iptables -A INPUT -p tcp --syn -j REJECT
As with ipchains, this rule blocks TCP/IP packets used to initiate connections. They have their SYN bit set but the ACK and FIN bits unset.
If you block all incoming traffic, you will block ICMP messages required by Internet standards (RFCs); see
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Blocking Outgoing Traffic
Drop all outgoing network traffic. If possible, do not affect incoming traffic.
For iptables :
# iptables -F OUTPUT
# iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT
# iptables -A OUTPUT -j REJECT
For ipchains :
# ipchains -F output
# ipchains -A output -p tcp ! --syn -j ACCEPT
# ipchains -A output -j REJECT
Depending on your shell, you might need to escape the exclamation point.
This recipe takes advantage of iptables's statefulness. iptables can tell the difference between outgoing traffic initiated from the local machine and outgoing traffic in response to established incoming connections. The latter is permitted, but the former is not.
ipchains is stateless but can recognize (and reject) packets with the SYN bit set and the ACK and FIN bits cleared, thereby permitting established and incoming TCP connections to function. However, this technique is insufficient for UDP exchanges: you really need a stateful firewall for that.
iptables(8), ipchains(8).
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Blocking Incoming Service Requests
You want to block connections to a particular network service, for example, HTTP.
To block all incoming HTTP traffic:
For iptables :
# iptables -A INPUT -p tcp --dport www -j REJECT
For ipchains :
# ipchains -A input -p tcp --dport www -j REJECT
To block incoming HTTP traffic but permit local HTTP traffic:
For iptables :
# iptables -A INPUT -p tcp -i lo --dport www -j ACCEPT
# iptables -A INPUT -p tcp --dport www -j REJECT
For ipchains :
# ipchains -A input -p tcp -i lo --dport www -j ACCEPT
# ipchains -A input -p tcp --dport www -j REJECT
You can also block access at other levels such as TCP-wrappers. [Recipe 3.9][Recipe 3.11]
iptables(8), ipchains(8).
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Blocking Access from a Remote Host