In this tutorial we’re going to take a look in an important topic, secure server deployment. We’re going to create a web application that handles API requests using Apache 2, PHP 7 and MySQL. Our architecture is made of one API server and one database server.
1. Prepare your system
Always keep your system up to date. This ensures you get all latest security patches.
sudo apt-get u
pdate
sudo apt-get upgrade
2. Install Apache2
The Apache web server is among the most popular web servers in the world. It has been in wide use for much of the history of the web and it performs really well.
sudo apt-get apache2
After installation has been successful we can configure our server name.
sudo nano /etc/apache2/apache2.conf
Find ServerName in the configuration file and edit it like this
ServerName your_domainName_or_IP
Next, check for syntax errors by typing:
sudo apache2ctl configtest
If everything went well, it should output Syntax OK.
3. Install PHP7
sudo apt install php
Always sanitize user input for our API using PHP’s built in mysql_real_escape_string
method!
4. Install Fail2Ban
While connecting to your server through SSH can be very secure, the SSH daemon itself is a service that must be exposed to the internet to function properly. This comes with some inherent risk.
A service called fail2ban can mitigate this problem by creating rules that can automatically alter your iptables firewall configuration based on a predefined number of unsuccessful login attempts.
sudo apt-get install fail2ban
The fail2ban service keeps its configuration in /etc/fail2ban/jail.conf
file.
Since this file can be modified by package upgrades, we should not edit this file in-place, but rather copy it so that we can make our changes safely.
awk '{ printf "# "; print; }' /etc/fail2ban/jail.conf | sudo tee /etc/fail2ban/jail.local
Settings located under the [DEFAULT]
section will be applied to all services enabled for fail2ban that are not overridden in the service’s own section.
To edit our configuration file type
sudo nano /etc/fail2ban/jail.conf
Our configuration file should look like this
[DEFAULT]
ignoreip = 127.0.0.1/8
bantime = 172800
findtime = 60
maxretry = 5
The ignoreip
setting configures the source addresses that fail2ban ignores. By default, it is configured to not ban any traffic coming from the local machine.
The bantime
parameter sets length
of time in seconds that a client will be banned when they have failed to authenticate correctly. In our example a client will be banned for 48 hours.
The next two parameters that you want to pay attention to are findtime
and maxretry
. These work together to establish the conditions under which a client is found to be an illegitimate user that should be banned. The maxretry
variable sets the number of tries a client has to authenticate within a window of time defined by findtime
, before being banned. In our example a client will be banned if it fails to login 5 times in 60 seconds.
5. Configuring Iptables
Iptables is a standard firewall included in most Linux distributions by default (a modern variant called nftables will begin to replace it). Iptables are reloaded on every boot, to prevent that we’ going to install iptables-persistent package.
sudo apt-get install iptables-persistent
Next we’re going to start adding our rules.
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
sudo iptables -A INPUT -j DROP
You can save the firewalls so that they survive a reboot by typing:
sudo dpkg-reconfigure iptables-persistent
With this configuration we’re only accepting incoming traffic on our management SSH port 22, web server port 80 and our SSL web server port 443 (SSL).
Often, services on the server communicate with each other by sending network packets to each other. We want this type of behaviour to be allowed
sudo iptables -A INPUT -i lo -j ACCEPT
sudo service fail2ban start
Because we’re running our server on VPC instance for DDoS protection we’ll be using Alibaba Cloud Anti-DDoS.
6. Configuring Apache settings
We’re going to configure some additional Apache settings, such as hiding our server version, and disabling ETags. Open your Apache configuration and edit it:
sudo nano /etc/apache2/httpd.conf
<Directory /var/www/your_api_folder>
Options FollowSymLinks
AllowOverride None
Require all granted
</Directory>
Header unset Pragma
FileETag None
Header unset ETag
ServerSignature Off
ServerTokens Prod
We’re also going to hide Powerd-by header. Open your php.ini
sudo nano /etc/php/7.0/apache2/php.ini
edit the following line so it looks like this expose_php = Off
7. Database deployment
Install MySQL server
sudo apt-get install mysql-server
Since we’re using another VPC instance for our database server, we need to repeat steps 1, 4 and 5. We’re going to add different set of Iptables rules for database server.
iptables -A INPUT -p tcp -s **SERVER_IP** --dport 3306 -j ACCEPT
iptables -A INPUT -p tcp -s 127.0.0.1 --dport 3306 -j ACCEPT
iptables -A INPUT -p tcp -s **SERVER_IP** --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 3306 -j DROP
Our database server only accepts connections on port 3306 and 22 from our API server IP. If we want to manage our database server we need to connect to it via our API server since it only allows connections from its IP.
Next, we want our MySQL server to accept remote connections
sudo nano */etc/mysql/mysql.conf.d/mysqld.cnf*
find this line bind-address = 127.0.0.1
and replace 127.0.0.1 with our API server IP.
It’s also a good practice to create a new MySQL user that won’t have root privileges, we’re going to use newly created user to run all our queries.
Conclusion
In this tutorial we covered some basic server security practices. It’s also strongly recommended to use a SSL certificate and also pin it to your apps that are using this API. If everything went fine we should be able to start Apache and MySQL server.