Jan 5, 2017

How To Generate a Self-Signed SSL Certificate for Nginx on CentOS 7


This article will guide you through the steps to create a self-signed SSL certificate in order to use with an Nginx web server on a CentOS 7 server to secure web traffic. To begin with self-signed certificate creation process, you need to log into your CentOS 7 Server as a sudo (non-root) user.





Install Nginx and Adjust the Firewall
You should make sure that the Nginx web server is installed on your CentOS 7 machine.

Since Nginx is not available in CentOS's default repositories, it is present in the EPEL (extra packages for Enterprise Linux) repository. You can enable the EPEL repository to access to the Nginx package by executing the following commands:

sudo yum install epel-release

Next, we can install Nginx by typing:

sudo yum install nginx

Start the Nginx service by typing:

sudo systemctl start nginx

Check that the service is up and running by typing:

systemctl status nginx

Output
● nginx.service - The nginx HTTP and reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
   Active: active (running) since Thur 2017-01-05 16:20:40 UTC; 12s ago

. . .

Jan 05 16:20:40 centos-7-server systemd[1]: Started The nginx HTTP and reverse proxy server.

You will also want to enable Nginx, so it starts when your server boots:

sudo systemctl enable nginx

Output
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.

Next, we need to make sure that we are not blocking access to port 80 and 443 with a firewall. If you are not using a firewall, you can skip ahead to the next section.

If you have a firewalld firewall running, you can open these ports by typing:

sudo firewall-cmd --add-service=http
sudo firewall-cmd --add-service=https
sudo firewall-cmd --runtime-to-permanent

If have an iptables firewall running, the commands you need to run are highly dependent on your current rule set. For a basic rule set, you can add HTTP and HTTPS access by typing:

sudo iptables -I INPUT -p tcp -m tcp --dport 80 -j ACCEPT
sudo iptables -I INPUT -p tcp -m tcp --dport 443 -j ACCEPT

You should now be able to access the default Nginx page through a web browser.

Create the SSL Certificate
The /etc/ssl/certs directory, which can be used to hold the public certificate, should already exist on the server. Let's create an /etc/ssl/private directory as well, to hold the private key file. Since the secrecy of this key is essential for security, we will lock down the permissions to prevent unauthorized access:

sudo mkdir /etc/ssl/private
sudo chmod 700 /etc/ssl/private

Now, we can create a self-signed key and certificate pair with OpenSSL in a single command by typing:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt

You will be asked a series of questions.

Fill out the prompts appropriately. The most important line is the one that requests the Common Name (e.g. server FQDN or YOUR name). You need to enter the domain name associated with your server or your server's public IP address.

The entirety of the prompts will look something like this:

Output
Country Name (2 letter code) [AU]:PK
State or Province Name (full name) [Some-State]:Islamabad
Locality Name (eg, city) []:Islamabad City
Organization Name (eg, company) [Internet Widgits Pty Ltd]:TECH SUPPORT PK
Organizational Unit Name (eg, section) []:IT
Common Name (e.g. server FQDN or YOUR name) []:your_server_IP_address
Email Address []:admin@example.com

Both of the files you created will be placed in the appropriate subdirectories of the /etc/ssl directory.

While we are using OpenSSL, we should also create a strong Diffie-Hellman group, which is used in negotiating Perfect Forward Secrecy with clients.

We can do this by typing:

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

This may take a few minutes, but when it's done you will have a strong DH group at /etc/ssl/certs/dhparam.pem that we can use in our configuration.


Configure Nginx to Use SSL
The default Nginx configuration in CentOS is fairly unstructured, with the default HTTP server block living within the main configuration file. Nginx will check for files ending in .conf in the /etc/nginx/conf.d directory for additional configuration.

We will create a new file in this directory to configure a server block that serves content using the certificate files we generated. We can then optionally configure the default server block to redirect HTTP requests to HTTPS.

Create the TLS/SSL Server Block

Create and open a file called ssl.conf in the /etc/nginx/conf.d directory:

sudo vi /etc/nginx/conf.d/ssl.conf

Inside, begin by opening a server block. By default, TLS/SSL connections use port 443, so that should be our listen port. The server_name should be set to the server's domain name or IP address that you used as the Common Name when generating your certificate. Next, use the ssl_certificate, ssl_certificate_key, and ssl_dhparam directives to set the location of the SSL files we generated:

/etc/nginx/conf.d/ssl.conf
server {
    listen 443 http2 ssl;
    listen [::]:443 http2 ssl;

    server_name server_IP_address;

    ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
    ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
}

Now, we will add some additional SSL options that will increase our site's security.

/etc/nginx/conf.d/ssl.conf
server {
    listen 443 http2 ssl;
    listen [::]:443 http2 ssl;

    server_name server_IP_address;

    ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
    ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;

    ########################################################################
    # from https://cipherli.st/                                            #
    # and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html #
    ########################################################################

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
    ssl_ecdh_curve secp384r1;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 203.130.2.3 203.130.2.4 valid=300s;
    resolver_timeout 5s;
    # Disable preloading HSTS for now.  You can use the commented out header line that includes
    # the "preload" directive if you understand the implications.
    #add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
    add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;

    ##################################
    # END https://cipherli.st/ BLOCK #
    ##################################
}

Because we are using a self-signed certificate, the SSL stapling will not be used. Nginx will simply output a warning, disable stapling for our self-signed cert, and continue to operate correctly.

Finally, add the rest of the Nginx configuration for your site. This will differ depending on your needs. We will just copy some of the directives used in the default location block for our example, which will set the document root and some error pages:

/etc/nginx/conf.d/ssl.conf
server {
    listen 443 http2 ssl;
    listen [::]:443 http2 ssl;

    server_name server_IP_address;

    ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
    ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;

    ########################################################################
    # from https://cipherli.st/                                            #
    # and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html #
    ########################################################################

    . . .

    ##################################
    # END https://cipherli.st/ BLOCK #
    ##################################

    root /usr/share/nginx/html;

    location / {
    }

    error_page 404 /404.html;
    location = /404.html {
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
    }
}

When you are finished, save and exit. This configures Nginx to use our generated SSL certificate to encrypt traffic. The SSL options specified ensure that only the most secure protocols and ciphers will be used. Note that this example configuration simply serves the default Nginx page, so you may want to modify it to meet your needs.





Create a Redirect from HTTP to HTTPS (OPTIONAL)
Create a new file called ssl-redirect.conf and open it for editing with the following command:

sudo vi /etc/nginx/default.d/ssl-redirect.conf

Then paste in this line:

/etc/nginx/default.d/ssl-redirect.conf
return 301 https://$host$request_uri/;

Save and close the file when you are finished. This configures the HTTP on port 80 (default) server block to redirect incoming requests to the HTTPS server block we configured.

Activate the Changes in Nginx
Now that we've made changes, we can restart Nginx to implement new configuration.

First, we should check to make sure that there are no syntax errors in our files. We can do this by executing:

sudo nginx -t

If everything is successful, you will get a result that looks like this:

Output
nginx: [warn] "ssl_stapling" ignored, issuer certificate not found
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Notice the warning in the beginning. As noted earlier, this particular setting throws a warning since our self-signed certificate can't use SSL stapling. This is expected and our server can still encrypt connections correctly.

If your output matches the above, your configuration file has no syntax errors. We can safely restart Nginx to implement our changes:

sudo systemctl restart nginx

The Nginx process will be restarted, implementing the SSL settings we configured.

Test Encryption

Open your web browser and type https:// followed by your server's domain name or IP into the address bar:

https://server_domain_or_IP

Because the certificate we created isn't signed by one of your browser's trusted certificate authorities, you will likely see a scary looking warning like the one below:


This is expected and normal. We are only interested in the encryption aspect of our certificate, not the third party validation of our host's authenticity. Click "ADVANCED" and then the link provided to proceed to your host anyway:


You should be taken to your site. If you look in the browser address bar, you will see some indication of partial security. This might be a lock with an "x" over it or a triangle with an exclamation point. In this case, this just means that the certificate cannot be validated. It is still encrypting your connection.

If you configured Nginx to redirect HTTP requests to HTTPS, you can also check whether the redirect functions correctly:

http://server_domain_or_IP

If this results in the same icon, this means that your redirect worked correctly.

Conclusion
You have successfully configured your Nginx server to use strong encryption for client connections. This will allow you serve requests securely, and will prevent outside access from reading your traffic.

Post a Comment

 
TECH SUPPORT © 2012-2016