5 steps to secure your Linux server

by jagbir on February 16, 2011

How would you ensure security of your production Linux Server? Should you can be happy with default configuration there in place or there’s are things which we must implement for enhancing security aspects? Of course, Yes. Here I’m writing 5 steps which I usually take to tighten security in Server. This doesn’t means these are Best thing you can do or You don’t need to do anything else. There are many ways and remember securing your Server is a never ending process, So keep an eye open and check your Server regularly.

Step 1. Disable direct root access.
Login should be allowed using simple/wheel user and then from there you can switch to root or use sudo to execute commands under root privileges. Let’s disable direct root login:

$ vi /etc/ssh/sshd_config
Look for "PermitRootLogin yes" line in it and change it to "PermitRootLogin no".

Save the file, check for syntex and reload sshd service to make it effective:

$ sshd -D -f /etc/ssh/sshd_config
$ service sshd reload

You can create a new user now which will be used for login, leave it if there’s already a user for this purpose. Don’t forget to have a strong password for root and for this user as well.

$ useradd usertogetin
$ passwd usertogetin

Our step 1 is completed, but why it’s a necessary? A direct access to root user with a weak password is sure-shot invite for compromising security and get inside your server easily. Another powerful way to make it more difficult to hack in server is to change default ssh port 22 to something else, you can find the steps here to do that.

You should also keep looking into security related logs like /var/log/secure for clue about possible attempt of logins from remote places.

Let me show you something:

$ tail /var/log/secure
Feb  6 07:41:56 ip-184-x-xx sshd[20421]: Failed password for root from xx.xx.xx.xx port 48976 ssh2
Feb  6 07:41:57 ip-184-x-xx-x sshd[20422]: Received disconnect from xx.xx.xx.xx: 11: Bye Bye
Feb  6 07:41:57 ip-184-x-x-x sshd[20424]: reverse mapping checking getaddrinfo for 184-xx-xx-xx.abcd.net failed - POSSIBLE BREAK-IN ATTEMPT!

It shows somebody is trying to get in your server by trying random password for root user. You can block such IPs but most important step is to block root access and use strong passwords.

Example of another instance:

$ tail /var/log/secure
Feb  6 07:46:58 ip-184-168-71-156 sshd[20769]: input_userauth_request: invalid user deathrun
Feb  6 07:46:58 ip-184-168-71-156 sshd[20768]: pam_unix(sshd:auth): check pass; user unknown
Feb  6 07:46:58 ip-184-168-71-156 sshd[20768]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=184.xx.xx.xx

Here login attempts are done using random username and password. It implies that do not name your entry/wheel username as obvious one, choose somewhat difficult but what you can remember text for your username. Of course, Password must be strong which should includes chars,numbers and special symbols.

There should be mechanism to block an IP from where hacking/cracking/invalid/failed login attempts come from. If you see that there are 10s of failed login attempt from a particular IP address, then you should block it immediately. To facilitate this thing automatically, there a very good tool available, called as DenyHosts. I’ve already written an article explaining how to download/install/configure DenyHosts in Server. Its a must have package in any prod server.

Step 2. Remove login shell from all other users except wheel user.
You have disabled the remote access to root but do you know through how many users, a person can get inside to your server? many application while installation creates their user but with a major security flaw, they set login shell to ‘bash’ and this loophole can be exploited.

[root@ip-184-168-71-156 log]# grep 'bash' /etc/passwd
root:x:0:0:root:/root:/bin/bash
usertogetin:x:500:500::/home/usertogetin:/bin/bash

Here you can see only two entries, which are fine but if you see more lines here like with users mysql, ftp, postgre etc. then please change shell of these users to nologin so by using these users, login can’t be done.

# usermod -s /sbin/nologin mysql

Here we have modified shell of user MySQL from /bin/bash to /sbin/nologin. You should do this for other users as well except root and wheel user you created earlier.

Step 3. Check open ports and stop unused services.

$ netstat -ant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             State      
tcp        0      0 184.xx.xx.xx:53             0.0.0.0:*                   LISTEN      
tcp        0      0 184.xx.xx.xx:53             0.0.0.0:*                   LISTEN      
tcp        0      0 127.0.0.1:53                0.0.0.0:*                   LISTEN      
tcp        0      0 0.0.0.0:21                  0.0.0.0:*                   LISTEN      
tcp        0      0 0.0.0.0:25                  0.0.0.0:*                   LISTEN      
tcp        0      0 :::80                       :::*                        LISTEN      
tcp        0      0 :::22                       :::*                        LISTEN      
tcp        0      0 :::443                      :::*                        LISTEN      
tcp        0      0 ::ffff:xx.xx.xx.xx:80       ::ffff:xx.xx.xx.xx:52502    TIME_WAIT   
tcp        0   3152 ::ffff:xx.xx.xx.xx:22       ::ffff:xx.xx.Xx.xx:5222     ESTABLISHED
..
..

Apart from whatever showing above, your list may have many such lines with different ports with Listen/Established state. Here we used netstat command to list all active/listen/established ports with their IP addresses. You can see here some well known port numbers like 53 (DNS), 21 (FTP), 25 (SMTP), 80 (HTTP), 22 (SSH), 443 (HTTPS). These seems fine but if you doesn’t need any of these services, stop that program. In case you see some unusual listening ports, then you should verify their applications and stop them if they are not necessary.

Here by look at port numbers, you can’t get the information about which application is associated with any particular port number. Just for example, we want to know, which application is listening or using the port number 443. We can get this information by lsof command:

$ lsof -i :443
# lsof -i :443
COMMAND   PID   USER   FD   TYPE DEVICE SIZE NODE NAME
httpd    4335 apache    6u  IPv6 369447       TCP *:https (LISTEN)
httpd    6888   root    6u  IPv6 369447       TCP *:https (LISTEN)
httpd    7343 apache    6u  IPv6 369447       TCP *:https (LISTEN)
...
...

So port 443 is used by httpd (Apache) application/process to provide secure http services.

Step 4. Solid Backup Plan
Ensure that your server have a solid backup plan. All important files/databases/scripts etc. should be included in backup and it should be frequent. I have written a script which can help you to take frequent backup of essential log files/database. You can find it here with its usage.

Step 5. Regular upgrades
Ensure that regular upgrades/security patches/fixes of packages must be applied on time to so that all known vulnerabilities are fixed. You can check sites like http://www.securityfocus.com/ for such vulnerabilities.

Installation of more advanced packages like SELinux and/or AppArmour and/or rootkit detection etc. will provide you higher level of security.

Please note that nothing can ensure a 100% secure server but the steps listed above can ensure that your server have adequate security mechanism in place. One more thing, if unfortunately your security in your Server get compromised then never trust that server as a cracker can have access to 100% of the system. In such cases where we don’t have 100% confidence that Server is ok, its better to rebuild the Server from scratch and restore backup to make it up again.

I’d appreciate your comments sharing your experience or approaches which can help us securing our Servers more effectively.

Previous post:

Next post: