Using Apache as a reverse proxy to Jetty with SSL

Hey there, Allan here.

Since my last post was about ideas and discussions I decided to make this one more technical. So here is the cenario

I’ve got a maven project that runs with org.mortbay.jetty.maven-jetty-plugin. That way I’m able to run “mvn jetty:run” and got the system up and running in no time. Since it’s a “default” jetty installation, when I’m done with a new feature, I just pack the code and install in the jetty of the homologation enviroment.

The Problem

In unix systems you can only allocate ports bellow 1024 being a root. That means that, if I want to run as a normal user, when I set the Jetty plugin, I must choose some port over 1024 for both http and https (ports 80 and 443). The problem is that, if I use other ports than these, I must, manually, put the ports in the URL when navigating through the system. And that is WRONG.

So, as many of you may have guessed, when I’m working in a project with this setup, I put my jetty on port 8080 and configure an Apache Server to be a reverse proxy to my jetty. (since apache runs as a service, and, therefore, can run on 80)

<VirtualHost *:80>
ServerName myproject.com

LimitRequestFieldSize 65536

ProxyRequests Off
ProxyVia Block
ProxyPreserveHost Off
ProxyTimeout 10

ProxyPassReverse / http://127.0.0.1:8080/

RewriteEngine On

RewriteCond %{REQUEST_URI} ^(.(?!\.css|js|gif|png|jpg|ico))*$
RewriteRule /(.*) http://localhost:8080/$1 [P,L]
</VirtualHost>

And I was happy forever after until someone told me “hey, this one in https” and handled me a jks file to be the jetty certificate. So, I configured the jetty to the oncoming safe requests, on port 4430 and went to configure my apache.

Since it was a dev machine, and Apache don’t like jks, I created my own certificate for it, with openssl:

Creating certificate

openssl genrsa -des3 -out self-ssl.key 2048

This command will create a self-ssl.key file. As you may have guessed, this is my key.

Then I created my Certified Signing Request (CSR)

openssl req -new -key self-ssl.key -out self-ssl.csr

No news here, as it will be in self-ssl.csr.

Then, finally, my certificate

openssl x509 -req -days 365 -in self-ssl.csr -signkey self-ssl.key -out self-ssl.crt

(IMPORTANT: it will ask for a passphrase. Create one and remember to save it)

Using the certificate

With all these files in hand, I went to configure my virtual Host again:

<Virtualhost *:443>

ServerName myproject.com.br

SSLEngine on
SSLProxyEngine On
SSLProxyVerify none
SSLCertificateFile /path/to/my/crt/file/self-ssl.crt
SSLCertificateKeyFile /path/to/my/key/file/self-ssl.key
ProxyRequests Off
ProxyVia Block
ProxyTimeout 10
ProxyPass / http://127.0.0.1:4430/
ProxyPassReverse / http://127.0.0.1:4430/
ProxyPreserveHost on

RewriteEngine On

RewriteRule /(.*) http://127.0.0.1:4430/$1 [P,L]

</Virtualhost>

Then I restarted the apache, everything worked and I went for a beer…… há! Just kidding, the proxy stopped working.

Why?

Of course, as you see, I had two different certificates and they didn’t want to be friends. The logs accused problems with not being able to get a valid HandShake.

The quick and dirty solution

Point the proxy to the unsafe port!

<Virtualhost *:443>

ServerName myproject.com.br

SSLEngine on
SSLProxyEngine On
SSLProxyVerify none
SSLCertificateFile /path/to/my/crt/file/self-ssl.crt
SSLCertificateKeyFile /path/to/my/key/file/self-ssl.key
ProxyRequests Off
ProxyVia Block
ProxyTimeout 10
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
ProxyPreserveHost on

RewriteEngine On

RewriteRule /(.*) http://127.0.0.1:8080/$1 [P,L]

</Virtualhost>

This way, your apache will validate it’s own certificate and proxy the requests to the jetty “http” port. Since it’s a dev machine, it’s not a security issue, and you don’t need to create “copies” from your real certificate. You will navigate trough a safe connection and can test all your system with no worries.

5 thoughts on “Using Apache as a reverse proxy to Jetty with SSL

  1. Hey Allan, I’m actually working on this exact problem currently. While your solution works for the rendering of the index.html page, if one makes GET/POST requests to the backend at http://localhost:port, SSL complains of an insecure request. Did you find anyway around this? Thanks.

    • You mean, a javascript ajax call? Or a “between services” layer?

      In the first case, you can “add” the certificate to your trusted list opening the GET in a new tab and accept the certificate.

      The second case is a bit more complicated, which involves making your application a little more smart and accepting self signed certificates (obviously, only in development enviroments). Therefore, this aproach depends on your technology.

      This link explains how to do in java.

Leave a message

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s