TLS, or transport layer security, and its predecessor SSL, secure sockets layer, are secure protocols created in order to place normal traffic in a protected, encrypted wrapper.


These protocols allow traffic to be sent safely between remote parties without the possibility of the traffic being intercepted and read by someone in the middle.

They are also instrumental in validating the identity of domains and servers throughout the internet by establishing a server as trusted and genuine by a certificate authority.


In this guide, we'll cover how to create a self-signed SSL certificate for Apache on an Ubuntu server, which will allow you to encrypt traffic to your server.

To enable TLS between the server and client you need to setup both the server and the client with appropriate certificates and configuration. The following instructions walk you through the setup process.


Pre-requisites

Before you begin, you should have some configuration already taken care of.

We will be operating as a non-root user with sudo privileges in this guide.

You are also going to need to have Apache installed. If you don't already have that up and running, you can quickly fix that by typing:


> sudo apt-get update
> sudo apt-get install apache2


Step One — Activate the SSL Module


SSL support actually comes standard in the Ubuntu 14.04+ Apache package. We simply need to enable it to take advantage of SSL on our system.

Enable the module by typing:


> sudo a2enmod ssl


After you have enabled SSL, you'll have to restart the web server for the change to be recognized:


> sudo service apache2 restart


With that, our web server is now able to handle SSL if we configure it to do so.


Using self-signed certificate.


Step Two — Create a Self-Signed SSL Certificate for the Server/Client


While doing this always keep in mind that the root CA certificate you will create now is used by the webserver as comparison to the final webserver certificate and that this root CA certificate must be imported in your browser.

For doing this without any oncoming problems we advise to create RSA keys without a passphrase; otherwise Apache and your browser will not be able to resolve the certificate chain!


On the server create a couple of directories for working with the certificates:


  SERVER:

   mydir> mkdir $HOME/buildcerts
   mydir> mkdir $HOME/certs


Copy the following script to the buildcerts directory that was just created:


#!/bin/sh

# File Name "generate-keys.sh"
# mkdir -p $HOME/buildcert
# cd $HOME/buildcert
# rm -f *.key *.csr *.crt *.pem *.srl

SUBJ="/C=/ST=/L=/O=/CN=ca"

# Generate CA Private Key
openssl req \
        -newkey rsa:2048 \
        -nodes \
        -keyout ca.key \
        -subj $SUBJ

# Generate Req
openssl req \
        -key ca.key \
        -new -out ca.csr \
        -subj $SUBJ

# Generate self signed x509
openssl x509 \
        -signkey ca.key \
        -in ca.csr \
        -req \
        -days 365 -out ca.crt

## Change restconf to your entry-point
SUBJ="/C=/ST=/L=/O=/CN=restconf"

# Generate Server Private Key
openssl req \
        -newkey rsa:2048 \
        -nodes \
        -keyout server.key \
        -subj $SUBJ

# Generate Req
openssl req \
        -key server.key \
        -new -out server.csr \
        -subj $SUBJ

# Generate x509 with signed CA
openssl x509 \
        -req \
        -in server.csr \
        -CA ca.crt \
        -CAkey ca.key \
        -CAcreateserial \
        -out server.crt

SUBJ="/C=/ST=/L=/O=/CN=client.com"

# Generate Client Private Key
openssl req \
        -newkey rsa:2048 \
        -nodes \
        -keyout client.key \
        -subj $SUBJ

# Generate Req
openssl req \
        -key client.key \
        -new -out client.csr \
        -subj $SUBJ

# Generate x509 with signed CA
openssl x509 \
        -req \
        -in client.csr \
        -CA ca.crt \
        -CAkey ca.key \
        -out client.crt

echo ""
echo " == Validate Server"
openssl verify -verbose -CAfile ca.crt server.crt
echo ""
echo " == Validate Client"
openssl verify -verbose -CAfile ca.crt client.crt


Cd to the buildcerts directory, run the key generation script and check the files were created:


  SERVER:

  mydir> cd buildcerts
  buildcerts> ./generate-keys.sh

  buildcerts> ls -l
  -rw-rw-r-- 1 user group  956 Mar 16 15:05 ca.crt
  -rw-rw-r-- 1 user group  883 Mar 16 15:05 ca.csr
  -rw-rw-r-- 1 user group 1708 Mar 16 15:05 ca.key
  -rw-rw-r-- 1 user group   17 Mar 16 15:05 ca.srl
  -rw-rw-r-- 1 user group  969 Mar 16 15:05 client.crt
  -rw-rw-r-- 1 user group  891 Mar 16 15:05 client.csr
  -rw-rw-r-- 1 user group 1708 Mar 16 15:05 client.key
  -rwxrwxr-x 1 user group 1513 Feb 23 16:29 generate-keys.sh
  -rw-rw-r-- 1 user group  969 Mar 16 15:05 server.crt
  -rw-rw-r-- 1 user group  891 Mar 16 15:05 server.csr
  -rw-rw-r-- 1 user group 1704 Mar 16 15:05 server.key


Copy the server certificates to their proper places:


  SERVER:

  buildcerts> sudo cp ca.crt /usr/local/share/ca-certificates/
  buildcerts> sudo cp client.crt /etc/ssl/certs/
  buildcerts> cp server.crt ../certs/
  buildcerts> cp server.key ../certs/


For the client certification, if the client is not localhost, also create a couple of directories on your client machine for working with the certificates:


  CLIENT:
  
  mydir> mkdir $HOME/buildcerts
  mydir> mkdir $HOME/certs


On the server copy the files you created to the client machine using sftp:


  SERVER:

  mydir> cd $HOME/buildcerts
  buildcerts> sftp CLIENT_USERNAME@CLIENT
  sftp> cd buildcerts
  sftp> put *
  sftp> bye


Now copy the certificates on the client to their proper places:


  CLIENT:

  mydir> cd $HOME/buildcerts
  buildcerts> sudo cp ca.crt /usr/local/share/ca-certificates
  buildcerts> sudo cp server.crt /etc/ssl/certs
  buildcerts> cp client.crt $HOME/certs/
  buildcerts> cp client.key $HOME/certs/


If you want to run client and server on localhost, copy client certificates described in the previous step to the same place you copied server certificates.

Go to the /etc/ssl/certs directory, run updates and check the results:


 SERVER:

  buildcerts> cd /etc/ssl/certs

#make sure system does not have any previously installed certificates
  etc/ssl/certs> sudo rm /etc/ssl/certs/ca.pem

  etc/ssl/certs> sudo update-ca-certificates
  
  etc/ssl/certs> ls -l | grep ca.crt
  lrwxrwxrwx 1 root root     39 Mar 16 15:52 ca.pem -> /usr/local/share/ca-  certificates/ca.crt
  
  etc/ssl/certs> ls -l | grep client.crt
  lrwxrwxrwx 1 root root     10 Mar 16 15:52 55a71c96.0 -> client.crt
  lrwxrwxrwx 1 root root     10 Mar 16 15:52 ca0a1cd4.0 -> client.crt
  -rw-r--r-- 1 root root    969 Mar 16 15:43 client.crt


Generate the client Fingerprint:


certs> cd $HOME/buildcerts
buildcerts> openssl x509 -noout -fingerprint -sha1 -inform pem -in client.crt

SHA1   Fingerprint=4B:A7:05:1E:12:F7:BC:FF:2D:9E:48:66:0A:8B:CC:D7:A5:65:E5:97


Add following four parameters lines in /etc/yumapro/netconfd-pro.conf and substitute the Fingerprint value. 


netconfd-pro {
    with-netconf-tls true
    netconf-tls-certificate ~/certs/server.crt
    netconf-tls-key ~/certs/server.key
    cert-usermap <YOUR_USERNAME>@<first_six_pairs_of_the_SHA1_Fingerprint>
}



Repeat the same steps on your client (if you are not running client  and server on localhost)


  CLIENT:
  
  buildcerts> cd /etc/ssl/certs
  etc/ssl/certs> sudo update-ca-certificates
  
  etc/ssl/certs> ls -l | grep ca.crt
  
  lrwxrwxrwx 1 root root     39 Mar 16 16:25 ca.pem -> /usr/local/share/ca-  certificates/ca.crt
  
  etc/ssl/certs> ls -l | grep server.crt
  
  lrwxrwxrwx 1 root root     10 Mar 16 16:25 5ec6e3b0.0 -> server.crt
  lrwxrwxrwx 1 root root     10 Mar 16 16:25 942ef14c.0 -> server.crt
  -rw-r--r-- 1 root root    969 Mar 16 16:24 server.crt



Step Three — Configure Apache to Use TLS protocol and generated certificates


Now that we have our certificate and key available, we can configure Apache to use these files in the RESTCONF virtual host file.


Open the file with root privileges now:


> sudo <your_editor> /etc/apache2/sites-available/restconf.conf


Replace <your_editor> with the editor of your choice such as vi, vim, emacs, gedit, etc.

And add the following configurations into the file:


<IfModule mod_ssl.c>
<VirtualHost *:443>
    DocumentRoot /var/www/yang-api

    #### CHANGE 'localhost' to match your server name
    ServerName localhost

    AllowEncodedSlashes On
    AddHandler fcgid-script .fcgi

    #### CHANGE '/var/www/yang-api' to match DocumentRoot if needed
    <Directory /var/www/yang-api>
        SetHandler fcgid-script
        Options Indexes FollowSymLinks ExecCGI
        AllowOverride all
        Order allow,deny
        allow from all

    </Directory>

    #### CHANGE '/var/www/yang-api' to match DocumentRoot if needed
    <Directory /var/www/yang-api/.well-known>
        SetHandler default-handler
        ForceType 'application/xrd+xml'

        ## enable mod_headers to use the following directives
        ## > a2enmod headers
        Header unset Etag
        Header unset Last-Modified
        Header unset Accept-Ranges
        Header set Cache-Control no-cache
        Header merge Cache-Control no-store
        Header set Pragma no-cache

        ## Ony GET is allowed
        <Limit POST PATCH DELETE PUT>
            Order deny,allow
            Deny from all
        </Limit>

        AllowOverride all
        Order allow,deny
        allow from all
    </Directory>

    SSLEngine on

    #### CHANGE '/home/user' to your certificates dir
    SSLCertificateFile /home/user/certs/server.crt
    SSLCertificateKeyFile /home/user/certs/server.key


</VirtualHost>
</IfModule>


Save and exit the file when you are finished.



Step Four — Activate the TLS Virtual Host


Now that we have configured our TLS-enabled virtual host, we need to enable it:


> sudo a2ensite restconf.conf


We then need to restart Apache to load our new virtual host file:


> sudo service apache2 restart


This should enable your new virtual host, which will serve encrypted content using the TLS certificate you created.

To verify that the site was loaded correctly examine the output of the following command:


> sudo apache2ctl -S

AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message
VirtualHost configuration:
*:443                  localhost (/etc/apache2/sites-enabled/restconf.conf:24)
*:80                   is a NameVirtualHost
         default server localhost (/etc/apache2/sites-enabled/restconf.conf:74)
         port 80 namevhost localhost (/etc/apache2/sites-enabled/restconf.conf:74)
ServerRoot: "/etc/apache2"
Main DocumentRoot: "/var/www/html"
Main ErrorLog: "/var/log/apache2/error.log"
Mutex default: dir="/var/lock/apache2" mechanism=fcntl 
Mutex fcgid-pipe: using_defaults
Mutex watchdog-callback: using_defaults
Mutex rewrite-map: using_defaults
Mutex ssl-stapling-refresh: using_defaults
Mutex fcgid-proctbl: using_defaults
Mutex ssl-stapling: using_defaults
Mutex ssl-cache: using_defaults
PidFile: "/var/run/apache2/apache2.pid"
Define: DUMP_VHOSTS
Define: DUMP_RUN_CFG
User: name="www-data" id=33
Group: name="www-data" id=33


As shown in the output we have configred our Web server as a localhost Virtual Host that listens on port 443 for any incoming connection from clients.


Step Five — Test your Setup


Now that you have everything prepared, you can test your configuration by visiting your server's domain name or public IP address after specifying the https:// protocol.

Via browser, you will need to add your self-signed certificate into browser. Open Browser's Certificate Manager and import Your Certificate.


Via yangcli-pro:

Next you need to configure the client with the parameters needed to use TLS by editing the yangcli-pro.conf file. If you have an existing yangcli-pro.conf then add the following parameter lines,

within “yangcli-pro {“ and “}”, to the existing file. If you don’t have an existing yangcli-pro.conf file then run your editor as shown and a yangcli-pro.conf file will be created, then add the lines shown.


buildcerts> sudo <your_editor> /etc/yumapro/yangcli-pro.conf


Replace <your_editor> with the editor of your choice such as vi, vim, emacs, gedit, etc.

Add the following parameters:


  yangcli-pro {
       ssl-fallback-ok false
       ssl-certificate $HOME/certs/client.crt
       ssl-key $HOME/certs/client.key
       ssl-trust-store $HOME/certs/ca.crt
  }


Run yangcli-pro on the client and connect using the command show below:


  CLIENT:
  
  mydir> yangcli-pro  user=<username> server=<SERVER_HOST> protocol=restconf transport=tls