your linux box for the Internet
Last Modified: 25 April, 2000
Organizations throughout the world are adopting Linux as their production
platform. By connecting to the Internet to provide critical
services, they also become targets of opportunity. To help protect
these Linux systems, this article covers the basics of securing a Linux
box. The examples provided here are based on Red Hat 6.0, but should
apply to most Linux distributions.
The best place to start in armoring your system is at the beginning,
OS installation. Since this is a production system, you cannot trust any
previous installations. You want to start with a clean installation, where
you can guarantee the system integrity. Place your system in an isolated
network. At no time do you want to connect this box to an active network
nor the Internet, exposing the system to a possible compromise. I personally
witnessed a system hacked by a script
kiddie within 15 minutes of connecting to the Internet. To get
critical files and patches later, you will need a second box that acts
as a go between. This second box will download files from the Internet,
then connect to your isolated, configuration "network" to transfer critical
files or burn the patches to a CDROM.
Once you have placed your future Linux box in an isolated network, you
are ready to begin. The first step is selecting what OS package to load.
As of RH 6.0, you have three options, Workstation, Server, and Custom (default).
I highly recommend Custom, as this allows you to choose what services are
added and how the system is partitioned. The idea is to load the
minimum packages, while maintaining maximum efficiency. The
less software that resides on the box, the fewer potential security exploits
or holes. This means if you do not need a News or Real Audio Server,
don't install it. The nice thing about Linux is, if you change your
mind, it is easy to add packages later. Regardless of which installation
you choose, I would add the manual pages and HOWTO docs. I find the
on-line man pages and docs to be a critical resource that add little risk
to your system.
If you selected Custom, you will be asked to partition your system.
I always like to make root as big as possible and just throw everything
in there, then you do not run out of room in the future. However,
we do need several partitions to protect the root drive. If we were
to fill the root partition with data, such as logging or email, we would
cause a denial of service, potentially crashing the system.
Therefore, I always recommend a separate partition for /var, this is
where all the system logging and email goes. By isolating the /var
partition, you protect your root partition from overfilling.
I've found 400 MB to be more then enough for /var (increase this if
your system will have alot of mail) . You may also consider
making a separate partition for specific application purposes, especially
applications that store extensive logging or a /home if you have a lot
of users. With such a setup, your partitions would look as follows:
- everything else
- 400 MB
- (I normally go with 256 MB)
Once the system has rebooted after the installation, be sure to install
the recommend security patches. For Red Hat, you can find these security
patches at Red Hat's
errata support site. Patches are critical to armoring a system
and should always be updated. email@example.com
are excellent sources for following bugs and system patches. Without
these patches, your system can be easily compromised. Be sure to
use your go between box to get the patches, the Linux box should always
remain on an isolated network. . For Red Hat, once you download the rpm,
you can easily update your system using the following syntax. An
excellent example of this is the security update for wu-ftpd
rpm -Uvh wu-ftpd-2.6.0-1.i386.rpm
For systems that are already on-line, you can ftp the rpm and install
it at the same time, using the following syntax.
rpm -Uvh ftp://updates.redhat.com/5.2/i386/wu-ftpd-2.6.0-1.i386.rpm
As of RH 6.1, there is a new utility for patches called 'up2date'. I
highly recommend you try this excellent utility. When ran on a local system,
it determines which .rpm's need to be updated, gets those rpm's from Red
Hats's web site, and then downloads and installs the updated files. This
tool is highly customizable and easy to use.
Once you have loaded the installation package, patches, and rebooted,
we are now ready to armor the operating system. Armoring consists mainly
of turning off services, adding logging, tweaking several files, and configuring
TCP Wrappers. First we will begin with turning off services.
By default, Linux is a powerful operating system that executes many
useful services. However, most of these services are unneeded and pose
a potential security risk. The first place to start is /etc/inetd.conf.
This file specifies which services the /usr/sbin/inetd daemon will listen
for. By default, /etc/inetd.conf is configured for a variety of services,
you most likely only need two, ftp and telnet. You eliminate the remaining
unnecessary services by commenting them out (example
A). This is critical, as many of the services run by inetd pose
serious security threats, such as popd, imapd, and rsh. Confirm what
you have commented out with the following command (this will show you all
the services that were left uncommented)
grep -v "^#" /etc/inetd.conf
The next place to start are the .rc scripts, these scripts determine
what services are started by the init process. For Red Hat, you will find
these scripts in /etc/rc.d/rc3.d (or /etc/rc.d/rc5.d if you automatically
boot to a GUI, such as Gnome or KDE). To stop a script from starting,
replace the capital S with a small s. That way you can easily start the
script again just by replacing the small s with a capital S. Or, if you
prefer, Red Hat comes with a great utility for turning off these services.
Just type "/usr/sbin/setup"
at the command prompt, and select "System
Services", from there you can select what scripts are started
during the boot up process. Another option is chkconfig,
which you will find on most distributions. The following startup
scripts may be installed by default but are not critical to system functioning.
If you don't need them, turn these scripts off. The numbers in the
names determine the sequence of initialization, they may vary based on
your distribution and version. Scripts that start with a capital
K instead of a captial S are used to kill services that are already
(You only need this for laptops)
(Network time protocol)
(Required if you have any rpc services, such as NIS or NFS)
(Saves sound cared settings)
(This is the nfs client, used for mounting filesystems from a nfs server)
(Try to avoid running any r services, they provide too much
information to remote users)
for diskless clients, you probably don't need this vulnerable service)
if you are a NIS server, this is an extremely vulnerable service)
(Required if you are a NIS server, this is an extremely vulnerable
(Starts dhcp server daemon)
(Used for the at service, similar to cron, by not required by the system)
(You only need this script for laptops)
(SNMP daemon, can give remote users detailed information about your
(DNS server. If you are setting up DNS, upgrade to the latest
version of BIND, http://www.isc.org/bind.html)
(RIP, don't run this unless you REALLY need it)
(Netware file and print server)
(Use for NFS server, do not run unless you absolutely have to).
(AutoMount daemon, used to mount remote file systems)
(used to run other routing protocols, such as OSPF)
(You can still send email if you turn this script off, you just will
not be able to receive or relay)
(Apache webserver, I recommend you upgrade to the latest version,
(Required if you are a NIS client)
(X font server)
(Used to remotely configure Linux systems via browser, every black-hat's
To see how many services are running before you change the startup scripts,
ps aux | wc -l
Once you are done with the installation and have turned off the startup
scripts, type the command again and compare how the number of services
have decreased. The fewer services running, the better. Also, confirm which
are left running by executing the following command:
netstat -na --ip
Once you have eliminated as many services as possible, we want to enable
logging. All system logging occurs in /var/log. By default,
Linux has excellent logging, except for ftp. You have two options
for logging for ftp, configure /etc/ftpaccess file or edit /etc/inetd.conf.
I prefer to edit /etc/inetd.conf, as it is simpler (i.e. harder to mess
up :). Edit /etc/inetd.conf as follows to ensure full logging of
all FTP sessions.
stream tcp nowait root
/usr/sbin/tcpd in.ftpd -l -L -i -o
--- From the man pages
If the -l option is specified,
each ftp session is logged in the syslog
If the -L flag is used,
command logging will be on by default as soon as the ftp server is invoked.
This will cause the server to log all USER commands,
which if a user accidentally enters a password for that command instead
of the username, will cause passwords to be logged via syslog.
If the -i option is
specified, files received by the ftpd(8) server will be logged to the xferlog(5).
If the -o option is
specified, files transmitted by the ftpd(8) server will be logged to the
--- snip snip ---
Next comes tweaking. This involves various file administration. The
first thing we want to do is secure our /etc/passwd file (this is the database
file that holds your user accounts and passwords). First, we want
to ensure our system is using /etc/shadow, this securely stores everyone's
password as hashes in a file only root can access. This protects your passwords
from being easily accessed and cracked (one of the first exploits a hacker
looks for). The use of shadow passwords is default as of RH 6.0,
however it never hurts to be sure. All you have to do is type the following
command as root. This automatically converts your passwords to the /etc/shadow
file. Of all the actions you can take to secure your system, I consider
this to be one of the most important.
The second step is to remove most of the default system accounts in
/etc/passwd. Linux provides these accounts for various system activities
which you may not need. If you do not need the accounts, remove them.
The more accounts you have, the easier it is to access your system.
An example is the "news" account. If you are not running nntp, a
news group server, you do not need the account (be sure to update /etc/cron.hourly,
as this looks for the user "news"). Also, make sure you remove the "ftp"
account, as this is the account used for anonymous ftp. From the
Ftpd authenticates users according to four rules.
4) If the user name is ``anonymous''
or ``ftp'', an anonymous ftp account must be pre-sent in the password file
(user ``ftp''). In this case the user is allowed to log in by specifying
any password (by convention this is given as the client host's name).
For an example of my /etc/passwd file, check out example
We also want to modify the file /etc/ftpusers (example
D). Any account listed in this file cannot ftp to the system. This
restricts common system accounts, such as root or bin, from attempting
ftp sessions. Linux has the file by default. Ensure that root stays
in this file, you never want root to be able to ftp to this system.
Ensure that any accounts that need to ftp to the box are NOT in the file
Also, ensure that root cannot telnet to the system. This forces users
to login to the system as themselves and then su to root. The file /etc/securetty
lists what ttys root can connect to. List only tty1, tty2, etc in
this file, this restricts root logins to local access only. ttyp1,
ttyp2, are pseudo terminals, they allow root to telnet to the system remotely
Last, create the file /etc/issue. This file is an ASCII text banner
that appears for all telnet logins (example
B). This legal warning will appear whenever someone attempts to login
to your system. If you want to continue using the same /etc/issue file,
you will have to modify /etc/rc.d/init.d/S99local. By default, Linux
creates a new /etc/issue file on every reboot.
to your server
For those of you who will be doing remote administration, it is critical
that you develop a secured, controlled way to connect to the server.
Often, you need remote access to your server for administration or the
uploading of files, these communications need to be secured I will
discuss two options here, ssh and TCP Wrappers.
I prefer ssh, as it encrypts all communication between you and the firewall.
TCP Wrappers will NOT protect your network
traffic from sniffing. Users can still capture all of your keystrokes
(including passwords) on the network. If you are concerned
about users capturing communications to your firewall, I recommend
you replace telnet/ftp with ssh. ssh will encrypt all
communications to your server, allowing you both to upload files and
administer the server in a secure manner. ssh is similar
to TCP wrappers in that it has its own layer of logging, and can limit
what systems can connect to it. For more information on
ssh, you can find ssh here,
including source for both ssh clients and server daemon. I recommend
you use ssh version 1.2.x, as version 2.x has a limiting license.
Another ssh option is Openssh.
TCP Wrappers, while it does not encrypt, it does log and control who
can access your system. It is a binary that wraps itself
around inetd services, such as telnet or ftp. With TCP Wrappers, the
system launches the wrapper for inetd connections, logs
all attempts and then verifies the attempt against a access control
list. If the connection is permitted, TCP Wrappers hands the
connection to the proper binary, such as telnet. If the connection
is rejected by the access control list, then the connection is
dropped. Fortunately for us Linux users, TCP Wrappers is already
installed, the only thing left for us to do is edit the /etc/hosts.allow
and /etc/hosts.deny file. These files determine who can and cannot
access our systems. Also, TCP Wrappers allows us to do fancy things,
such as banners or spawn additional programs, such as safe_finger.
The syntax is relatively simple. Put the IP address or networks in
/etc/hosts.allow that you want to permit connections from. Put IP
addresses or networks in /etc/hosts.deny that you do not want to permit
access. By default, Linux allows connections from everyone, so you
will need to modify these files. 2 recommendations when working with
For examples on how to setup /etc/hosts.allow and /etc/hosts.deny, see
F. For more ideas on how to use TCPWrappers, check out Intrusion
Use IP addresses instead of system or domain names.
Set up /etc/hosts.deny to deny everything (ALL), then permit only specific
sites with /etc/hosts.allow.
I consider the measures discussed above absolutely essential.
By following these steps, you have greatly improved your system's security,
congratulations! Unfortunately, your system is not 100% secure, nor
will it ever be. So, for the truly paranoid, I have added some additional
steps you can take.
First we will create the wheel group. The wheel group is a group
of select individuals that can execute powerful commands, such as /bin/su.
By limiting the people that can access these commands, you enhance the
system security. To create the group, vi the file /etc/group, create
the group wheel, and add the system admins to the group. Then identify
critical system binaries, such as /bin/su. Change the group ownership
to wheel, and the permissions to owner and group executable only (be sure
to maintain the suid or guid bit for specific binaries). For /bin/su,
the commands would be:
/bin/chgrp wheel /bin/su
/bin/chmod 4750 /bin/su
Second, we will lock down the files .rhosts, .netrc, and /etc/hosts.equiv.
The r commands use these files to access systems. To lock them down,
touch the files, then change the permissions to zero, locking them down.
This way no one can create or alter the files. For example,
/bin/touch /root/.rhosts /root/.netrc
/bin/chmod 0 /root/.rhosts
Third, we configure /etc/shadow to use MD5
hashes instead of the crypt(3) function. This makes the encrypted
password file far more difficult to crack. This is done by modifying
the PAM modules. PAM (Pluggable Authentication Modules) is a suite
of shared libraries that enable you to choose how applications authenticate
users. To learn more about PAM, check out ftp://ftp.us.kernel.org/pub/linux/libs/pam/Linux-PAM-html/pam.html.
In the old days, you had to manually modify the PAM modules to use MD5
hashes. However, with Red Hat 6.0 or greater, you can select MD5
hashes with the setup utility. Just type "setup" at the command prompt,
then select "authentication configuration". From there, you can choose
to use MD5 hashes. However, the MD5 hashes will not take effect until
the user re-enters their password. For those of you who do not have
the setup utility (or have Red Hat 5.2 or earlier), you can still modify
the PAM modules manually (example
For us bash users, I'm not a big fan of the .bash_history file.
I do not want people (including root) to know my command history.
So, in my .bash_profile, I export the following entry:
This means that nothing will be logged to my .bash_history file.
I will still have keystroke history and recall, the HISTSIZE env variable,
but command history will not be written to the .bash_history file.
Last thing we can do is protect our system from physical access.
This mainly consists of setting up a password for our BIOS. Also,
you can password protect your system during boot-up by configuring /etc/lilo.conf
with a password (password=xxx)
where xxx is your password. However, keep in mind, once someone has
physical access to your system, there is no guaranteed way to protect it.
No discussion about Linux security would be complete without covering
IPChains. IPChains is packet filtering software that comes with the
2.2.x kernel and above. This means if you are running Red Hat 6.0 or later,
you have it as part of your Linux installation kit. IPChains is similar
to Cisco Access Control Lists, it can control what packets can come in
and out of your Linux box. Primarly used as a firewall application,
IPChains can also be used to armor your standalone Linux box.
To armor a standalone system, I configure IPChains to allow only TCP connections
I initiate. If anyone attempts to initate any TCP connections to
me, the connection is denied. Since IPChains is not stateful, I do
allow all UDP and ICMP connections. Last, I log all denied connections,
this lets me know if someone out there is being naughty :) However,
I drop but do not log all the broadcat/multicast traffic, as this would
quickly fill up the system logs. A simple IPChains configuration to armor
a standalone system would look something like this.
bash# ipchains -L
Chain input (policy
target prot opt source
DENY all ------ 0.0.0.0
DENY all ------ anywhere
DENY all ------ anywhere
ACCEPT tcp !y---- anywhere
anywhere any -> any
ACCEPT udp ----l- anywhere
anywhere any -> any
ACCEPT icmp ----l- anywhere
anywhere any -> any
DENY all ----l- anywhere
Chain forward (policy
Chain output (policy
To see the config files for this, see example
H. To learn more about using IPChains as a firewall or for a standalone
system, check out the IPChains
We have covered some of the more basic steps involved in armoring a
Linux box (Red Hat distribution). The key to a secure system is having
the minimal software installed, with protection in layers, such as TCP
Wrappers, IPChains, and shadowed passwords. There are many additional steps
that can be taken, such as tripwire
changes in system binaries) and swatch
log monitoring and alerts). I also recommend that new Linux users check
out Bastille Linux, a PERL
script that can automatically secure your new Linux system, step by step.
Remember, no system is truly 100% secure. However, with the steps outlined
above, you greatly reduce the security risks.
Lance Spitzner enjoys learning by blowing up his Unix systems at
home. Before this, he was an Officer
in the Rapid Deployment Force, where he blew up things of a different
nature. You can reach him at firstname.lastname@example.org