Easy SSL with Heroku & Cloudflare

Gonçalo Pereira
Runtime Revolution
Published in
7 min readMay 4, 2017

--

At Runtime Revolution we value the importance of security. As such, in any web application where sensitive data needs to be transmitted (e.g. passwords, personal data, etc) we always aim to ensure that these applications use HTTPS. Following up on my previous blog post about SSL, this not only improves site security and privacy but also increases the search engine optimization.

This week I am going to write about a common scenario we face: the development of a Rails application to be deployed on Heroku and served from an associated domain using HTTPS.

As you might know, Heroku already provides HTTPS in their web applications hosted there through an SNA wildcard SSL certificate. As such, accessing a Heroku hosted web application directly is not a problem, however developing a web application where its entry point is set to be the default Heroku URL will almost never be the case.

Usually, the client either asks us for a specific DNS address or for it to be associated with a domain previously bought. In both these cases simply making the DNS an alias or pointing to the Heroku app URL and then accessing that DNS host through HTTPS will not work. If you try to do that any noteworthy browser will at least give you a warning which will probably scare off many of your client’s users. This happens because the certificate that is being served is that of Heroku and the domains for which it is valid do not include the client’s DNS.

How to solve this issue?

Obviously, the traditional approach still works. You buy a certificate for the client’s DNS name, add it to Heroku and voilà, problem solved. However, for some cases (e.g. an MVP) this is actually not necessary and you can save your client a few bucks while setting everything up quite fast.

A good alternative is to use Cloudflare’s free service which comes with a few extra added bonuses such as automatically managing your site’s access through their global CDN and some level of DDOS protection. However, given our goal, the most important advantage is that by setting up Cloudflare as your DNS manager you will be able to create a secure connection to your Heroku web application without buying a new SSL certificate.

To achieve this, you should follow a few steps:

a) Acquire a domain name

For this example consider: example.com

b) Register in Cloudflare and setup domain management

After signing up follow these steps:

  1. Insert the domain name you acquired in the first step of the wizard shown and click Scan DNS Records
  2. If a list of records of type CNAME, A, etc. are shown, then you are good to go, if not, don’t worry we will add one later on. Click continue
  3. Select Free Website
  4. Login into the account from which the DNS domain was bought and change your nameservers to the ones shown at this step. If for some reason you leave that page, don’t worry, it will still be shown on your overview page of Cloudflare each time you login.

c) Configure DNS records on Cloudflare

Once the status of your domain name appears in your dashboard as Active you can continue configuring the DNS. Usually it is updated in a few minutes, but it can take up to a day.

Go to your DNS tab in Cloudflare. Then do one of the steps below, depending on which applies to your case:

  1. If, as it has happened to me, in step a-2 you had no records to import then no DNS records are shown in this menu. As such you should add at least one to redirect requests from example.com to your Heroku custom domain name, which should be something like: example-prod.herokuapp.com. As such, in this case you would add the record:
    CNAME — example.comintetesting-prod.herokuapp.com
  2. If on the other hand you had a record imported of type A you should probably change it to a CNAME and point it to your Heroku URL: example-prod.herokuapp.com
  3. If you had a CNAME imported, just check that it is pointing to your Heroku URL: example-prod.herokuapp.com

Finally, a very important configuration is to set the CNAME record just added/edited to route its traffic through Cloudflare. It should look like this:

If you don’t do this step, any SSL options we will configure in the next step won’t work. Notice: other records such as MX records do not need this to work normally.

d) Setup SSL options

  1. Open the Crypto tab of Cloudflare dashboard
  2. Change the current SSL option to Full

e) Setup page rules to enforce HTTPS

Once you have HTTPS configured you can use HTTPS to all the requests made into your website. To do so:

  1. Open the Page Rules tab in Cloudflare
  2. Create a new page rule
  3. Redirect any HTTP traffic to your domain to HTTPS by typing in the URL matching box something like: *example.com/*
  4. Add the setting: “Always use HTTPS”
  5. Save the rule

f) Test your setup

  1. Access your site through HTTPS, and your page should appear as secure (locker icon on browser)
  2. Access the website through HTTP and you should be redirected to HTTPS
  3. Check your web application logs to see that the connection was made using HTTPS
  4. Finally test your site in https://www.ssllabs.com/ssltest/ and you should pass with flying colors: A grades all around.

That’s it!

Now that it is all set, an option that warrants a more in depth discussion is the Crypto configuration on Cloudflare. In the past I have misused Flexible instead of Full in SSL configuration. If you try using it, you might be misled into thinking that the connection to your web application is fully secure when in fact that is not the case.

If you try to access your website with HTTPS and your domain name it will all look perfectly fine: the SSL certificate that will be served is provided by Cloudflare (SNI type), will be valid for your domain name and it is even displayed by your browser as secure. However, the Flexible setting will leave a point of failure in your connection. When you make a request to your website, what is happening behind the scenes is that Cloudflare is actually acting as a Man in the Middle (configured by you) and routes your requests between your browser and the Heroku host. This is how Cloudflare manages to give you the appropriate certificate for your DNS.

However, when you have the Flexible setting that request is passed on to Heroku using only HTTP (without SSL) and is thus insecure. To signal to Cloudflare that your app actually has SSL configured and that it should be used instead you must therefore set it to Full. This can be easily verified if you check the logs on your Heroku app. With Flexible only the part of the connection between your browser and Cloudflare will be encrypted, whilst if you set it to Full all the request process will be encrypted, from the browser to Cloudflare to Heroku.

Final Remarks

Migrating websites from using HTTP to HTTPS is getting easier and easier, which means that excuses to avoid doing so should be hard to entertain. The discussed use case is a quick and easy way to configure your web app using HTTPS with your client’s custom domain name. There are however a couple of things that I would still like to leave for consideration.

Since we are talking about security one could argue that, in fact, by getting Cloudflare in the middle we are bringing in another point of failure to the web application security infrastructure. And some recent events seem to prove it:

Major Cloudflare bug leaked sensitive data from customers’ websites”
— TechCrunch

However, the fact is that Cloudflare is just one of many entities in which you must put your trust in order to ensure the intended security. For example, when buying an SSL certificate, you trust their issuers to not leak your private key; by using a web browser you are trusting, by default, a set of Certificate Authorities which attest the validity of SSL certificates or even Heroku in which you trust they follow the best practices in security for the hosting software that supports it. At an even more basic level you trust that your web servers support the most up to date SSL protocols/libraries and don’t fall prey to known security vulnerabilities (e.g. SSL 3.0 Protocol Vulnerability and POODLE Attack).

Furthermore, if you only had HTTP to start with, this setup would be a good help in improving site security with a few added bonuses like better SEO, saving a few dollars or even letting you off the responsibility of renewing your SSL certificate.

To wrap it up, if having an SSL certificate issued for your domain name which can be renewed frequently and automatically at no cost and without your traffic being routed through Cloudflare sounds even better, you should take a look at the Let’s Encrypt the Web. But setting it up is a completely different story or article!

Nowadays I work at Runtime Revolution. Working here has been, and continues to be, a great learning experience. I’ve matured professionally as a developer, focusing on building and maintaining large scale Ruby on Rails applications.

--

--