• Get In Touch
June 11, 2016

Install and Secure Nginx on CentOS 7

Want your very own server? Get our 1GB memory, Xeon V4, 25GB SSD VPS for £10.00 / month.
Get a Cloud Server

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:

  1. Handling of static files, index files and auto-indexing.
  2. Load balancing with in-band health checks.
  3. Ability to handle more than 10,000 simultaneous connections with a low memory footprint.
  4. TLS/SSL with SNI and OCSP stapling support, via OpenSSL.
  5. Name and IP address-based virtual servers.
  6. gzip compression and decompression.
  7. 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.

Want your very own server? Get our 1GB memory, Xeon V4, 25GB SSD VPS for £10.00 / month.
Get a Cloud Server

Share this Article!

Related Posts

Node.js Authentication – A Complete Guide with Passport and JWT

Node.js Authentication – A Complete Guide with Passport and JWT

Truth be told, it’s difficult for a web application that doesn’t have some kind of identification, even if you don’t see it as a security measure in and of itself. The Internet is a kind of lawless land, and even on free services like Google’s, authentication ensures that abuses will be avoided or at least […]

Node.js and MongoDB: How to Connect MongoDB With Node

Node.js and MongoDB: How to Connect MongoDB With Node

MongoDB is a document-oriented NoSQL database, which was born in 2007 in California as a service to be used within a larger project, but which soon became an independent and open-source product. It stores documents in JSON, a format based on JavaScript and simpler than XML, but still with good expressiveness. It is the dominant […]

Using MySQL with Node.js: A Complete Tutorial

Using MySQL with Node.js: A Complete Tutorial

Although data persistence is almost always a fundamental element of applications, Node.js has no native integration with databases. Everything is delegated to third-party libraries to be included manually, in addition to the standard APIs. Although MongoDB and other non-relational databases are the most common choice with Node because if you need to scale an application, […]

Node.Js Vs Django: Which Is the Best for Your Project

Node.Js Vs Django: Which Is the Best for Your Project

Django and NodeJs are two powerful technologies for web development, both have great functionality, versatile applications, and a great user interface. Both are open source and can be used for free. But which one fits your project best? NodeJs is based on JavaScript, while Django is written in Python. These are two equally popular technologies […]

Nodejs Vs PHP:  Which Works Best?

Nodejs Vs PHP: Which Works Best?

Before getting into the “battle” between Node.js and PHP we need to understand why the issue is still ongoing. It all started with the increased demand for smartphone applications, their success forcing developers to adapt to new back-end technologies that could handle a multitude of simultaneous requests. JavaScript has always been identified as a client-side […]