Tips to Secure Linux Workstation

If you have a Linux workstation with a direct connection to the Internet, you need to take certain measures in order to protect it from attacks. This article contains configuration information and tips on how to protect your machine. The article is applicable to all popular Linux distributions.

General

Configure and Enable Firewall

The firewall is the front-line defense against remote attacks. It's highly recommended that you enable and configure it. Linux firewall infrastructure is called netfilter/iptables. To configure it, check this Iptables howto, or use a configuration frontend such as m0n0wall (CLI), shorewall (CLI), or FireStarter (GUI).

I suggest that you drop all incoming connections, and then open the ports you need, like SSH or BitTorrent.

Avoid Easy-to-compromise User Accounts

Your machine must not have user accounts with easy-to-guess passwords, especially accounts like test/test or guest/guest. Many Linux worms try to exploit such accounts over SSH. open /etc/passwd and make sure there are no such accounts, if you do have an account like this, delete it:

$ sudo userdel <username>

If you really need such an account for some odd reason, change its shell to /bin/false, so that an attacker cannot login using it:

$ sudo chsh -s /bin/false <username>

Mount /tmp as noexec

Many script kiddies rely on downloading scripts to /tmp and executing them. By mounting /tmp as noexec, scripts located in /tmp will not be executable. This effectively disables exploits that rely on /tmp. Here is the /tmp config line from my /etc/fstab:

/dev/hda5               /tmp            ext2            noatime,noexec 0 0

Protect against Fork Bombs

Fork bombs are programs that keep creating child processes until system resources are all used. They actually aren't remote exploits because they require a local user to execute the bomb; however, users may be tricked into running a fork bomb. For example, the following example may look innocent, but running it on an unprotected system may take the whole system down:

:(){ :|:& }; :

Do not run the above code on an unprotected system!

The above shell script will actually keep forking at an exponential rate until system resources are exhausted.

To protect a system against such attacks, there is a file for limiting the number of processes per user. It is /etc/security/limits.conf. Add the following two lines to it:

@users          soft    nproc  100
@users          hard    nproc  150

These lines prevent anyone in the users group from having more than 150 processes, and issue a warning at 100 processes.

Your system may not have a users group, so you may want to edit the lines to match your needs.

Limit Usage of su/sudo

su lets normal users switch to the root account, and sudo enables granting more privileges to users. It's always better to grant only the absolutely necessary privileges to specific users, and limit the usage of su to a specific group.

When the usage of su/sudo is limited, even if the system is compromised through a dummy account (like test as username and password), the attacker will have less options to play with.

Linux Daemons

OpenSSH

Users of machines with broadband connections usually need to remotely connect to their machines through SSH. So even if the workstation is protected by a firewall, the port of SSH needs to be open for inbound connections. Therefore, SSH is a common target for remote attacks.

Here is a list of OpenSSH configuration settings that make it more secure against attacks. SSH settings are usually located in /etc/ssh/sshd_config:

SSH default port is 22, change it through the line below. This will stop many automated attacks.

Port 22

(change the port number)

Notice that when remotely connecting to your machine, the new port number needs to be specified to the SSH client, for example:

$ ssh -p <new-port> <username>@<host>

Make sure the protocol is set to 2. Version 1 is not secure.

Protocol 2

The following config lines protect against brute force attacks.

LoginGraceTime 2m
MaxAuthTries 6

Random attackers will usually try random usernames when trying to break through SSH, and since the root account exists on every machine, it will be on the attack list. The following config line disables root login over SSH and stops such attackers. If root access to a remote machine is needed, login using your regular account and use sudo:

PermitRootLogin no

A username with blank password may be added accidentally. The following config line disables SSH for such accounts.

PermitEmptyPasswords no

In addition to the configuration lines I listed, and in case you login to your machine from the same IP address or range, limit IP addresses that can connect to SSH using /etc/hosts.allow. Use the following format:

sshd : 127.0.0.1 : allow
sshd : IP address here : allow
sshd : IP address here : allow
sshd : ALL : deny

MySQL

if you use MySQL for local development, then it's safer to limit its connections to localhost (among the other things). To do so, run the mysql_secure_installation script, and it will take care of things for you.

Samba

Many need Samba for sharing files over the local network. Here is a list of config lines to secure it. The configuration file is usually located at /etc/samba/smb.conf or /etc/smb.conf:

hosts allow = 127.0.0.1 192.168.0.0/24
hosts deny = 0.0.0.0/0

These config lines limit the hosts that can connect to Samba to localhost and local IP ranges; modify to suit your needs.

security = user

Set security to user. In this case, users connecting to Samba will need to login before continuing. To add Samba user accounts, use the following command:

$ sudo smbpasswd -a <username>

You will be asked to provide a password for the new account.

If you login to your Samba share from a MS Windows machine, you may set your Samba username/password to match those on Windows, and avoid having to enter them every time you connect to the share.

As a final Samba tip, do not share your home directory. If you do so, you are just asking for trouble. Create a directory for sharing, and drop files there when necessary.

General Tips

  • Keep your system up-to-date, especially when security vulnerabilities appear in packages you use. All major Linux distros have security mailing lists, subscribe to your distro's.
  • Disable services you don't need. Every open service makes your system more open to attacks.
  • Regularly monitor the output of the following command for odd entries:

    $ sudo less /var/log/messages  # System log.
    $ sudo ps aux  # Running processes.
    $ sudo netstat -anp  # Active connections.
    

Comments

Anonymous
Anonymous's gravatar

Interesting, thanks.


Posted at 8:36 p.m. on March 5, 2006

Shane
Shane's gravatar

Great Tutorial and very helpful for Gentoo Linux users.


Posted at 8:24 p.m. on March 7, 2006

Eliel
Eliel's gravatar

These are some very good tips that everyone should follow. One thing I don't recommend doing, though is using vi to look at /var/log/messages.

Use cat or tail instead.


Posted at 8:24 p.m. on March 7, 2006

Anonymous
Anonymous's gravatar

Port 21 is it????? I don't think so.


Posted at 8:59 p.m. on March 7, 2006

Anonymous
Anonymous's gravatar

I don't know whether LSB requires /tmp to be writable, but I know programs such as gzexe that require an executable /tmp. nodev and nosuid are better settings as executables can most often be placed elsewhere too. The suggestions mentioned above are mostly paranoid.


Posted at 9:01 p.m. on March 7, 2006

CVirus
CVirus's gravatar

http://digg.com/linux_unix/Tips_to_Secure_Linux_Workstation


Posted at 9:37 p.m. on March 7, 2006

Anonymous
Anonymous's gravatar

Port 21 is for FTP, port 22 is for ssh by default...

TW


Posted at 10:28 p.m. on March 7, 2006

PerlJunkie
PerlJunkie's gravatar

If you need to open MySQL for remote access, consider running MySQL on another port. There are numerous exploits (mainly brute force) which look for MySQL on it's default port (3306). If you use port forwarding on your incoming router, you won't even have to change your MySQL installation. Forward a different port on your external interface to 3306 internal.

Also, there is no reason in the world why the 'root' user in MySQL needs to exist (in the 'mysql' database). Clone this user to another username and remove the 'root' username account from MySQL. Most brute force kits look for the default 'root' account.


Posted at 11:12 p.m. on March 7, 2006

Ayman Hourieh
Ayman Hourieh's gravatar

Ah, this is a typo. Fixed now. Thanks :)


Posted at 12:45 a.m. on March 8, 2006

Anonymous
Anonymous's gravatar

setting /tmp to noexec won't stop the script kiddies, they just download perl scrips and execute them from somewhere else, if fact I've found it caused more problems then it solved in the past due to applications falsely assuming they could exec temp stuff in /tmp


Posted at 5:08 a.m. on March 8, 2006

jfb3
jfb3's gravatar

Instead of using netfilter/iptables, which even you admit has configuration headaches, I'd suggest investing in a separate fireall device.

You get to stop all incoming traffic before it reaches and attempts to swamp your machine, and in general it's easier to manage.

Do you really want to have to worry about your firewall during an upgrade<->downgrade<->upgrade problem with portage because one of the devs (bless their little hearts) got something slightly wrong?

I've been running Gentoo on my workstation and one server for 3 years very successfully but I'd rather have my fireall be an appliance while I'm upgrading and changing configurations.

My firewall only cost 60$ 3 or 4 years ago and has worked flawlessly ever since.


Posted at 6:34 p.m. on March 8, 2006

tchmnkyz
tchmnkyz's gravatar

the default port is 22, telnet uses port 21...

i would also suggest this added to the sshd_config

StrictModes yes X11Forwarding no UsePrivilegeSeparation yes

and this option is not even valid for ssh MaxAuthTries 6

--T


Posted at 7:01 p.m. on March 8, 2006

Ayman Hourieh
Ayman Hourieh's gravatar

Thanks for your additions.

By the way:

$ man sshd_config [...] MaxAuthTries Specifies the maximum number of authentication attempts permitted per connection. Once the number of failures reaches half this value, additional failures are logged. The default is 6. [...]


Posted at 11:50 a.m. on March 9, 2006

Ayman Hourieh
Ayman Hourieh's gravatar

I said that in the article. Script kiddies with some Linux knowledge will try to move their scripts to another directory. However, if there is not other directory that they have write access to, or if the attack is automated, they will fail.


Posted at 11:56 a.m. on March 9, 2006

Anonymous
Anonymous's gravatar

telnet does NOT use port 21, it uses tcp port 23

FTP uses tcp ports 20 and 21, though might only use 21 in some cases if passive ftp is possible.


Posted at 6:08 p.m. on March 9, 2006

Anonymous
Anonymous's gravatar

I also find AllowUsers to be helpful in allowing specific users the ability to log in using SSH

AllowUsers [username] [username 2] ... [username n]


Posted at 1:10 a.m. on March 12, 2006

Anonymous
Anonymous's gravatar

i persnally use the command netstat -luntp to show all open ports and programms listening on the ports. on bsd one can use sockstat -4 -l and see the same.

greetings


Posted at 1:01 p.m. on March 13, 2006

Arun Kumar
Arun Kumar's gravatar

As you suggested dropping incoming conn at the firewall is a really good idea.

If you do login to the server using ssh from a remote location, it is always safe to configure iptables to allow incoming conn to sshd only from a particular IP addrs. (you can allow conn to port 22 from the ip xxx.xxx.xxx.xxx)

In case the client uses DHCP, and the IP changes regularly, u can configure iptables on the server to allow incoming conn only from ur clients MAC addrs. This is better than using IP addrs bcoz someone might be able to use ur client IP address when ur client is not using it. (you can allow conn to port 22 from MAC addrs xx-xx-xx-xx-xx-xx)

Also note that if for some reason if ur network card fails, there is no way you can do a remote login to the machine. Someone shld change the settings by physically being at the terminal.


Posted at 12:50 p.m. on March 14, 2006

fak3r
fak3r's gravatar

Good article, wish I had something similar when I was starting out.

Instead of your proposed vi /var/log/messages use some scripts like Logcheck http://logcheck.org/ which runs through your logs and emails you things that are out of place. It's easy to modify the conf files to train it to ignore things that come up often that you're not worried about. I have it set to run nightly, and it's amazing what it's able to help out with. It easily cuts out the cruft (regular events) allowing me to focus on things that are unexpected.

Also, aside from sub'ing to your distro's security mailling list, sub to things like Security Focus, or other apps that are 'live' to the world. I found out about and fixed some Drupal vulns before my distro (freebsd) did since I was on the Drupal list.

Thanks fak3r


Posted at 6:35 p.m. on March 14, 2006

Anonymous
Anonymous's gravatar

i tried changing the default port and it didn't work...i was using putty to connect to a different ssh port, could that be the problem or maybe the port i chose to use...do you recommend another port outside of 22?

great article by the way...i implented most of you ideas for ssh...was getting multiple hacking attempts


Posted at 3:30 p.m. on March 17, 2006

Ayman Hourieh
Ayman Hourieh's gravatar

Any unused port above 1024 should do the trick.

Did you restart sshd after changing the config file? You can see what port sshd is listening to by running the command:

netstat -lunpt | grep sshd

In PuTTY, just change the port number. You don't need to do anything else.


Posted at 3:51 p.m. on March 17, 2006

TCP
TCP's gravatar

Just passing through when I saw your thread, great tips I also have a few that people may find useful. If you add this to the end of your /etc/profile file, it will alert you when an account is created. Unfortuntely I haven't been able to verify if this works just yet

if "$UID" > 1000 ; then echo 'ALERT - New Account Created (MachineName) on:' date who | mail -s "New Account Created on (MachineName) who | cut -d'(' -f2 | cut -d')' -f1" you@yourdomain.com fi

Now just modify it a bit to alert you if someone creates an acount that is part of the root group:

if "$GID" == 0 ; then echo 'ALERT - New Account Created With Root Group Privileges (MachineName) on:' date who | mail -s "New Account Created With Root Group Privileges on (MachineName) who | cut -d'(' -f2 | cut -d')' -f1" you@yourdomain.com fi

Add this line to your /etc/hosts.deny file and it will email you if there is a refused connection from the Inetd daemon ( TCP Wrappers):

ALL:ALL:/bin/mail -s %s connection attempt from %c you@yourdomain.com


Posted at 9:59 a.m. on March 21, 2006

Anonymous
Anonymous's gravatar

m0n0wall is not a netfilter/iptables frontend. It's an embedded "firewall distribution" based on FreeBSD.


Posted at 12:47 p.m. on April 9, 2006

Azio
Azio's gravatar

Hello there, Well, what a great guide on security basics, some very interesting stuff too, Thanks for the interesting read, It's proved useful to me, with some of the debian machines I run,

Thanks again

Adam


Posted at 1:52 p.m. on April 13, 2006

Anonymous
Anonymous's gravatar

Also which distro has out-of-the-box support for SATA hard drives. Any suggestions?

Have you tried Ubuntu. It's a gr8 distro and has very good support for a variety of vendors. You need to have a good connection for downloading necessary packages.

I have tried FC5 too and it seems to contain good support in a single DVD (5 CDs).


Posted at 10:41 a.m. on April 17, 2006

Bitmuncher
Bitmuncher's gravatar

The following /proc manipulation is minimal to secure linux for networking:

# don't answer to broadcast pings
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
# don't answer to bogus ICMP messages
echo 0 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
# enable source validation and kick the ip spoofing shit
echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter
# change default TTL (default in Linux is 64)
echo 61 > /proc/sys/net/ipv4/ip_default_ttl
# send RST packages if buffer is full
echo 1 > /proc/sys/net/ipv4/tcp_abort_on_overflow
# wait max. 30 seconds for FIN/ACK
echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
# max 3  SYN packages for one connection attempt
echo 3 > /proc/sys/net/ipv4/tcp_syn_retries
# max 3 SYN/ACK packages for one connection attempt
echo 3 > /proc/sys/net/ipv4/tcp_synack_retries

Posted at 10:53 p.m. on April 28, 2006

Anonymous
Anonymous's gravatar

you would have to be insane or very inexperienced to allow password access to any machine running SSH, especially in the wild. any sysadmin with any clue whatsoever disables password authentication and uses keyfiles. keep them with you on an encrypted usb stick: if you use freeOFTE and luks then you have windows + linux compatibility for accessing your keys. additionally, SELinux is very useful for protecting the system against your legitimate users and rogue programs.


Posted at 12:01 p.m. on May 12, 2006

Paul
Paul's gravatar

Your notes are good and helpful. I notice you use hosts.allow, and I do too, but I think you should mention putting ALL: ALL in hosts.deny. You might also warn FC5 users that the xinetd package is not installed by default. As far as I know, hosts.allow is a tcpwrappers thing, right? So without xinetd, it doesn't do anything. Does it?

in a computer lab with lots of systems, I use ssh related tools a lot to administer the systems and if I follow your advice and turn off root logins in sshd, then my administrative problems are much more difficult. If I do allow root access with sshd, I think there should be some other ways to secure the system.

For example, is there a way with iptables to allow root logins only from a few IP numbers? Or is there a way to make ssh accept logins only from systems that have a particular PGP security key (an id_rsa file) in .ssh?

Just wondering...

pj


Posted at 5:01 p.m. on May 30, 2006

Shameless Plug
Shameless Plug's gravatar

Hey Aymanh,

Good stuff; keep it up. A buddy of mine wrote an extremely useful Python script for security called DenyHosts:

http://denyhosts.sourceforge.net/

It's open source and is already included in a number of Linux distros already. It'll be included in the next Ubuntu release ("Edgy Eft"), as well.

HTH!


Posted at 3:01 a.m. on October 9, 2006

Kishor
Kishor's gravatar

Hey, this is the very great post. i've got the new ideas of securing the linux box. i hope it will work on my red hat enterprise server 2004.


Posted at 11:22 p.m. on November 23, 2006

Anonymous
Anonymous's gravatar

hi, due to Darren Tucker you need to disable ChallengeResponseAuthentication with ChallengeResponseAuthentication no if you are using Pam with openssh.

so it won't accept no more passwords and just pubkeys


Posted at 4:45 a.m. on December 28, 2006

keli
keli's gravatar

It helps somewhat, but not too much. I'm using it on a server, and was just hacked by a "/tmp" script.

simple really: instead of executing a script, the hacker just initiated perl script.pl and voila, noexec does nothing, since perl itself is obviously not on a noexec partition.


Posted at 9:03 a.m. on June 21, 2007

Anonymous
Anonymous's gravatar

http://goinggnu.wordpress.com/2007/01/30/tips-to-secure-linux-workstation-2/

exactly same article.....


Posted at 12:03 p.m. on July 7, 2008

Anonymous
Anonymous's gravatar

yes port 21 exists....the port 21 is used by ftp.....


Posted at 11:15 a.m. on November 18, 2008

linux tips
linux tips's gravatar

Nice list. You can also make accounts inaccessable by locking them. As root do "passwd -l useraccount". Now its impossible to login as this user. The advantage of locking is that you can unlock it later. Another good tip for securing the server is making an wheel group - add all the users who can become root to this group. This way only one user may change to root. I don't know why this isn't enabled by default like the BSD's do.

Ssh - I only login using keys. if you do not have the key you won't be able to enter a passphrase to login. This way an attacker either needs both your key and passphrase to login or use an exploit to gain access. Also if you have a fixed ip address - add rules that only your ip address can login via ssh. You can do this with iptables or use hosts.allow and hosts.deny.

I've put up some nice tips on my squidoo lens. http://www.squidoo.com/linux-tips-and-tricks


Posted at 12:35 p.m. on November 21, 2008

Anonymous
Anonymous's gravatar

pretty sure it works on most distros, not just gentoo


Posted at 2:05 p.m. on December 30, 2008

Anonymous
Anonymous's gravatar

thx for the great post!!!best wishes from romania.


Posted at 10:15 p.m. on April 4, 2009

Matt K.
Matt K.'s gravatar

I agree with everything about this article except

1) the tmp noexec

That is about it... the use of a firewall is also not nessassary... as you are poking a hole in the firewall to access ssh port and others...so why bother?

The key is to use TCP Wrappers... set ssh: in /etc/hosts.allow

Than if anyone not coming from that IP address, will simply be instantly denied with no attempt for any kind of attack whatso ever....

How ever, I do recomment that if you do use KEYED ssh passwords, that you create a user account SPECIFICALLY for the sole purpose of logging into SSH... a user that is bare minimum rights.. than from there elevate to ROOT.

Using TCP Wrappers and a non root user to log in...and your pretty much safe. I have never been hacked... but I can tell you they have tried... but since TCP wrappers blocks them from the get go.. they go elsewhere.

Also, changing the PORT will not do much good, as using nmap will tell you all open ports anyways, and only inconviences you from having to use another odd port number.. although layers of security never hurts.


Posted at 1:40 a.m. on September 29, 2009

Matt K.
Matt K.'s gravatar

If you enable networking for remote mysql... they you can add mysqld: to hosts.allow just like you do for sshd.

There is never really a need to access mysql directly. Typically using phpMyADMIN thru apache which then connects through the localhost... is more secure.. but if you have multiple servers with mysql running on them, then you can as I just mentioned use TCPWRAPPERS for mysql/mysqld restricted by ip address...


Posted at 2:05 a.m. on September 29, 2009

Anonymous
Anonymous's gravatar

Good article. While I agree with many people its better to have a separate firewall at the edge of the network before anything ever hits an internal box that just isn't realistic in all applications. Take SIP and many streaming media related applications. NAT is a nightmare to deal with when using SIP and including supplemental solutions like STUN/proxies create more bottlenecks and potential points of failure/overhead. I think this article does a great job showing how to harden SSH to any box that must be on the public internet. From there many people would want to keep adding more layers of security. Good stuff.


Posted at 5:28 p.m. on May 26, 2010

Anonymous
Anonymous's gravatar

You can give ssh a config file for specific machines so you don't have to specify port and user on the command line:

Example for ~/.ssh/config:

Host 192.168.0.1 Port 12345 User john_doe


Posted at 2:28 p.m. on August 4, 2011

Post a comment

HTML is not allowed. You can use markdown syntax to format your comment.