Introduction
Nginx [engine x] is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP/UDP proxy server, originally written by Igor Sysoev.
Nginx is a high performance web server software. It was released for production in 2004.
Nginx uses an asynchronous event-driven approach to handling requests, similar to Apache HTTP Server Event MPM model. Nginx’s modular event-driven architecture can provide more predictable performance under high loads.
Features
Nginx is a much more flexible and lightweight program than Apache Web Server. It features an event-driven design, which can make better use of today’s computer hardware than Apache’s process-driven design. It comes in two flavours 1. Free & Open Source and 2. Nginx Plus, which is commercially supported product from NGINX, Inc.
The detailed features are listed below:
- Handling of static files, index files and auto-indexing.
- Load balancing with in-band health checks.
- Ability to handle more than 10,000 simultaneous connections with a low memory footprint.
- TLS/SSL with SNI and OCSP stapling support, via OpenSSL.
- Name and IP address-based virtual servers.
- gzip compression and decompression.
- Web page access authentication.
The paid NGINX Plus product includes additional features such as advanced load balancing and access to an expanded suite of metrics for performance monitoring.
In this tutorial, we will learn how to install nginx (FOSS) & secure it on CentOS 7 GNU/Linux.
Requirements
- A server running CentOS 7.
- A static IP Address for your server.
- A non-root user account with sudo privilege set up on your server.
Getting Started
Let’s start by making sure that your Centos-7 server is fully up to date.
You can update your server by running the following command:
sudo yum update -y
Install Nginx
Before installing Nginx, you will need to install the EPEL repository as pre-requisite to install nginx.
You can install it by simply running the following command:
sudo yum install epel-release
Then, install Nginx by running the following command:
sudo yum install nginx
Next, start Nginx service by running the following command:
sudo systemctl start nginx
Then, add Nginx service to start at boot time by running the following command:
sudo systemctl enable nginx
You should see the following output:
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.
Next, you will need to allow the default Nginx port 80 (HTTP) and 443 (HTTPS) using FirewallD.
You can do this by running the following commands:
sudo firewall-cmd --permanent --add-port=80/tcp
sudo firewall-cmd --permanent --add-port=443/tcp
Reload the firewall service for the changes to take effect.
sudo firewall-cmd –reload
Secure Nginx Web Server
In this section, we will learn how to secure Nginx web server.
Update Your Server Packages
A great first step in securing your entire system along with nginx is to update all the packages on your system.
sudo yum update -y
Note: Be sure to determine whether or not update will cause issues with anything running on your system other than Nginx before updating all the packages on your system.
Hide Nginx Version
By default, Nginx shows its name and version in the HTTP headers which can be checked by running following curl
command.,
curl -I http://localhost
Output of curl -I http://localhost
HTTP/1.1 200 OK
Server: nginx/1.5.6 (CentOS)
...
The version of Nginx and the name of the operating system can be seen in the above output, which an attacker can try to solve to compromise Nginx server.
This can be a major security issue for your web server. To hide this information, you need to edit Nginx main configuration file.
sudo nano /etc/nginx/nginx.conf
To hide this header information, add the line server_tokens off;
inside the http configuration part in ‘nginx.conf’ file.
http {
server_tokens off;
}
Save & exit config file and reload ‘nginx’ service.
sudo systemctl reload nginx
The following is the output of curl
after turning of server tokens on nginx configuration –
HTTP/1.1 200 OK
Server: nginx
Setup HTTP Basic Authentication
You will need to install the httpd-tools
package to get the htpasswd
command. This command configures the password to restrict access to the target website.
sudo yum install -y httpd-tools
Create a username & password for basic http authentication. The username & password can be stored in a file which we specify at creation time. The password will be encrypted & saved in file. Run following command to create credentials,
sudo htpasswd -c /etc/nginx/.htpasswd nginx
In above command we are storing credentials in /etc/nginx/.htpasswd
for user nginx
.
You can check the contents of the newly-created file to see the username and hashed password.
sudo cat /etc/nginx/.htpasswd
nginx:$may1$ilgq7ZEO$OarDY15gjNAxuxzv0JTrO/
Update the ‘nginx’ configuration by adding the auth_basic
and auth_basic_user_file
directives in its configuration file.
Add above mentioned directives by editing /etc/nginx/nginx.conf
file:
sudo nano /etc/nginx/nginx.conf
Under the server
section, add auth_basic
and auth_basic_user_file
directives,
...
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
auth_basic "Private Property";
auth_basic_user_file /etc/nginx/.htpasswd;
...
Reload nginx to test the changes with the following command –
sudo systemctl reload nginx
Now try accessing the website you just secured by going to http://your_server_ip/
in your browser. It should present an authentication window (which says “Private Property”, the string we set for auth_basic), and you will not be able to access the website until you enter the correct credentials.
onfigure SSL for Nginx
SSL (Secure Socket Layer protocol) was created by Netscape to secure transactions between web servers and browsers.
SSL is an essential part of creating a secure Apache site. SSL certificates allow you encrypt all the traffic sent to and from your Apache web site to prevent others from viewing all of the traffic. It uses public key cryptography to establish a secure connection. This means that anything encrypted with a public key (the SSL certificate) can only be decrypted with the private key.
In order to set up the self-signed certificate, you will need to install mod_ssl Apache module in your system.
You can install mod_ssl by running the following command:
sudo yum install mod_ssl
Create a directory for SSL certificates with following command:
sudo mkdir /etc/nginx/ssl/
For SSL we’ll need a certificate with a strong signature algorithm, SHA256. For testing purposes or non-production environments you can use a self-signed certificate while ignoring the SSL warnings. Create one self-signed cerificate with following command,
sudo openssl req -x509 -nodes -sha256 -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt
Answer the all questions shown below:
Generating a 2048 bit RSA private key
.........+++
.............................+++
writing new private key to '/etc/nginx/ssl/nginx.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:IN
State or Province Name (full name) []:GUJARAT
Locality Name (eg, city) [Default City]:AHMEDABAD
Organization Name (eg, company) [Default Company Ltd]:Hostpresto
Organizational Unit Name (eg, section) []:IT
Common Name (eg, your name or your server's hostname) []:Hitesh
Email Address []:hitjethva@gmail.com
After that it will create a 2048 bit RSA encrypted key in the file /etc/nginx/ssl/nginx.key
and a SHA256 certificate in the file /etc/nginx/ssl/nginx.crt
.
Now generate stronger, 4096 bit long DH parameters. It may take long time depending upon your system. Run following command to generate the DH parameters,
sudo openssl dhparam -out /etc/nginx/ssl/dhparam.pem 4096
Once you get all the SSL related files ready, configure the default server block for SSL. Open its configuration file for editing,
sudo nano /etc/nginx/sites-enabled/default
Edit the server configuration part adding the SSL part after the server_name
directive as shown below,
server {
...
server_name localhost;
### SSL Config
listen 443 ssl;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
...
Let’s quickly go through each of the configuration parameters configured above :-
- listen — enable the SSL listener on port 443, i.e. the HTTPS port.
- ssl_protocols — enable only these three, considered currently secure protocols – TLSv1 TLSv1.1 TLSv1.2.
- ssl_ciphers — enable only these secure SSL ciphers: EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
- ssl_prefer_server_ciphers — make sure that the client respects the server’s ciphers preferences.
- ssl_dhparam — use the custom, strong DH parameters which we have generated earlier.
- ssl_certificate — use our self-signed SSL certificate. Make sure to change it if you are using another certificate.
- ssl_certificate_key — use our SSL private key, which we have previously generated.
Save and close the file, reload ‘nginx’ to bring above settings in effect.
sudo systemctl reload nginx
Restrict Access by IP
To avoid attackers exploiting weak passwords or software vulnerabilities in your website to gain unauthorised access, you can restrict the site by IP addresses.
For example, if you have an admin site and its admin area is at /site-admin/
, you should limit the access to it only to your IP or to the IPs of all the administrators. To allow or deny access by IP open the corresponding server block — the default server block for Nginx is /etc/nginx/sites-enabled/default
,
sudo nano /etc/nginx/sites-enabled/default
Add following in server
configuration part in file,
server {
...
location /site-admin/ {
allow 192.168.1.1/24;
allow 10.0.0.1/24;
deny all;
}
...
In above example, make sure to replace 192.168.1.1 and 10.0.0.1 with your IPs & subnet mask.
Disable Unwanted HTTP Methods
Most of the time, you need just GET, HEAD & POST HTTP requests in your web application. Allowing TRACE or DELETE is risky as it can allow Cross-Site Tracking attack and potentially allows hackers to steal the cookie information.
You can do this by editing nginx.conf
file:
sudo nano /etc/nginx/nginx.conf
Add the following line inside server block:
if ($request_method !~ ^(GET|HEAD|POST)$ )
{
return 405;
}
Save the file and restart the nginx.
sudo systemctl restart nginx
Now, use telnet
command to test Nginx server.
telnet localhost 80
You should now show 405 Not Allowed:
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
TRACE / HTTP/1.1
Host: testing
HTTP/1.1 405 Not Allowed
Server: nginx/1.6.3
Date: Tue, 31 May 2016 02:59:08 GMT
Content-Type: text/html
Content-Length: 172
Connection: close
<title>405 Not Allowed</title>
<h1>405 Not Allowed</h1>
<hr>nginx/1.6.3
Connection closed by foreign host.
Secure Nginx From A Clickjacking Attack
Clickjacking is a well known web application vulnerability. It is a malicious technique used by an attacker to collect an infected user’s clicks.
The X-Frame-Options in an HTTP response header can be used to indicate whether or not a browser should be allowed to open a page in frame or iframe. This will prevent site content embedded into other sites.
There are three settings for X-Frame-Options:
- SAMEORIGIN: This setting will allow page to be displayed in frame on the same origin as the page itself.
- DENY: This setting will prevent a page displaying in a frame or iframe.
- ALLOW-FROM uri: This setting will allow page to be displayed only on the specified origin.
You can do this by editing the nginx.conf
file:
sudo nano /etc/nginx/nginx.conf
Add the following line inside server block:
add_header X-Frame-Options "SAMEORIGIN";
Save and close the file and restart Nginx service.
sudo systemctl restart nginx
Conclusion
In this tutorial, you have learned how to install and secure the nginx HTTP server. Try to find a balance between functionality and security while working with web servers so that you can run your web sites securely on the network without compromising usability. Security is an ongoing task which requires regular updating, reconfiguration, scanning, etc.