How to secure your LAMP server


The LAMP stack which stands for Linux, Apache, MySQL/MariaDB and PHP/Python/Perl is a very popular combination of free and open-source software used to run millions of websites today. Although many opt for the much efficient LEMP stack based on Nginx instead of Apache, there are still a significant number of users that choose LAMP for their projects. In fact, more than 30% of the active websites today run on top of LAMP. The stack is considered as reliable and very suitable for running high-performance high-availability web applications. In this tutorial we are going to show you how to secure the LAMP stack on your Linux VPS.

Secure Linux

Enable automatic updates

Having in mind that the LAMP stack is based on Linux and the whole open-source community works on improvements, it is considered as secure too. On an Ubuntu VPS, all security updates and patches are available as an automatic unattended install as soon as they become available in the Ubuntu repos, and therefore, make sure you configure your system to automatically install the security updates if you are concerned about the security. In case this feature is not enabled on your server and you are not installing the latest upgrades and patches manually, you are putting your server at risk of being exploited.

To enable automatic unattended upgrades you should install the unattended-upgrades package.

sudo apt-get install unattended-upgrades

To configure which category of packages to be automatically upgraded you should edit the /etc/apt/apt.conf.d/50unattended-upgrades file.

Configure firewall

Having a properly configured firewall is another thing that is very important for the overall security. ufw is the default firewall configuration tool for Ubuntu and it is initially disabled. To enable ufw you can use:

sudo ufw enable

Enable access to the basic services like OpenSSH and Apache:

sudo ufw allow 22
sudo ufw allow 80
sudo ufw allow 443

Enabling access to other services is pretty easy. Just replace the port number in the examples above with the port number of the service which you want to enable access to and that’s it. The firewall rules will be active even after system reboot.

Disable unused services

If you have active services which you are not using, you can simply disable them. For example, if you have service like Dovecot up and running on your server and you are not using it at all, stop and disable the service using the following commands:

sudo systemctl stop dovecot.service
sudo systemctl disable dovecot.service

Install Fail2ban

Fail2ban is a service which scans the log files for too many login failures and blocks the IP address which is showing malicious signs. This service is very useful if you are not using two factor or public/private authentication mechanisms on services like OpenSSH. To install Fail2ban, run this command:

sudo apt-get install fail2ban

Create a copy of the default configuration file so you can safely make changes without them being overwritten by system upgrades:

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Edit the jail.local file:

sudo nano /etc/fail2ban/jail.local

The [sshd] block should look like the following one:

[sshd]

enabled  = true
port     = ssh
filter   = sshd
logpath  = /var/log/auth.log
maxretry = 5
bantime = 600

Save the file and restart Fail2ban for the changes to take effect:

sudo systemctl restart fail2ban.service

Enable Fail2ban on system boot:

sudo systemctl enable fail2ban.service

Secure Apache

Hide Apache sensitive information

The default Apache configuration provides much sensitive information which can be used against the service. Making this information hidden is crucial so go ahead and create a configuration file for your new settings:

sudo nano /etc/apache2/conf-available/custom.conf

Paste the following content:

ServerTokens Prod
ServerSignature Off
TraceEnable Off
Options all -Indexes
Header unset ETag
Header always unset X-Powered-By
FileETag None

Enable the headers Apache module if it is not already enabled:

sudo a2enmod headers

Enable the configuration:

sudo a2enconf custom.conf

Restart Apache for the changes to take effect:

sudo systemctl restart apache2.service

Install and enable mod_security

Mod_security is a web application firewall (WAF) which can be installed as an additional module for Apache. It can be used to protect the web server from numerous attacks like SQL injections, session hijacking, cross site scripting, bad user agents and many others. To install and enable mod_security run the commands below:

sudo apt-get install libapache2-modsecurity
sudo a2enmod security2

Once it is installed you should configure the module and enable the OWASP ModSecurity Core Rule Set (CRS).

sudo mv /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf

Then, open the /etc/modsecurity/modsecurity.conf file and edit/add the following settings:

SecRuleEngine On
SecResponseBodyAccess Off
SecRequestBodyLimit 8388608
SecRequestBodyNoFilesLimit 131072
SecRequestBodyInMemoryLimit 262144

Save and close the file. Remove the current CRS and download the OWASP CRS by using the following commands:

sudo rm -rf /usr/share/modsecurity-crs
sudo git clone https://github.com/SpiderLabs/owasp-modsecurity-crs.git /usr/share/modsecurity-crs
cd /usr/share/modsecurity-crs
sudo mv crs-setup.conf.example crs-setup.conf

Edit the /etc/apache2/mods-enabled/security2.conf file. It should look like the one below:

<IfModule security2_module>
	SecDataDir /var/cache/modsecurity
	IncludeOptional /etc/modsecurity/*.conf
	IncludeOptional "/usr/share/modsecurity-crs/*.conf"
	IncludeOptional "/usr/share/modsecurity-crs/rules/*.conf
</IfModule>

Finally, restart Apache for the changes to take effect:

sudo systemctl restart apache2.service

Install and enable mod_evasive

Mod_evasive is an Apache module which can be used to protect the web server from DoS (Denial of Service), DDoS (Distributed Denial of Service) and brute-force attacks. To install mod_evasive on your server, run this command:

sudo apt-get install libapache2-mod-evasive

Open the default configuration file /etc/apache2/mods-enabled/evasive.conf and edit the settings to look like those below:

<IfModule mod_evasive20.c>
	DOSPageCount        5
	DOSSiteCount        50
	DOSPageInterval     1
	DOSSiteInterval     1
	DOSBlockingPeriod   600
	DOSLogDir           "/var/log/mod_evasive"
</IfModule>

Save and close the file. Create a directory for the log files:

sudo mkdir /var/log/mod_evasive
sudo chown -R www-data: /var/log/mod_evasive

Restart Apache:

sudo systemctl restart apache2.service

Secure MySQL

Secure the MySQL server deployment

The first thing you need to do to secure the MySQL service is to run the mysql_secure_installation script.

sudo mysql_secure_installation

The script will help you to perform important security tasks like setting up root password, disable remote root login, remove anonymous users etc.

Disable remote MySQL access

If you don’t perform remote operations over your MySQL server then disabling the remote access to the service is a very important thing to do. You can do this by editing the /etc/mysql/mysql.conf.d/mysqld.cnf file and changing the bind-address to 127.0.0.1.

bind-address = 127.0.0.1

Restart the service for the changes to take effect.

sudo systemctl restart mysql.service

Create separate MySQL users

Another thing you need to consider is creating separate MySQL users for each database and application.

Log in to MySQL as root:

mysql -u root -p

You can create MySQL database and grant all privileges to a new user using the following commands:

mysql> CREATE DATABASE new_db;
mysql> GRANT ALL PRIVILEGES on new_db.* to 'new_user'@'localhost' identified by 'PaSsW0rD';
mysql> FLUSH PRIVILEGES;
mysql> EXIT

Then, you can use the newly created database and user for your application.

Disable LOCAL INFILE

If you explicitly don’t use LOCAL INFILE then it is good to disable it. Again, edit the MySQL configuration file and add the following line under the [mysqld] block:

local-infile=0

Restart the MySQL service for the changes to take effect.

Secure PHP

If you performed the steps above, your server should be already secure. The last part of securing the LAMP server is securing PHP, which is a pretty straightforward process. Find the location of your PHP ini file:

php --ini | grep "Loaded Configuration File"

All changes we will be making into this file.

Hide PHP basic information

The first step is to hide the information provided by PHP which some attackers may find useful. Open the php.ini file and change the settings to match the following:

expose_php = Off
display_errors = Off
mail.add_x_header = Off

Save the file and restart Apahce:

sudo systemctl restart apache2.service

Disable dangerous PHP functions

The disable_functions directive allows you to disable some functions that could be harmful to your system. Edit the directive in your php.ini file to match the following:

disable_functions = show_source,system,shell_exec,passthru,exec,phpinfo,popen,proc_open,allow_url_fopen,curl_exec,curl_multi_exec

While you are here, disable the remote PHP code execution by using the following settings:

allow_url_fopen=Off
allow_url_include=Off

Restrict file uploads

If you don’t use file uploading features it is totally safe to restrict the file uploads in PHP. Open the php.ini file and set the following setting:

file_uploads=Off

In case you are using file uploading features you can set the following:

file_uploads=On
upload_max_filesize=1M

where upload_max_filesize is the upload size limit.

Restart Apache after making these changes.

Set maximum execution time

Again, edit the php.ini file and change the following settings:

max_execution_time = 30
max_input_time = 30
memory_limit = 40M

This sets the maximum time in seconds a script is allowed to run or parse data as well as will set the maximum amount of memory that a script is allowed to allocate.

Enable open_basedir

The open_basedir directive allows you to set the location from which PHP is allowed to access files. Edit the php.ini file and set the correct location to match your current configuration:

open_basedir="/path/to/the/directory/"

Don’t forget to restart Apache so the changes can take effect.

Of course, if you are one of our Linux VPS Hosting customers, you don’t have to do any of this, simply ask our admins, sit back and relax. Our admins will secure your LAMP server for you immediately.

PS. If you liked this post please share it with your friends on the social networks using the buttons below or simply leave a comment in the comments section. Thanks.

Tutorials
How to install Laravel on Linux
Tutorials
Install PrestaShop on Debian Wheezy VPS with PHP-FPM and Nginx
Tutorials
Install and Configure PureFTPd with MySQL on an OpenSUSE Linux VPS
  • Jaro

    JaroJaro

    Author Reply

    This command doesn’t work (shows php cli ini):

    php –ini | grep “Loaded Configuration File”


    • admin

      adminadmin

      Author Reply

      Make sure that you can access the PHP Command Line Interface using the php command. You can use the TAB key to auto-complete the command and check if the php binary is under different name like php5 or php7.0 for example.


  • juan carlos garcia

    Excellent article mate, implementing this suggestions right now.


 
Free Migration to RoseHosting. Award Winning Linux VPS Hosting with Fully Managed Support. Coupon RHBLOG50 for 50% offOrder Now
+