CodeRevisited Keep Learning.. Cheers!

Two Way SSL Authentication

This post demonstrate how to authenticate clients using Certificates. In another words, this post demonstrates the mutual SSL authentication.

Suppose, we have a service running in an application server and we wanted to expose it to outside world through Apache HTTP Server using two way SSL authentication. We would like to do the following

  • Redirect requests from Apache HTTP Server to underlying Tomcat/Jetty Servers. This has been discussed here
  • Enable SSL for Apache HTTP Server. This has been discussed here
  • How to set up two way SSL Authentication. I will discuss this in this post.

What is Mutual SSL Authentication

Mutual SSL authentication or certificate based mutual authentication refers to two parties authenticating each other through verifying the provided digital certificate so that both parties are assured of the others’ identity.

In technology terms, it refers to a client (web browser or client application) authenticating themselves to a server (website or server application) and that server also authenticating itself to the client through verifying the certificate issued by the trusted Certificate Authorities (CAs)

From a high-level point of view, the process of authenticating and establishing an encrypted channel using certificate-based mutual authentication involves the following steps:

  • A client requests access to a protected resource.
  • The server presents its certificate to the client.
  • The client verifies the server’s certificate based on the root certificate authority.
  • If successful, the client sends its certificate to the server.
  • The server verifies the client’s credentials based on the configured certificate authority.
  • If successful, the server grants access to the protected resource requested by the client.

Mutual SSL

Original source of image

Assuming that our service is ready to accept client requests over SSL. It has been discussed here

We will see how to create client certificate and configure server to accept requests based on client authetication.

Creating client certificate

At Client Side

  • Create Client Private Key
openssl genrsa -out client.key 2048
  • Generate CSR which we will send to CA for signing
openssl req -new -key client.key -out client.csr

Client CSR

We use the root certificate authority created here to generate Client certificates.

  • Signing CSR
openssl x509 -req -in client.csr -CA rootCA.pem -CAkey rootCA.key -CAserial rootCA.srl -out client.crt -days 500 -sha256

CSR Sign

client.crt will be sent to client. Client will use this and generate pkcs12 for use within a browser

openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12

Importing Client certificate to a browser

In Windows machine, Go to IE, Internet Options, go to the Content tab, then hit the Certificates button. This will take you to the the Windows certificate repository. Import the rootCA.pem (not the key) under Personal.

Server Side Configuration

  • In httpd-ssl.conf uncomment
SSLVerifyClient require
SSLVerifyDepth  10
  • Uncomment and set CA root certificate file path against
SSLCACertificateFile "c:/Apache24/conf/rootCA.pem"

Restart Apache Server, if we hit our service running at https://localhost/hello, browser will shows us list of available certificates for use. If we select appropriate certificate, we get response from the service.

Certificate Select

We can onboard as many clients we wanted by generating client certificates using our root CA.

But, what if client wants to use their own certificates. How can server accommodate this? Alternatively, we should understand how to handle multiple CAs for validating end user Client Certificates.

There are two approaches through which we can achieve this.

  1. combining root CAs into one big file and specifying it as SSLCACertificateFile This approach is preferable if we have very less number of root CAs to manage.
  2. Placing root CAs into a directory and generating hash symlinks. This directory should be specified against SSLCACertificatePath

Read here for more information on second approach.

References

An-Introduction-to-Mutual-SSL-Authentication

Configure SSL on Apache

This post demonstrates how to configure SSL on Apache HTTP Server. It demonstrates how to create SSL certificate authority to use on Apache.

What is SSL?

SSL, stands for Secure Socket Layer, creates an encrypted connection between a web server and a client web browser allowing for private information to be transmitted without the problems of eavesdropping, data tampering, or message forgery.

All browsers have the capability to interact with secured web servers using the SSL protocol. However, the browser and the server need what is called an SSL Certificate to be able to establish a secure connection. SSL Certificates have a key pair: a public and a private key. These keys work together to establish an encrypted connection. The certificate also contains what is called the “subject,” which is the identity of the certificate/website owner.

How Does the SSL Certificate Create a Secure Connection?

When a browser attempts to access a website that is secured by SSL, the browser and the web server establish an SSL connection using a process called an SSL Handshake. Note that the SSL Handshake is invisible to the user and happens instantaneously.

  • Browser connects to a web server (website) secured with SSL (https). Browser requests that the server identify itself.
  • Server sends a copy of its SSL Certificate, including the server’s public key.
  • Browser checks the certificate root against a list of trusted CAs and that the certificate is unexpired, unrevoked, and that its common name is valid for the website that it is connecting to. If the browser trusts the certificate, it creates, encrypts, and sends back a symmetric session key using the server’s public key.

At this point, If the server cannot be authenticated, the user is warned of the problem that an encrypted and authenticated connection cannot be established

  • Server decrypts the symmetric session key using its private key and sends back an acknowledgement encrypted with the session key to start the encrypted session.
  • Server and Browser now encrypt all transmitted data with the session key.

How to get SSL Certificate

To get a certificate, we must create a Certificate Signing Request (CSR) on our server. This process creates a private key and public key on your server. The CSR data file that we send to the SSL Certificate issuer (called a Certificate Authority or CA) contains the public key. The CA uses the CSR data file to create a data structure to match our private key without compromising the key itself. Certificate authorities charges some nominal amount to issue these SSL certificates.

For our example, we are going to create our own certificate Authority to generate server certificates.

Create Own SSL Certificate Authority

We use OpenSSL to create your own private certificate authority. The process for creating your own certificate authority

  • Create a private key
openssl genrsa -des3 -out rootCA.key 2048

By using above command, we can generate private key with 2048 bit long. This is the basis of all trust for your certificates. Please keep the password safe, and if someone gets a hold of it, they can generate certificates that your browser will accept

  • Self-sign
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.pem

This will ask for various information. Once done, this will create an SSL certificate called rootCA.pem, signed by itself, valid for 1024 days, and it will act as our root certificate. The interesting thing about traditional certificate authorities is that root certificate is also self-signed.

Self Sign

  • Install root CA on your various workstations In Windows machine, Go to IE, Internet Options, go to the Content tab, then hit the Certificates button. This will take you to the the Windows certificate repository. Import the rootCA.pem (not the key) under the Trusted Root Certificate Authorities tab.

Certificate Import

From above three steps, we have root certificate authority is ready and installed in our browser. Now we are going to create SSL certificate for our Apache HTTP Server

Create Server Certificate

  • Create a private key
openssl genrsa -out server.key 2048

Creates private key for server

  • certificate signing request
openssl req -new -key server.key -out server.csr

You’ll be asked various questions (Country, State/Province, etc.). Answer them how you see fit. The important question to answer though is common-name.

Common Name (e.g. server FQDN or YOUR name) []:localhost

Whatever you see in the address field in your browser when you go to your device must be what you put under common name, even if it’s an IP address. Yes, even an IP (IPv4 or IPv6) address works under common name. If it doesn’t match, even a properly signed certificate will not validate correctly and you’ll get the “cannot verify authenticity” error.

Once CSR is ready, we need rootCA.key to sign this CSR

openssl x509 -req -in server.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out server.crt -days 500 -sha256

This creates a signed certificate called device.crt which is valid for 500 days

Note on CAcreateserial

The first time you use your CA to sign a certificate you can use the -CAcreateserial option. This option will create a file (rootCA.srl) containing a serial number. You are probably going to create more certificate, and the next time you will have to do that use the -CAserial option (and no more -CAcreateserial) followed with the name of the file containing your serial number. This file will be incremented each time you sign a new certificate. This serial number will be readable using a browser (once the certificate is imported to a pkcs12 format). And we can have an idea of the number of certificate created by a CA.

Configurations on Apache Server

  • Enable SSL module by uncommenting LoadModule ssl_module modules/mod_ssl.so in conf/httpd.conf in Apache installation directory.
  • Uncomment LoadModule socache_shmcb_module modules/mod_socache_shmcb.so This is required by SSL session cache.
  • Uncomment Include conf/extra/httpd-ssl.conf to include SSL conf
  • In httpd-ssl.conf file, set Server Name same as Common Name given in CSR
ServerName localhost:443
  • Copy server.crt, server.key to conf directory of Apache
  • Specify server.crt path against SSLCertificateFile in httpd-ssl.conf
SSLCertificateFile "c:/Apache24/conf/server.crt"
  • Specify server.key path against SSLCertificateKeyFile in httpd-ssl.conf
SSLCertificateKeyFile "c:/Apache24/conf/server.key"
  • Restart Apache Server. Our server is SSL ready.

If wanted to redirect request to any underlying services, we can add the required Rewrite rules in httpd-ssl.conf before </VirtualHost>

Refer to my previous post where i discussed about redirection from Apache Server to Jetty service. Using the same example, we have to the following rules in httpd-ssl.conf

RewriteEngine On
RewriteRule ^/hello http://localhost:8080/hello [P]
  • Restart Apache Server, if we hit https://localhost/hello, it will get redirected to http://localhost:8080/hello

FAQ

  • ERROR: SSLSessionCache: ‘shmcb’ session cache not supported (known names: ). Maybe you need to load the appropriate socache mod ule (mod_socache_shmcb?).

    Uncomment LoadModule socache_shmcb_module modules/mod_socache_shmcb.so in httpd.conf

References

Creating Your Own SSL Certificate Authority

Redirect fom Apache HTTP server to Jetty

This post demonstrates how to redirect requests from apache HTTP server to Jetty. These steps are independent of any application server and can be used for Tomcat.

Real-world websites use apache HTTP server to serve static content because

  • Apache server is faster than Jetty/Tomcat when it comes to serving static pages.
  • Apache server is robust and configurable to support many modules such as perl,PHP.

We would like Apache HTTP Server to serve HTML pages, Images to clients and forward other requests for dynamic content to underlying application server.

How that redirection happens? More specifically, we will get answers to the following questions in the post by taking jetty as our application server

  1. How will Apache know which request / type of requests should be forwarded to Jetty?
  2. How will Apache forward these requests to Jetty?
  3. How will Jetty accept and handle these requests?

To Run a service with Jetty

I have used dropwizard to developed a simple Hello World web service.

Code for this Hello Rest service can be found here.

After cloning the repository, execute mvn clean install to build target jar. Once target jar is ready, execute java -jar hello-1.0-SNAPSHOT.jar server to start service on 8080 port.

Our resource is located at /hello. Execute http://localhost:8080/hello to make sure our service is working

Configure Apache server

Get the latest binary for Apache HTTP Server from here. I have taken Apache 2.4 from here Extracted zip in C drive by making APACHE_HOME located at C:\Apache24 Executed httpd.exe in bin directory to make sure, apache HTTP server is running at http://localhost:9999/ I had to change the port because of permission. you can change the port by editing httpd.conf in C:\Apache24\conf

we will use apache Module mod_rewrite to one URL to another URL. We will also enable virtual hosts where we will write redirection rules. We can still do it without vhosts, but it will be a mess in httpd.conf

Make the following changes in httpd.conf to

  • Enable mod_rewrite, Look for this LoadModule rewrite_module modules/mod_rewrite.so and uncomment it.
  • Enable mod_proxy by uncommenting LoadModule proxy_module modules/mod_proxy.so
  • Enable mod_proxy_http by uncommenting LoadModule proxy_http_module modules/mod_proxy_http.so
  • Enable vhosts in by uncommenting Include conf/extra/httpd-vhosts.conf

comment any pre-configured virtual hosts in conf/extra/httpd-vhosts.conf Add the following virtual host snippet

<VirtualHost *:9999>
	DocumentRoot "C:/Apache24/htdocs"
    ErrorLog logs/helloworld-error.log
    CustomLog logs/helloworld-access.log combined
	LogLevel error
	<Directory "C:/Apache24/htdocs">
        Options MultiViews FollowSymLinks
        AllowOverride all
        Require all granted
    </Directory>
    RewriteEngine On
    RewriteRule ^/hello http://localhost:8080/hello [P]
</VirtualHost>

Our httpd-vhosts.conf will contain only the above VirtualHost directive.

Using above VirtualHost directive,

  • we are starting server instance at port 9999.
  • RewriteEngine used to enable runtime rewrite engine on or off.
  • RewriteRule is quite simple, It maps request http://localhost:9999/hello to http://localhost:8080/hello
  • Use of the [P] flag causes the request to be handled by mod_proxy, and handled via a proxy request.

At this point, if you restart Apache HTTP server, it shouldn’t be throwing any errors. It should work normal.

When you access http://localhost:9999/hello you should be presented with JSON message same as the message when you hit http://localhost:8080/hello

Read here for more about mod_rewrite Read here for more about regular expressions in mod_rewrite

That is it for this post. In the next post I will talk about how to configure SSL to Apache server.

Reverse every k nodes of a linked list

Problem

Write a function to reverse every k nodes of a linked list (k is the input to the function)

Example:

Given linked list is 1->2->3->4->5->6->7->8>9, Input: K = 3
Output: 3->2->1->6->5->4->9->8->7
Input: K = 5
Output: 5->4->3->2->1->9->8->7->6

Iterative Solution

Recursive Solution

Check here for complete code.

Reverse a singly linked list

Reverse a singly linked list is one of the most commonly asked data structures interview questions

Problem

Given a singly linked list, write a function to reverse it.

Example:

If the linked list is 1->2->3->4->5, then the function should change it to 5->4->3->2->1

Iterative Solution

Recursive Solution

Click here for complete code