Tải bản đầy đủ (.pdf) (50 trang)

Linux System Administration phần 9 potx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (811.5 KB, 50 trang )

Your firewall can be as restrictive or open as you wish. Perhaps you simply want to prevent people
outside your firewall from being able to Telnet into your system. You may do this by having the
firewall reject incoming packets that are required to set up such connections. In an alternate
scenario, you might want to filter packets from inside your local area network to prevent anyone
from reaching a given IP address. How restrictive your firewall is depends upon the rules you set in
IP chains or IP tables.
The functionality for a packet−filtering firewall is built into the Linux kernel, although you must
recompile with certain network kernel options turned on. This is outlined in the Firewall−HOWTO,
maintained by Mark Grennan. Basically, in selecting options, you need to include routing,
defragmentation, IP masquerading, and multicast routing (if you intend to do multicasting). Older
kernels in the 1.x.x era used a package called ipfwadm, which is no longer supported. Kernels since
2.2.13 use IP chains instead; we'll talk about that in the "IP Chains" section below. The 2.4 kernels
use a new firewall utility, known as iptables.
Read the Firewall and Proxy Server HOWTO if you are building a firewall! It will probably be helpful
to read the Linux Networking HOWTO and the Linux IPCHAINS HOWTO as well. Most HOWTOs
can be found on Red Hat's site at For information on
IP tables, look for information under the heading of NetFilter on />A filtering firewall does not require high−end computer power. If you have an old 486DX66 or better
with at least 16MB of memory, 300–500MB of hard drive space, and network connections, you will
do fine. In reality, more often the system is at least a Pentium or a Pentium II with 32−64MB of
memory and a 20GB hard drive; the point is that you don't have to max out the specifications if the
system is only to be used as a filtering firewall since the work of filtering packets doesn't heavily tax
a system. More memory will be beneficial if the system requires extremely large IP tables rulesets
or if a great deal of state information will be kept.
IP Chains
The IP Chains package makes managing the kernel's inherent firewall capabilities simpler. An IP
chain is a set of rules to be considered when a data packet is attempting to pass through the
firewall. The default IP Chains configuration includes three permanent chains: input, output, and
forward. The input chain governs incoming packets, the forward chain manages packets destined
for another host, and outgoing packets are subjected to the rules of the output chain. You may add
and edit other chains as needed. The IP Chains process is fairly simple and is illustrated in Figure
15.3.


389
Figure 15.3: The IP Chains process
In an alternate scenario when the loopback interface is used for debugging, a packet that is sent
from a local process and destined for a local process passes through the output chain right into the
input chain.
Rules and Rulesets
An IP Chains rule can specify the packet source with the −s option, the protocol with the −p option,
the destination with the −d option, the chain to which packets are to be sent if the rule matches with
the −j (jump) option, and the port. There are two types of rules: those that affect an entire chain and
those that affect the rules within a chain.
These options affect an entire chain:
−N Create a new chain.
−X Delete an empty chain.
−P Change the policy for a built−in chain.
−L List the rules in a chain.
−F Flush the rules out of a chain.
−Z Zero the packet and byte counters on all rules within a chain.
These options affect rules within a chain:
390
−A Append a new rule to a chain.
−I Insert a new rule at some position within a chain.
−R Replace a rule at some position within a chain.
−D Delete a rule at some position within a chain if passed a numeric value or delete the
first rule that matches if passed a rule to match.
Now let's look at a few sample rules. This rule denies all packets from 192.168.0.11:
ipchains −A input −s 192.168.0.11 −j DENY
This rule denies all packets that are not from 192.168.0.11:
ipchains −A input −s !192.168.0.11 −j DENY
This displays a list of all rules for the input chain:
ipchains −L input

Both of the following rules delete the seventh rule in the input chain, the first by matching the rule
number and the second by matching the rule itself:
ipchains −D input 7
ipchains −D input −s 192.168.1.11 −j DENY
Finally, this rule flushes the input chain:
ipchains input −F
Now perhaps we want to deny FTP to the outside world but allow it on our internal network. We do
this by adding a rule to the input chain that rejects FTP requests that come in on eth0 but accepts
those coming in on eth1. To do this, we must run two separate ipchains commands:
ipchains −A input −p tcp −i eth0 −−dport ftp −j REJECT
ipchains −A input −p tcp −i eth1 −−dport ftp −j ACCEPT
Once your ipchains file is properly set up, you will need to make it run at each bootup. Red Hat
offers the ipchains−save and ipchains−restore binaries for this purpose. Run ipchains−save
redirecting its output to /etc/ipchains.conf in order to save your rules to the ipchains.conf file:
ipchains−save > /etc/ipchains.conf
Next add the ipchains−restore command to /etc/rc.d/rc.local so that it will run automatically at
bootup. You could just as easily add the ipchains commands that we stored in /etc/ipchains.conf to
/etc/rc.d/rc.local, but if you expect to make a lot of changes to the ipchains configuration, the first
method is more versatile.
Listing 15.7 contains an example ipchains file. This file is set up to do IP masquerading for the
192.168.1 internal network.
Listing 15.7: A Sample ipchains File
#!/bin/bash
/bin/echo −n "Setting up IP Chains: ipchains"
/bin/echo "."
391
#
# New ipchains commands for somedomain.com
#
# Define some variables

# Any system anywhere
export ANY="0.0.0.0/0"
# The Internet connection
export INET="−W eth0"
# The local network port
export LETH="−V 192.168.1.1 −W eth1"
# The local network
export LNET="192.168.1.1/255.255.255.0"
# The firewall (this system on the local network)
export FWALL="192.168.1.1/32"
# The firewall's Internet address (if known or determinable)
export INET_IP="225.126.21.1"
# Some ipfwadm flags for the TCP protocol
export OpenNewConn="−y"
export ConnEstablished="−k"
# Flush Old Rules
/sbin/ipchains input −F
/sbin/ipchains output −F
# Load masquerade support modules
/sbin/modprobe ip_masq_ftp
/sbin/modprobe ip_masq_irc
/sbin/modprobe ip_masq_raudio
# Create forwarding chain and set reject as default
/sbin/ipchains −N forward
/sbin/ipchains −A forward −j reject −S #LNET −d $LNET
/sbin/ipchains −A forward −j reject −S #LNET −d 10.0.0.0/8
/sbin/ipchains −A forward −j reject −S #LNET −d 172.16.0.0/12
/sbin/ipchains −A forward −j reject −S #LNET −d 192.168.0.0/16
# Masquerade these ip's w/ default as all
/sbin/ipchains −A forward −j MASQ −s 192.168.1.1/32 −i eth0 −d $ANY

/sbin/ipchains −A forward −j MASQ −s 192.168.1.2/32 −i eth0 −d $ANY
/sbin/ipchains −A forward −j MASQ −s 192.168.1.3/32 −i eth0 −d $ANY
/sbin/ipchains −A forward −j MASQ −s 192.168.1.4/32 −i eth0 −d $ANY
/sbin/ipchains −A forward −j MASQ −s 192.168.1.5/32 −i eth0 −d $ANY
/sbin/ipchains −A forward −j MASQ −s 192.168.1.6/32 −i eth0 −d $ANY
/sbin/ipchains −A forward −j MASQ −s 192.168.200.206/32 −i eth0 −d $ANY
# Sets telnet and ftp to be instant, and ftp−data to have fast
# throughput
/sbin/ipchains −A output −p tcp −d 0.0.0.0/0 telnet −t 0x01 0x10
/sbin/ipchains −A output −p tcp −d 0.0.0.0/0 ftp −t 0x01 0x10
/sbin/ipchains −A output −p tcp −s 0.0.0.0/0 ftp−data −t 0x01 0x08
# Default policy: allow all traffic unless explicitly blocked
#/sbin/ipchains −N input
#/sbin/ipchains −A input −P accept
#/sbin/ipchains −N ouput
#/sbin/ipchains −A output −P accept
# Tell the kernel to allow ip forwarding
/bin/echo "1" > /proc/sys/net/ipv4/ip_forward
Administrator's Logbook: IP Chains
392
System: E12345678
Added the following rule to prevent message traffic from 192.168.1.23 from being passed on:
ipchains −A input −s 192.168.1.23 −j DENY
Added the following rules to deny ftp requests coming in from the outside world (eth0) but accept
internal network (eth1) FTP requests:
ipchains −A input −p tcp −i eth0 −−dport ftp −j REJECT
ipchains −A input −p tcp −i eth1 −−dport ftp −j ACCEPT
IP Tables
The IP Tables package, more often called Netfilter, is a bit more sophisticated than IP Chains. IP
Chains establish a stateless firewall that doesn't concern itself with the ordering of packets received.

There is no mechanism for noticing that a packet arrived out of order or that a packet that was
expected wasn't received. The IP Tables package is a stateful firewall, which adds tracking of open
connections in a state table. There are three default tables: filter, nat, and mangle. We will discuss
the filter and nat tables here. The default filter table includes these permanent chains: INPUT,
OUTPUT, and FORWARD. Building on our IP Chains explanation, the use of these chains is rather
intuitive except for a couple of differences: whereas all incoming datagrams are sent to the IP
Chains input chain, only datagrams destined for the localhost are sent to the Netfilter INPUT chain;
datagrams destined for other hosts are sent to the FORWARD chain. Another key difference is that
the IP Chains output chain sees all outgoing packets regardless of where they originated. Netfilter's
OUTPUT chain only looks at packets originating in the localhost destination, ignoring those
datagrams being routed from a different host.
For masquerading, you'll need to use the nat table. This table has two chains: PREROUTING and
POSTROUTING. Use −t nat to specify that you want to affect the nat table.
You may still add and edit other chains as needed. The IP Tables process is illustrated in Figure
15.4.
393
Figure 15.4: The IP Tables process
Walking through the process, we see that a packet enters the system and is checked by checksum
to see if it is corrupted. If it is, it is denied; otherwise it is passed on to the sanity check, which
checks to see whether the packet is properly formatted. If it isn't, it is denied. If the packet passes
this test, it is evaluated as either a local packet or an external packet. Local packets are sent on to
the INPUT chain, which evaluates it against the INPUT chain ruleset, which drops, rejects, or sends
it through that process to the OUTPUT chain. External packets, those bound for external hosts, are
sent to the FORWARD chain. Once sent on to the FORWARD chain, the packet is checked against
that chain's ruleset and dropped, rejected, or sent on to the OUTPUT chain. The Netfilter method is
quite streamlined when compared to the IP Chains method that we discussed above. In order to use
IP Tables, you need to build the kernel with Netfilter support (must be kernel 2.3.15 or later) or
include it as a module.
Rules and Rulesets
Rules for IP Tables look a little different than IP Chains rules. First let's examine the syntax: A

Netfilter rule can specify the packet source with the −s option, the protocol with the −p option, the
destination with the −d option, the chain to which packets are to be sent if the rule matches with the
−j (jump) option, and the port. There are three types of rules now: those that affect an entire table,
those that affect an entire chain, and those that affect the rules within a chain. Use −t to specify a
table name. The default table is the filter table, but you'll use the nat table to affect masquerading.
394
The nat table has two chains: PREROUTING for incoming interfaces and POSTROUTING for
outgoing interfaces.
This option affects an entire table:
−t Names a specific table to act upon.
These options affect an entire chain:
−N Create a new chain.
−X Delete an empty chain.
−E Rename a chain.
−P Change the policy for a built−in chain.
−L List the rules in a chain.
−F Flush the rules out of a chain.
−Z Zero the packet and byte counters on all rules within a chain.
These options affect rules within a chain:
−A Append a new rule to a chain.
−I Insert a new rule at some position within a chain.
−R Replace a rule at some position within a chain.
−D Delete a rule at some position within a chain if passed a numeric value or delete the
first rule that matches if passed a rule to match.
Now let's look at the sample rules we used with IP Chains above, rewritten in IP Tables syntax.
This rule drops all packets from 192.168.0.11:
iptables −A INPUT −s 192.168.0.11 −j DROP
This rule drops all packets that are not from 192.168.0.11:
iptables −A INPUT −s !192.168.0.11 −j DROP
This displays a list of all rules for the input chain:

iptables −L INPUT
To list the rules in the nat table, add the −t flag instead of a chain name.
iptables −L −t nat
Both of the following rules delete the seventh rule in the input chain, the first by matching the rule
number and the second by matching the rule itself:
iptables −D INPUT 7
iptables −D INPUT −s 192.168.1.11 −j DROP
Finally, this rule flushes the input chain:
iptables INPUT −F
To flush the rules of the nat table only:
395
iptables −F −t nat
Now perhaps we want to deny FTP to the outside world but allow it on our internal network.
Assuming that we have two network cards, eth0 and eth1, and that eth0 is the one that connects to
the Internet, we do this by adding a rule to the input chain that rejects FTP requests that come in on
eth0 but accepts those coming in on eth1. To do this, we must run two separate iptables
commands:
iptables −A INPUT −p tcp −i eth0 −−source−port ftp −j REJECT
iptables −A INPUT −p tcp −i eth1 −−source−port ftp −j ACCEPT
Once your Netfilter file is properly set up, you will need to make it run at each bootup. Red Hat
offers the iptables−save and iptables−restore binaries for this purpose. Run iptables−save
redirecting its output to /etc/iptables.conf in order to save your rules to the iptables.conf file:
iptables−save > /etc/iptables.conf
To restore from /etc/iptables.conf, run iptables−restore with redirection from /etc/iptables.conf:
iptables−restore < /etc/iptables.conf
Next add the ipchains−restore command to /etc/rc.d/rc.local so that it will run automatically at
bootup. You could just as easily add the Netfilter commands that we stored in /etc/iptables.conf to
/etc/rc.d/rc.local, but if you expect to make a lot of changes to the configuration, the first method is
more versatile. Still better is adding an IP Tables script to /etc/init.d or wherever your distribution
puts its startup scripts. Red Hat 7.3 does this by default with the script shown in Listing 15.8:

Listing 15.8: A Sample Netfilter Startup File
#!/bin/sh
#
# Startup script to implement /etc/sysconfig/iptables pre−defined rules.
#
# chkconfig: 2345 08 92
#
# description: Automates a packet filtering firewall with iptables.
#
# by , based on the ipchains script:
# Script Author: Joshua Jensen <>
# −− hacked up by gafton with help from notting
# modified by Anton Altaparmakov <>:
# modified by Nils Philippsen <>
#
# config: /etc/sysconfig/iptables
# Source 'em up
. /etc/init.d/functions
IPTABLES_CONFIG=/etc/sysconfig/iptables
if [ ! −x /sbin/iptables ]; then
exit 0
fi
KERNELMAJ=`uname −r | sed −e 's,\ *,,'`
KERNELMIN=`uname −r | sed −e 's,[^\.]*\.,,' −e 's,\ *,,'`
if [ "$KERNELMAJ" −lt 2 ] ; then
396
exit 0
fi
if [ "$KERNELMAJ" −eq 2 −a "$KERNELMIN" −lt 3 ] ; then
exit 0

fi
if /sbin/lsmod 2>/dev/null |grep −q ipchains ; then
# Don't do both
exit 0
fi
iftable() {
if fgrep −qsx $1 /proc/net/ip_tables_names; then
iptables −t "$@"
fi
}
start() {
# don't do squat if we don't have the config file
if [ −f $IPTABLES_CONFIG ]; then
# If we don't clear these first, we might be adding to
# pre−existing rules.
action $"Flushing all current rules and user defined chains:"
iptables −F
action $"Clearing all current rules and user defined chains:"
iptables −X
chains=`cat /proc/net/ip_tables_names 2>/dev/null`
for i in $chains; do iptables −t $i −F; done && \
success $"Flushing all current rules and user defined
chains:" || \
failure $"Flushing all current rules and user defined
chains:"
for i in $chains; do iptables −t $i −X; done && \
success $"Clearing all current rules and user defined
chains:" || \
failure $"Clearing all current rules and user defined
chains:"

for i in $chains; do iptables −t $i −Z; done
echo $"Applying iptables firewall rules: "
grep −v "^[[:space:]]*#" $IPTABLES_CONFIG | grep −v
'^[[:space:]]*$' | /sbin/iptables−restore −c && \
success $"Applying iptables firewall rules" || \
failure $"Applying iptables firewall rules"
echo
touch /var/lock/subsys/iptables
fi
}
stop() {
chains=`cat /proc/net/ip_tables_names 2>/dev/null`
for i in $chains; do iptables −t $i −F; done && \
success $"Flushing all chains:" || \
failure $"Flushing all chains:"
for i in $chains; do iptables −t $i −X; done && \
success $"Removing user defined chains:" || \
failure $"Removing user defined chains:"
echo −n $"Resetting built−in chains to the default ACCEPT
policy:"
iftable filter −P INPUT ACCEPT && \
397
iftable filter −P OUTPUT ACCEPT && \
iftable filter −P FORWARD ACCEPT && \
iftable nat −P PREROUTING ACCEPT && \
iftable nat −P POSTROUTING ACCEPT && \
iftable nat −P OUTPUT ACCEPT && \
iftable mangle −P PREROUTING ACCEPT && \
iftable mangle −P OUTPUT ACCEPT && \
success $"Resetting built−in chains to the default ACCEPT policy"

|| \
failure $"Resetting built−in chains to the default ACCEPT policy"
echo
rm −f /var/lock/subsys/iptables
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
# "restart" is really just "start" as this isn't a daemon,
# and "start" clears any pre−defined rules anyway.
# This is really only here to make those who expect it happy
start
;;
condrestart)
[ −e /var/lock/subsys/iptables ] && start
;;
status)
tables=`cat /proc/net/ip_tables_names 2>/dev/null`
for table in $tables; do
echo $"Table: $table"
iptables −t $table −−list
done
;;
panic)
echo −n $"Changing target policies to DROP: "

iftable filter −P INPUT DROP && \
iftable filter −P FORWARD DROP && \
iftable filter −P OUTPUT DROP && \
iftable nat −P PREROUTING DROP && \
iftable nat −P POSTROUTING DROP && \
iftable nat −P OUTPUT DROP && \
iftable mangle −P PREROUTING DROP && \
iftable mangle −P OUTPUT DROP && \
success $"Changing target policies to DROP" || \
failure $"Changing target policies to DROP"
echo
iftable filter −F INPUT && \
iftable filter −F FORWARD && \
iftable filter −F OUTPUT && \
iftable nat −F PREROUTING && \
iftable nat −F POSTROUTING && \
iftable nat −F OUTPUT && \
iftable mangle −F PREROUTING && \
iftable mangle −F OUTPUT && \
398
success $"Flushing all chains:" || \
failure $"Flushing all chains:"
iftable filter −X INPUT && \
iftable filter −X FORWARD && \
iftable filter −X OUTPUT && \
iftable nat −X PREROUTING && \
iftable nat −X POSTROUTING && \
iftable nat −X OUTPUT && \
iftable mangle −X PREROUTING && \
iftable mangle −X OUTPUT && \

success $"Removing user defined chains:" || \
failure $"Removing user defined chains:"
;;
save)
echo −n $"Saving current rules to $IPTABLES_CONFIG: "
touch $IPTABLES_CONFIG
chmod 600 $IPTABLES_CONFIG
/sbin/iptables−save −c > $IPTABLES_CONFIG 2>/dev/null && \
success $"Saving current rules to $IPTABLES_CONFIG" || \
failure $"Saving current rules to $IPTABLES_CONFIG"
echo
;;
*)
echo $"Usage: $0 {start|stop|restart|condrestart|status|panic|save}"
exit 1
esac
exit 0
Listing 15.9 contains an example iptables.conf file. This file is set up to do IP masquerading for the
192.168.1 internal network and is generated with the iptables−save command. The syntax used in
this file is slightly different than if each command were typed at the command line.
Listing 15.9: A Sample iptables.conf File as Saved with iptables−save
*mangle
:PREROUTING ACCEPT [1508811:283630700]
:OUTPUT ACCEPT [492803:54921745]
COMMIT
# Completed on Sun Mar 24 08:35:38 2002
# Generated by iptables−save v1.2.4 on Sun Mar 24 08:35:38 2002
*nat
:PREROUTING ACCEPT [11027:587954]
:POSTROUTING ACCEPT [26364:1785343]

:OUTPUT ACCEPT [26284:1782075]
[0:0] −A POSTROUTING −s 192.168.1.3 −j MASQUERADE
[0:0] −A POSTROUTING −s 192.168.1.4 −j MASQUERADE
[2:113] −A POSTROUTING −s 192.168.1.5 −j MASQUERADE
[0:0] −A POSTROUTING −s 192.168.1.6 −j MASQUERADE
COMMIT
# Completed on Sun Mar 24 08:35:38 2002
# Generated by iptables−save v1.2.4 on Sun Mar 24 08:35:38 2002
*filter
:INPUT ACCEPT [387120:48095941]
:FORWARD ACCEPT [1041504:200933897]
:OUTPUT ACCEPT [492803:54921745]
[3:108] −A INPUT −p icmp −m icmp −−icmp−type 8 −m limit −−limit 1/sec −j
ACCEPT
399
[0:0] −A INPUT −i eth0 −p tcp −m limit −−limit 3/hour −m tcp −−sport 22 −j
ACCEPT
[0:0] −A INPUT −i eth0 −p tcp −m limit −−limit 3/hour −m tcp −−sport 901 −j ACCEPT
[0:0] −A INPUT −i eth0 −p udp −m udp −−sport 22 −j ACCEPT
[0:0] −A INPUT −i eth0 −p udp −m udp −−sport 901 −j ACCEPT
[12169:6468491] −A INPUT −i eth0 −p tcp −m tcp −−sport 80 −j ACCEPT
[0:0] −A INPUT −i eth1 −j ACCEPT
[0:0] −A INPUT −i eth0 −p tcp −m tcp −−sport 80 −j ACCEPT
[20928:2481411] −A INPUT −i eth0 −m state −−state RELATED,ESTABLISHED −j
ACCEPT
COMMIT
# Completed on Sun Mar 24 08:35:40 2002
The Proxy Server
While a packet−filtering firewall handles filtering at the network level, a proxy server works at the
application level. The filtering firewall knows nothing of which application sent the packet—only the

IP address of the machine that sent it and the destination IP—but the proxy server receives data
directly from an application that is set up to talk to that specific proxy on that particular port. For
example, Netscape may be configured to send all requests to a proxy server that will get the
requested page and return it to the Netscape application. The proxy server may also maintain a
cache of the last pages visited and check each page against that cache before going onto the
Internet to retrieve the requested page.
The proxy server can reside on your firewall machine (the topology looks the same as in Figure 15.2
shown earlier), on a different machine inside the firewall (as in Figure 15.4), or connected to the
Internet and the local area network without the benefit of a firewall. It is usually preferable to have
as little outside the firewall as possible, so putting the proxy server on a different machine that is
protected by the firewall is a good idea. Sometimes the proxy is combined with the firewall, as
shown in Figure 15.5.
400
Figure 15.5: A combined proxy/firewall implementation
In this setup, the proxy server intercepts any Web requests coming from clients within the firewall
and checks them against an access control list, which details the sites for which access must be
denied. If the requested Web page is not on this list, the request is processed normally, going either
directly out on the Web or through a firewall for further processing. If the request successfully
passes through the ipchains or iptables filtering on the firewall, the retrieved Web page is sent back
to the requestor. If the requested Web page is on the control list, the requesting machine receives a
message indicating that the URL is not accessible or not valid. Many big companies set up a proxy
server to allow their users Internet access and also allow themselves to monitor the traffic.
A proxy server is much more resource−intensive than a filtering firewall, since it creates a new
process for each user who connects to it. If you have a lot of traffic, you'll need at least a Pentium II
with 64MB of memory, two network cards, and a 2GB or larger hard drive. This should handle
around 50 concurrent users. Understand again that this is the bare minimum system that should be
used. More common are Pentium III or Pentium IV proxy servers with 128–264MB of memory, two
network cards, and 20–30GB hard drives.
Proxy servers are useful, but their usefulness is limited to a small subset of the available network
services. Proxy servers are primarily used for HTTP. Linux systems can run a wide variety of

network services, and most Linux systems run several services by default. It is a good idea to turn
off any service that you don't intend to use; each service is a door that could potentially be opened
401
by a hacker scanning for open ports. If inetd (covered in Chapter 12) is used, you can add a pound
sign (#) to the start of each line in /etc/inetd.conf corresponding to the service you wish to disable
any services under inetd control, For services not under inetd control, use a tool like chkconfig.
chkconfig
In addition to services controlled through inetd or similar super servers, many services run directly,
linking up to ports without using a super server. You can usually shut these down by adjusting their
startup scripts, as described in Chapter 3. More commonly, however, is the use of chkconfig to shut
them down. The syntax of chkconfig is as follows:
chkconfig −−list [name]
chkconfig −−add [name]
chkconfig −−del [name]
chkconfig [−−level [levels]] [name] [on|off|reset]
The command chkconfig −−list without an argument will list all services and whether they are on or
off as appropriate. The service state will be listed by runlevel if not governed by xinetd or inetd. An
example is listed in Listing 15.10.
Listing 15.10: Sample chkconfig Output
syslog 0:off 1:off 2:on 3:on 4:on 5:on 6:off
crond 0:off 1:off 2:on 3:on 4:on 5:on 6:off
netfs 0:off 1:off 2:off 3:off 4:off 5:off 6:off
network 0:off 1:off 2:on 3:on 4:on 5:on 6:off
random 0:off 1:off 2:on 3:on 4:on 5:on 6:off
rawdevices 0:off 1:off 2:off 3:off 4:off 5:off 6:off
xfs 0:off 1:off 2:on 3:on 4:on 5:on 6:off
xinetd 0:off 1:off 2:off 3:on 4:on 5:on 6:off
reconfig 0:off 1:off 2:off 3:on 4:on 5:on 6:off
anacron 0:off 1:off 2:on 3:on 4:on 5:on 6:off
httpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off

apmd 0:off 1:off 2:on 3:off 4:off 5:off 6:off
atd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
named 0:off 1:off 2:off 3:off 4:off 5:off 6:off
keytable 0:off 1:off 2:on 3:on 4:on 5:on 6:off
gpm 0:off 1:off 2:on 3:on 4:on 5:on 6:off
ipchains 0:off 1:off 2:on 3:off 4:on 5:on 6:off
pcmcia 0:off 1:off 2:on 3:off 4:off 5:off 6:off
kdcrotate 0:off 1:off 2:off 3:off 4:off 5:off 6:off
kudzu 0:off 1:off 2:off 3:on 4:on 5:on 6:off
linuxconf 0:off 1:off 2:on 3:on 4:on 5:on 6:off
lpd 0:off 1:off 2:on 3:on 4:on 5:on 6:off
nfs 0:off 1:off 2:off 3:off 4:off 5:off 6:off
nfslock 0:off 1:off 2:off 3:off 4:off 5:off 6:off
sshd 0:off 1:off 2:on 3:on 4:on 5:on 6:off
identd 0:off 1:off 2:off 3:on 4:on 5:on 6:off
portmap 0:off 1:off 2:off 3:on 4:on 5:on 6:off
ypxfrd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
rstatd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
rusersd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
rwalld 0:off 1:off 2:off 3:off 4:off 5:off 6:off
rwhod 0:off 1:off 2:off 3:off 4:off 5:off 6:off
smb 0:off 1:off 2:off 3:off 4:off 5:off 6:off
sendmail 0:off 1:off 2:on 3:on 4:on 5:on 6:off
rhnsd 0:off 1:off 2:off 3:on 4:on 5:on 6:off
ypbind 0:off 1:off 2:off 3:off 4:off 5:off 6:off
yppasswdd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
402
ypserv 0:off 1:off 2:off 3:off 4:off 5:off 6:off
autofs 0:off 1:off 2:off 3:off 4:off 5:off 6:off
dhcpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off

mysqld 0:off 1:off 2:off 3:on 4:on 5:on 6:off
nscd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
ntpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
squid 0:off 1:off 2:off 3:off 4:off 5:off 6:off
vmware 0:off 1:off 2:off 3:on 4:off 5:off 6:off
apcupsd 0:off 1:off 2:off 3:on 4:off 5:off 6:off
mysqld−skip 0:off 1:off 2:off 3:off 4:off 5:off 6:off
postgresql 0:off 1:off 2:off 3:off 4:off 5:off 6:off
vmware.old.0 0:off 1:off 2:off 3:off 4:off 5:off 6:off
iptables 0:off 1:off 2:on 3:on 4:on 5:on 6:off
isdn 0:off 1:off 2:off 3:off 4:off 5:off 6:off
webmin 0:off 1:off 2:on 3:on 4:off 5:on 6:off
arkeia 0:off 1:off 2:off 3:off 4:off 5:off 6:off
xinetd based services:
amanda: off
amidxtape: off
finger: off
linuxconf−web: off
rexec: off
rlogin: off
rsh: off
auth: on
telnet: on
tftp: off
wu−ftpd: on
talk: off
ntalk: off
pop−3: on
chargen: off
chargen−udp: off

daytime: off
daytime−udp: off
echo: off
echo−udp: off
time: off
time−udp: off
sgi_fam: on
amandaidx: off
You can see from Listing 15.10 that there are many potential service vulnerabilities. As an example,
look at the Telnet service. This should definitely not be on. There are many more secure services
that accomplish the same mission; we use the secure shell (SSH). To turn off the Telnet service,
issue the following chkconfig command:
chkconfig telnet off
Any service that you do not absolutely need, should be turned off. If you only need a service rarely,
you might consider leaving it turned off until you need it and then turning it back off after use.
TCP Wrappers
TCP Wrappers is a host−based security layer that applies to daemons started by the inetd daemon.
The tcpd executable is a wrapper program that checks the /etc/hosts.allow and /etc/hosts.deny files
to determine whether or not the specified service should be run. When tcpd is started by inetd, it
reads the /etc/hosts.allow file and then /etc/hosts.deny. It grants or denies access based on the
403
rules in these two files.
Note Red Hat and Mandrake have both switched to xinetd as a replacement for both inetd and
TCP Wrappers. xinetd is discussed later in this chapter and in Chapter 12.
The /etc/hosts.allow file is a configuration file for the tcpd program. This file contains rules that
describe which hosts are allowed to access which services on the localhost. The format is as
follows:
service_list: host_list: [optional_command]
The service list is a comma−delimited list of service names to which this rule should be applied. The
ftpd, telnetd, and httpd services are examples. The keyword ALL or ALL EXCEPT may be used as

well. For instance, the following entry would allow all users to use all the local services except FTP:
ALL EXCEPT in.ftpd: ALL
The host list is a comma−delimited list of hostnames. The hostname may be represented as an IP
address, a specific hostname, or a hostname that uses wildcard characters to make the match. If
the hostname begins with a period, all hosts that share the string following that character will match
this rule. For example, the line below would match any attempt to Telnet in from a computer on the
somedomain.com network.
in.telnetd:.somedomain.com
If a numeric IP is used, it may be a full IP address for a specific machine or may consist of only the
partial address consisting of period−delimited numbers, causing any IP that starts with those
numbers to be matched. The host list may contain these keywords: ALL, LOCAL, PARANOID, and
EXCEPT. The ALL keyword would cause all hosts to match. The LOCAL keyword causes any local
login to match. The PARANOID keyword means that any host whose name is being spoofed will
match. The EXCEPT keyword is most often used in conjunction with ALL as in this example:
ALL EXCEPT hostname
This would match every host except the one that is listed. Another variation on this theme allows for
the rule to include an expression in the form:
12.34.56.0/255.255.254.0
This will be interpreted as a net/mask pair and will be matched if the net portion is equal to the
bitwise and of the address and the mask portion. Thus it would allow any address between
12.34.56.0 and 12.34.57.255 access to the system.
The optional_command argument identifies a command to be run every time the rule is matched.
For example, this might be used to send e−mail to the superuser when a certain host uses the
Telnet service. There are a number of expansions that may be used; they are covered in the
hosts.allow man page. Table 15.2 shows example entries from /etc/hosts.allow and what they
mean.
Table 15.2: Sample /etc/hosts.allow Entries
Line Meaning
in.ftpd:ALL EXCEPT 123.45.67.
404

FTP service is allowed to all except those on the
123.45.67.* domain.
ALL:ALL All services are allowed to all hosts.
ALL: 123.45.67.89 All services are allowed to the 123.45.67.89 host.
ipop3d:LOCAL The POP3 service is allowed to all local accounts.
in.talkd:host.somedomain.com,
host2.somedomain.com
The Talk service is allowed to both host and host2
in somedomain.com.
in.telnetd:.somedomain.com The Telnet service is allowed to any host on the
somedomain.com domain.
The /etc/hosts.deny file uses the same format as /etc/hosts.allow but serves the opposite purpose.
Lines in this file determine which hosts will be denied access to the specified service. The
/etc/hosts.allow and /etc/hosts.deny files work in conjunction. If the /etc/hosts.allow file listed the
rule ALL:ALL, allowing open access to all services, but the /etc/hosts.deny file included lines that
prohibited some hosts from using some services, /etc/hosts.deny would override the open access
for only the hosts and services specified. The deny file is the dominant file. An open system would
include the ALL:ALL entry in the /etc/hosts.allow file and nothing in the /etc/hosts.deny file, granting
access to everyone and denying it to no one. A completely closed system would have nothing in
/etc/hosts.allow and ALL:ALL in /etc/hosts.deny, thereby denying access to everyone.
The TCP Wrappers package includes two tools you can use to check your TCP security. There is
tcpdchk, which examines the /etc/inetd.conf, /etc/hosts.allow, and /etc/hosts.deny files for blatant
errors. To display a list of all access rules, use the following command:
# tcpdchk −v
The command will return a list of accesses explicitly permitted or denied, including the daemon to
which the access pertains, the client to whom the access pertains, and the actual access
determination. Here is an example:
>>> Rule /etc/hosts.allow line 18:
daemons: in.telnetd
clients: .ntrnet.net

access: granted
The other tool is the tcpdmatch utility, which allows you to test for a specific daemon and client. The
command looks like this:
# tcpdmatch in.telnetd www.macroshaft.com
The command will return the following if access is granted:
client: hostname www.macroshaft.com
client: address 117.4.137.45
server: process in.telnetd
access: granted
If the host is denied access, the response will look like this:
client: hostname www.macroshaft.com
client: address 117.4.137.45
server: process in.telnetd
matched: /etc/hosts.deny line 10
access: denied
405
Now that we know how to prevent access to the services available on your system, let's look at how
to handle them efficiently with xinetd.
xinetd
You will remember from Chapter 12 that the Internet Services Daemon (inetd) watches all ports
assigned to it and starts up the service associated with any port that has activity. This relieves each
process of the need to have a daemon running to check these ports. As of Red Hat 7.0, inetd is no
longer installed by default. Instead, the more secure extended Internet Service Daemon (xinetd) is
used. Most distributions are switching to xinetd as well. Both xinetd and inetd can be run
concurrently on a system. In fact, the author of the xinetd code suggests that an admin running an
RPC service do so from inetd. You can use your inetd.conf file to create a xinetd.conf file for the
non−RPC services.
The biggest reason that xinetd is more secure than inetd is due to its incorporation of something
similar to TCP Wrappers. In the xinetd.conf file as well as in the individual /etc/xinetd.d/ files, a
number of flags may be set that allow the administrator to determine who may run the service and

when they may do so. Listing 12.3 in Chapter 12 showed a sample xinetd service entry. You'll
remember that it included a user field to specify what username would be used to start the service.
Some services require that the root user control them, but others allow for a different user to control
them. If given a choice, always start the program with a non−root user so that any weaknesses in
the program behind the service do not render the entire system insecure. Although few services do
this by default, it is always good to use the interface flag to specify which interface to listen on for
that specific service. If attempts to exploit this service are made on interfaces that aren't explicitly
listed, xinetd ignores them instead of being exploited by them. You may use the log−specific flags to
alter what information is logged when xinetd runs the specified service. Two more flags important to
security are the no_access flag, which lists client machines not to be given access and the
only_from flag, which lists all clients authorized to access the service. The use of these flags can
help you establish a more secure system.
On a Red Hat 7.3 system, /usr/sbin/inetdconvert is a Python script that converts your inetd.conf file
to several files in a new /etc/xinetd.d directory. The command to use this tool to convert all services
that haven't already been converted is:
# inetdconvert −−convertremaining
A Perl script to convert the inetd.conf script into an xinetd.conf file is included with some other
versions of the xinetd package, located in the same directory as the binary. This script will be in
/usr/sbin if it exists on your system and may be run using the following command, assuming that the
executable is in /usr/sbin:
# /usr/sbin/xconv.pl < /etc/inetd.conf > /tmp/xinetd.conf
The transition creates several files within the /etc/xinetd.d directory. These files contain the
configuration options for each service managed by xinetd, so you'll need to edit these files to
configure xinetd to handle these services in the way you'd like.
Detecting Intrusion
Intruders usually, if not always, leave signs of intrusion. For some, being noticed is the game. Those
who don't want to be noticed need to stay on the system just long enough to adequately mask the
intrusion but still get off the system before someone notices that they are on. Crackers can alter the
406
logfiles in such a way as to make it almost impossible for someone to notice that they have been on

the system, but this takes a great deal of time. Many crackers simply delete the logfiles that would
identify them or cut out the portions that detail their activities. This leaves time gaps in the logs,
leaving a huge footprint. Still, you will usually only know that someone has been there and not know
who it was.
Sometimes intrusion is fairly easy to detect. Although crackers tend to try to disguise their intrusion,
there are always telltale signs. On a Red Hat system, the /var/log/secure file is very helpful. This file
logs all attempts to access services on the system along with information about whether the attempt
was successful or unsuccessful. Looking at this log, you can sometimes determine that someone is
trying to break in, because there are several failed attempts to access the system by a single IP or
hostname. Failed login attempts, by Telnet, FTP, or some other service, are easy to spot in the logs:
Jun 20 11:33:01 mydomain in.telnetd[1822]: refused connect
from 121.137.226.29
Jun 23 01:23:22 mydomain in.ftpd[19650: refused connect from
209.151.118.23
You can then use an nslookup on the IP to gain any information you can about where the attempted
logins are being instigated. Then add this IP to your /etc/hosts.deny file to make things a little
rougher. Most often, however, the IP is no longer valid, because the cracker was attempting to
access your system through a dial−up account. If the IP does resolve, don't immediately assume
that the would−be intruder actually has an account within that system; many times, crackers will
break into a system and use that system to try to access another system. Sometimes this continues
until the chain is quite long. In this case, the IP would belong to another of the cracker's victims and
not the cracker. Sometimes the cracker will delete the portions of the /var/log/secure and
/var/log/messages files that show the attempted breach, or the relevant logs may be deleted
entirely. These signs are all too often overlooked. System administrators must watch for blank spots
in the logs or missing logs as well as strange patterns in these same files.
In order to keep up with the evolving set of threats and vulnerabilities, system administrators must
take intrusion detection very seriously. As an old vulnerability is fixed, another one may be
introduced. The intruder may be a total stranger or the boss's son. It takes a concerted effort to stay
ahead. Intrusion detecting tools are one way to even the odds.
Applications for Detecting Intrusion

Intrusion detecting is a repetitive chore. It is difficult to keep up, since the break−in can happen at
any time—day or night. For this reason, it is better by far to run some intrusion−detecting
applications that will watch the system for you and notify you of suspicious activity or changes to
files. Several such applications are available. Here are just a few.
Tripwire
Tripwire for Linux, currently at version 2.4.2 for Windows and version 2.3.47 for Linux, produces a
baseline of your files and checks existing files against this baseline when requested to do so. Set it
up to run once a night. Look through it each morning, and after determining that all the changes
listed are valid, update the Tripwire database. You'll want to keep the baseline on a floppy or other
removable media to prevent an intruder from deleting or modifying it. The version for Linux is
available for free and is usually a few version numbers behind the Windows version as a result. To
download an open source version of Tripwire 2.3.47 for Linux or read about it, go to
A fairly recent version of Tripwire is included with most major distributions
of Linux.
407
Scanlogd
Scanlogd detects port scans and writes one line per scan through the syslog mechanism. Since
denial−of−service attacks typically send multiple packets to different ports to cause the system to be
too overwhelmed to handle legitimate requests, if any outside IP address sends several packets to
different ports on the same machine in a short time, scanlogd logs it. You can download it or read
more about it on />Deception Tool Kit
The Deception Tool Kit (DTK) is a very clever application that allows you to spy back at the
intruders who are spying on you. It fakes certain services, making it appear as if the system has
multiple vulnerabilities, and then captures information about any attempt to exploit them. For
instance, if the cracker tries to get the /etc/passwd file, DTK will send a fake one. The cracker then
wastes time trying to crack the passwords before realizing that it does not contain valid passwords
for the system. As a preventive measure, traffic on port 365 indicates that the target machine is
running DTK, thereby serving as a flag to the inquiring cracker and forcing reconsideration about
whether or not to pursue the attack on your system. Read more about it at />LogSentry
LogSentry is part of the Abacus Project being conducted by Psionic Software

( It examines the logfiles for possible security problems or
violations. It then generates a list of what it considers to be suspicious and e−mails that list to the
system administrator. It is free for use at any site. Download it at
/>This list of intrusion−detecting applications is not comprehensive. It is generally a good idea to
search the Internet for security sites that recommend applications of this type, since new ones are
made available quite often. Running one or more of these or other applications empowers you in
your attempts to prevent would−be intruders from cracking your system.
In Sum
Security is such a big topic that there is always more to be said. We have included the specific tools
that we use or have had recommended to us. You should search the Internet and talk to other
system administrators to find the specific products that meet the needs of your situation. Test
everything. Be very thorough and always watch your distribution's homepage for security advisories
and updated packages.
Now we go on to the topic of performance tuning. Knowing more tricks about how to get the most
performance for the buck can really get the boss's attention. Chapter 16 will get you started.
408
Chapter 16: Performance Tuning
Overview
Performance tuning is truly an art form. Those who are particularly skilled at it can often take a
system that seems barely sufficient for its intended task and make it fly. When a computer starts to
react sluggishly, whether because of new software that is taxing its resources or some other factor,
many people immediately conclude that a purchase order is the next step. Certainly the purchase of
a new, high−end system could speed things up, but often there is a less expensive way.
This chapter provides some performance tuning tips that will allow you to maximize the performance
of the computers in your system without the purchase of additional hardware. Use these tips to
enhance the computers you administer, and you'll enjoy a boost in performance.
The Elements of Performance
Many elements are used to measure performance. Certainly it is valuable to compare the amount of
time used to perform a task to the time used to perform the same task by a different computer or the
same computer after being configured differently. Memory usage, including swap memory usage, is

another factor that can be used to gauge performance. Hardware performance is often measured in
terms of number of failures and comparisons based on other factors like speed, and available
software is compared in a like manner.
Regardless of what element of performance you are testing, it is critical to ensure that the test
isolates that element so that variations in other areas do not influence the final outcome. If you want
to test CPU speed on two different systems, for example, you would not want one to have
significantly more memory or any other feature that would make the playing field uneven from the
beginning.
Hardware Performance
The hardware in a computer system is critical to its performance, so it's essential for system
administrators, like yourself, to be able to determine when new hardware will actually provide a
measurable benefit to the system in question. Making this determination requires measuring the
performance of existing hardware and determining if it's creating a bottleneck, which is a component
or process that limits the overall system performance. (Bottlenecks are covered in more detail
shortly.) There are several different classes of hardware that are potential sources of bottlenecks.
CPU Performance
The Central Processing Unit (CPU) of the computer carries most or all of the system's
computational load. It's the CPU that performs spreadsheet calculations, compresses data for
archiving, determines where to place a word when formatting a document, and so on. The CPU is
therefore a major contributor to a system's performance—and a potential source of bottlenecks.
The importance of the CPU varies from one system to another. On a computer that's used for very
CPU−intensive tasks, such as creating 3D animations or performing many types of scientific
simulations, the CPU is extraordinarily important. Other tasks, such as serving files, are more
affected by other subsystems, such as the disk or memory.
409
If your computer has an inadequate CPU, the most obvious fix is to upgrade the CPU. Roughly
speaking, a CPU cycle is a single "tick" of the CPU "clock"—most tasks require a fixed number of
CPU cycles to perform. Therefore, a process will run faster on a similar CPU with a higher clock
rate. Simply put, a 2 GHz Pentium 4 can finish a given process faster than a 1 GHz Pentium 4.
There may be other options, however. One trick is to get the computer to perform a task in fewer

CPU cycles than it otherwise would. You can sometimes reduce the number of CPU cycles required
to run a program by recompiling the program with more efficient compiler options. Of most
importance, most x86 Linux distributions use 386 optimizations, but if the computer uses a Pentium
or faster CPU, 586 or even 686 optimizations may produce better performance.
Tip The Mandrake and Stampede Linux distributions use 586 optimizations on their packages, and
so can be marginally faster than other distributions. On the other hand, the 586 optimizations
mean that these distributions don't run on 386 or 486 computers.
Memory
Many programs are memory−intensive—they consume a great deal of memory. Examples include
high−resolution graphics packages, some databases, and some scientific simulations. If your
system makes heavy use of such memory−intensive programs, it's important that you have enough
of both memory and fast memory.
Memory is measured in megabytes (MB). You can find how much your system has, and roughly
how it's being used, with the free command, thus:
$ free
total used free shared buffers cached
Mem: 95772 86748 9024 54480 5796 36164
−/+ buffers/cache: 44788 50984
Swap: 136512 7000 129512
The total column on the Mem line shows the total amount of RAM that Linux is using, usually equal
to the amount of memory that the system has. The used column shows the amount of memory
that's used, but the Mem line isn't the best to read in conjunction with this column, because it
includes memory that Linux has dedicated to disk buffers. On most systems, the used column
should show a value very close to the total column. Instead, check the −/+ buffers/cache line under
the used column to see how much memory is in use. If your system has insufficient memory, it will
use a lot of swap memory (indicated by a high value in the used column on the Swap line). This is
disk space treated like memory. Because disk performance is slow compared to memory
performance, it's best to minimize use of swap space.
Short of replacing or adding memory, there's not much you can do to improve the performance of
the memory you've got; however, there are steps you can take to make Linux use its existing

memory more efficiently. These techniques are covered later in this chapter.
Disk Performance
The disk subsystem—and particularly the hard disk—is a potentially important determinant of
performance. Many processes, including file serving, databases, and software development,
depend upon fast disk access. In addition, swap space resides on the hard disk, so if your computer
has inadequate memory, disk performance becomes important in memory−intensive tasks, as well.
You can improve disk performance by replacing your hard disk or by supplementing it with another
410
one. A less expensive option is to optimize your disk performance in any of several ways, described
in more detail later in this chapter. Careful partition layout, Linux disk−tuning options, and so on can
improve performance substantially.
Input/Output
Besides disk access, a variety of other I/O processes are also quite important, but less universally
so. The video hardware is extremely important to some video−intensive tasks, such as displaying
and moving windows in X, and in game playing. Network card I/O is important to servers and other
network−intensive tasks. Even the lowly serial and parallel ports can be important to tasks such as
printing.
For the most part, I/O speed is directly related to the quality of the relevant hardware. Sometimes
the hardware quality interacts with the quality of drivers written for that hardware. For instance,
historically, the fastest video hardware has first been supported in Linux using drivers that don't fully
take advantage of the cards' features. The newest video cards therefore often perform poorly in
Linux, at least until the XFree86 developers can produce improved drivers—a process that can take
several months.
Occasionally, special driver parameters can improve the performance of an I/O device. Linux
usually sets the best parameters at boot time, but you may want or need to adjust these settings in
some circumstances. Chapter 11, "Serial Communications, Terminals, and Modems," covers
adjusting the speed of serial ports, and this chapter includes tips for some other I/O devices.
Software Performance
Tools to measure software performance are typically expensive and are not often a justifiable
expense given the infrequency of usage. Typically software performance is measured in terms of

speed and accuracy. Software speed is directly dependent upon the skill of the programmer who
wrote the software, but since you can't control that, you have only to look to the hardware and
operating system when software performance appears to have degraded. Often a specific program
that your users run frequently will be the clue to them that the system is running poorly.
Measuring Performance
There are so many ways to measure performance that it is difficult to make the measurement
meaningful. One of the simplest benchmarks for Linux systems is the time it takes to compile a
specific kernel from the command line without X running; this is certainly useful when comparing
two identical computers or a single computer before and after a reconfiguration. Because kernel
compilation under Linux exercises most functions that are exercised by normal benchmarks except
floating−point performance, this comparison yields very useful data, which has the added benefit of
being in an easily compared form. To make the comparison even better, you can shut down any
external access, preventing user load from tainting the data. Of course, you need to use the same
kernel source tree and the same .config file to ensure that you are comparing apples to apples. This
is sufficient if your intent is to test the "guts" of the system.
For instance, you might compile a kernel and discover that the process requires 15:03 to complete.
After setting several optimizations, you might find that the same process requires only 11:34—a
substantial improvement. In performing such a comparison, though, you must ensure that nothing
about the compilation itself has changed. You should compile the same source code from the same
source tree. Also, be sure to do a make clean before each test compile. This command removes the
411
intermediate object code files created from the source code files. If you don't do a make clean, the
subsequent make bzImage (see Chapter 8, "Software Administration") or similar command will
simply relink the kernel against the previously compiled object files, resulting in a huge speed
difference that doesn't reflect the results of your performance tuning.
To measure X performance, use the xbench tool. As described on its Web site
( this tool uses a measurement called xStones, which is a
weighted average of several tests indexed to an old Sun station with a single−bit depth. A database
of test runs is available at its home site for your examination. xbench uses 13 low−level tests:
line Draws vertical and diagonal lines of different lengths.

dline Draws dashed lines.
wline Draws wide lines.
rects Draws rectangles.
fillrects Draws solid filled rectangles.
tiledrects Draws tiled rectangles.
stippledrects Draws stippled rectangles.
invrects Inverts rectangles on the screen.
arc Draws arcs of varying angles between 5 and 360 degrees.
filledarc Draws filled arcs of varying angles between 5 and 360 degrees.
filledpoly Draws a filled polygon with five points.
bilblt Test varies; see Web site for details.
imagestring Draws a string.
The simple tests listed above really only test the graphics engine. Additionally, xbench uses one
complex test to test the X server's overall performance. This test creates a window, clears an area,
draws some text, scrolls the window, and destroys the window. This is a very old tool. If there were
a newer tool that measured the same type of activity, we'd use it. As it is, though, xbench is the
usual benchmark for X performance.
Finding Bottlenecks
When you notice that one of your computers or an entire network is running slower than usual, it is
time to assume the detective role and track down the problem. Where is the bottleneck that is
preventing the data stream, whether on the network or on the backplane of an individual computer,
from flowing at its previous rate? What is causing the sluggishness? Is it hardware, software, the
network, or something in the operating system that is causing the problem? There are two tools we
use to determine the problem: top and traceroute. These tools can find most of the
non−hardware−related bottlenecks in the average computer system. If you don't find a bottleneck,
chances are the problem is hardware that is beginning to fail or is wrongly configured. Such issues
are discussed later in this chapter.
Using top to Find the Bottleneck
We use the top utility frequently to see how heavily loaded a particular computer is. The system
information top displays includes uptime, the number of processes and the states of those

processes, the percentages of CPU cycles and memory each process is using, the amount of time
each process has taken, and a lot of other information. The information may be specific to the listed
process or cumulatively computed from the process and its dead children. This information is
412
invaluable in troubleshooting a system. The processes are listed in order from the most
resource−intensive to the least intensive, and the display updates itself about every 5 seconds. top
reads global configuration information from /etc/toprc and user configuration information from a
.toprc file in the user's home directory.
The normal top utility is text−mode, but graphical versions also exist. The graphical versions are
available with the GNOME and KDE interfaces. The GNOME version is gtop, or the System
Monitor, and the KDE version is ktop, or the Task Manager. As you've seen in previous chapters,
we usually don't go for the GUI version of a tool unless it lends itself particularly well to a visual
presentation. In the case of table of process information, you'll see that it does. Figure 16.1 shows
the standard command−line top utility.
Figure 16.1: The top utility
Looking at the sample output, you'll see that the system is running a process called vmware, which
is taking up 27.7% of the CPU cycles. It also is using 46.1% of the memory. That's normal; this
product is quite resource−intensive and slows down a system quite a bit. Sometimes, however,
programs go haywire and start dominating the CPU or the memory and need to be shut down. The
top utility will help you find such programs.
Note VMware is a tool for running multiple operating systems on a single
computer. An alternative to dual−booting, it provides a virtual machine on an
Intel−based computer. This virtual machine is a simulated computer in which
an alternative operating system can be installed and run as if it were running
on standard PC hardware while actually being isolated from the host's
hardware and operating system. For more information, go to the VMware,
Inc. site at />Other information provided by top includes the process ID (PID), which can be used to kill an errant
program; the user who's running the program; the task priority (PRI) and nice value (NI), which
determine how Linux allots CPU time to the task; various measures of memory usage (SIZE, RSS,
and SHARE); the task's state (STAT)—R for running, S for sleeping, W for swapped out, and so on;

and the total CPU time consumed (TIME).
The top utility also has an interactive mode, which allows you to perform tasks like killing a process,
changing what information is displayed and how often it is updated, and renicing a process. (We'll
talk about nicing and renicing a process in the "Tuning the System" section of this chapter.) The
413

×