Suggestions here are divided into:
Green
Everyone should apply these! Unless you really want to be hacked.
Yellow
For the more cautious -- do these if you are a little worried about being hacked.
Red
For the truly paranoid -- if you have not moved to OpenBSD already!

There are no guarantees for what's here. Remember that security and convenience are usually inversely proportional. Good luck...


Before you start

Green -- everyone

Make sure that you have rescue media available.

Particularly before continuing with these suggestions. Try the Knoppix rescue media: http://www.knoppix.org/


Update your kernel and applications

Green -- everyone

Make sure that you apply all security updates!


Protect against network threats

Disable unneeded accounts
Green -- everyone

Attackers are attempting to login to your system via SSH as common default accounts like test, admin, guest, and root. Browse through /etc/passwd and disable all unneeded accounts. At least disable these, if they exist:
passwd -l test
passwd -l admin
passwd -l guest

Also make very certain that root has a strong password!

Red -- paranoid

Do the above, and also disable remote root access over SSH.

Make /etc/ssh/sshd_config contain the line:
PermitRootLogin no
and restart your SSH daemon:
/etc/init.d/sshd restart



Disable unneeded network services
Green -- everyone

Use lsof to list your system's open TCP and UDP ports:
lsof -i

Every one of those open ports is a risk. Do you really need to run every TCP/UDP service? Turn off what you do not need! You definitely should not run Telnet or any of the Berkeley R* services (rlogin, rcp, rsh).

For standalone services like HTTP/HTTPS, stop and disable the boot script:
/etc/init.d/httpd stop
chkconfig --del httpd

For services run out of xinetd, edit the specific configuration script and signal xinetd to reload its configuration:
vi /etc/xinetd.d/wu-ftpd
(change disable = no to disable = yes)
pkill xinetd

Yellow

If you must run HTTP, then do not also run HTTPS unless you really need a secure server (avoid some complication and reliance on the OpenSSL shared libraries).

Edit /etc/httpd/conf/httpd.conf and comment out the line reading:
# Listen 443
Then restart Apache:
/etc/init.d/httpd restart

Red -- paranoid

By the time you finish, your lsof output contains only the following:

COMMAND  PID USER  FD TYPE DEVICE SIZE NODE NAME
sshd    6502 root  3u IPv4 64002       TCP  *:ssh (LISTEN)
sshd    6502 root  3u IPv6 64003       TCP  *:ssh (LISTEN)



Protect your machine with iptables rules
Green -- everyone

Assuming there is no reference to /etc/rc.d/rc.firewall in any existing boot script, do the following. And if there is a reference, then either remove those references or use a different name in the following.

  1. Start a firewall script:
    touch /etc/rc.d/rc.firewall
    chmod 700 /etc/rc.d/rc.firewall
  2. Let's say your goal is:
    • Let any system in the entire 128.46.0.0/16 IP block (128.46.0.1 through 128.46.255.254) connect to the SSH service.
    • Also let the one system 44.48.40.12 connect to the SSH service.
    • Let any system in the 128.46.144.0/24 subnet (128.46.144.1 through 128.46.144.254) connect to the HTTP and HTTPS service.
    • Block all other attempts to connect to privileged TCP ports.
    • Block all attempts to connect to privileged UDP ports.
    Make it contain something like the following, modifying IP ranges and services, and adding ACCEPT lines as needed:
    #!/bin/sh
    
    # Flush any existing rules and set the default policies
    iptables -F
    iptables -P INPUT   ACCEPT
    iptables -P OUTPUT  ACCEPT
    iptables -P FORWARD ACCEPT
    
    # Accept anything from myself
    iptables -A INPUT -s 127.0.0.1/32 --jump ACCEPT
    # Allow myself to be a non-passive FTP client
    iptables -A INPUT -p tcp --dport ftp-data --jump ACCEPT
    
    # Do not allow a local user to connect to a remote Telnet
    # server and thus give away login and password information:
    iptables -A OUTPUT -p tcp --dport telnet --jump REJECT
    
    # Accept SSH connections from 128.46.0.0/16 and 44.48.40.12
    iptables -A INPUT -s 128.46.0.0/16  -p tcp --dport ssh --jump ACCEPT
    iptables -A INPUT -s 44.48.40.12/32 -p tcp --dport ssh --jump ACCEPT
    
    # Accept HTTP connections from 128.46.144.0/24
    iptables -A INPUT -s 128.46.144.0/16  -p tcp --dport http  --jump ACCEPT
    iptables -A INPUT -s 128.46.144.0/16  -p tcp --dport https --jump ACCEPT
    
    # If it's not one of the above allowed cases, block connection
    # attempts to privileged TCP and UDP ports.
    #
    # Send the client an ICMP Destination Unreachable (Port Unreachable)
    # packet to be polite and allow its application to quickly shut
    # down.
    iptables -A INPUT -p tcp --dport 1:1023 --jump REJECT
    iptables -A INPUT -p udp --dport 1:1023 --jump REJECT
    
    # Report what happened
    echo 'Firewall rules installed:'
    iptables -L
    
  3. Experiment with running that script directly and testing.
  4. When you are certain it works, add the following line to the end of /etc/rc.d/rc.local:
    /etc/rc.d/rc.firewall
Red -- paranoid

As above, but change the next-to-last block of code to the following (DROP vs REJECT):

# If it's not one of the above allowed cases, block connection
# attempts to privileged TCP and UDP ports.
#
# Silently drop unwanted packets to waste the attacker's time.
iptables -A INPUT -p tcp --dport 1:1023 --jump DROP
iptables -A INPUT -p udp --dport 1:1023 --jump DROP


Configure SSH securely
Green -- everyone

Put the following directives in /etc/ssh/sshd_config to configure the SSH server. Note that many of the SSH defaults are secure, so include the following but comment out any other directives currently used.
# Only the more secure SSH2 protocol
Protocol 2
X11Forwarding yes
Subsystem sftp /usr/libexec/sftp-server

And for the SSH client configuration in /etc/ssh/ssh_config:
# Only the more secure SSH2 protocol
Protocol 2
# Although read "man ssh_config" first...
ForwardX11 yes

Red -- paranoid

Put the following directives in /etc/ssh/sshd_config. Note that many of the SSH defaults are secure, so include the following but comment out any other directives currently used in your SSH daemon configuration:
# Only the more secure SSH2 protocol
Protocol 2
# List users allowed to connect via SSH
# Also see "AllowGroups", "DenyUsers",
# and "DenyGroups" in "man sshd_config".
AllowUsers joe jane ....
# Only the strongest ciphers
Ciphers blowfish-cbc,aes256-cbc,aes256-ctr
# Only accept authentication via cryptographic
# challenge-response (remote client must have
# cryptographic keys)
PasswordAuthentication no
# Do not allow root login -- first login
# as ordinary user, then su to root
PermitRootLogin no
Subsystem sftp /usr/libexec/sftp-server

And for the SSH client configuration in /etc/ssh/ssh_config:
# Only the more secure SSH2 protocol
Protocol 2


Prevent trivial root console break-in.

Green -- everyone

Add the following line to the file /etc/inittab right after the line referencing /etc/rc.d/rc.sysinit

	ss:S:respawn:/sbin/sulogin
Otherwise, just type linux s at the LILO prompt to break in as root on the console.

Yellow -- cautious

Do the above. And since an attacker could always boot from removable media like your Knoppix CD:

  1. Disable booting from the CD in the PC's BIOS.
  2. Install a BIOS password to prevent changes to the BIOS.

Red -- paranoid

Do both of the above. And since an attacker could open the system case and reset the BIOS or remove the hard drive, keep the computer in a physically secured room.


Harden the file system

Green -- everyone

Make /tmp a RAM-based filesystem. RAM is much faster than a disk, and any data stored there is truly temporary and is lost at shutdown.

  • Drop to single-user mode so the X font server is shut down:
    init 1
  • Clean out the existing /tmp:
    rm -r /tmp/.[a-zA-Z]*
  • Add this line to /etc/fstab:
    none /tmp tmpfs defaults 1 2
  • Mount it and verify that it worked:
    mount -a
    df
Yellow -- cautious

Do the above, but prevent an attacker from doing many things by making /tmp less useful to them. Make the /etc/fstab entry say:
none /mnt/tmp tmpfs noexec,nosuid,nodev 1 2

Red -- paranoid

Do all the above, and also use the noexec, nosuid, and nodev options on other partitions:
/var nosuid,nodev,noexec
/home nosuid,nodev
/usr nodev


Harden root authentication

Yellow -- cautious

Best practice for the root account is:

  • Do not allow direct root login, require someone to first authenticate as an ordinary user and then elevate privileges to root with su. This provides defense in depth plus an audit trail of who the actual user was.
  • Never let the root password traverse the net unencrypted.
  • Limit the set of people able to attempt to become root with su to the group wheel.
Do the following. Be very careful, this is where you can lock yourself out and only be able to break in with rescue media.

Disallow direct root login

  • Make certain that the file /etc/pam.d/login contains the line:
    auth required /lib/security/pam_securetty.so
  • The file /etc/pam.d/kde should differ by only that one line, and if so:
    cp /etc/pam.d/login /etc/pam.d/kde
  • If you use a display manager other than kdm (the KDE display manager), then copy the login file to the corresponding PAM file.
  • Specify that no device is trusted for root login:
    cp /etc/securetty /etc/securetty-BACKUP
    cp /dev/null /etc/securetty
  • Make /etc/ssh/sshd_config contain the line:
    PermitRootLogin no
  • Restart your SSH daemon:
    /etc/init.d/sshd restart
  • Test to verify that ordinary user login is still possible before exiting from your root session and continuing!

Prevent unencrypted transmission of the root password

  • See the above iptables suggestion for how to block outbound Telnet traffic.
  • See the above xinetd suggestion for how to turn off Telnet service. Also turn off POP and IMAP service, if there's a risk that someone will try to configure a mail user tool to connect in via POP or IMAP and read root's mail.

Limit the set of people able to attempt to become root

  • Create a group wheel (and if you already have one, don't worry about any error message at the groupadd command):
    groupadd -r wheel
  • Add the desired users to the group wheel (and you must add at least one!):
    usermod -G wheel joe
    usermod -G wheel jane
  • Change the group affiliation of the su command, and make it remain setuid as root and executable only by group wheel members:
    chgrp wheel /bin/su
    chmod 4750 /bin/su
  • Test to verify that group wheel members can use su to become root!

At this point you could write the root password on the monitor, and ordinary users still would be unable to become root -- not that this is a good idea, but root privileges now require knowledge of a privileged account's password plus knowledge of the root password.


Harden user authentication

Enforce password quality
Green -- everyone

Make sure that the file /etc/pam.d/system-auth contains the following line:
password required /lib/security/pam_cracklib.so minlen=8
Users will now be required to make their new passwords at least 8 characters long.

Yellow -- cautious

No, use:
password required /lib/security/pam_cracklib.so minlen=16

Red -- paranoid

You know, if you really want to take full advantage of the security offered by the 128-bit MD5 cryptographic hash used to authenticate the login pass phrase, you should consider the fact that English text contains about 1.2 bits of entropy per character, and 128/1.2 = 106.66666:
password required /lib/security/pam_cracklib.so minlen=107
Yeah, good luck convincing anyone that this is a good idea...