Monthly Archives: May 2013

How to get the latest stable OpenSSL, Apache and Nginx

Unfortunately many distributions are slow to pick up the most recent distributions of these core software packages. I see many arguments why this not a problem, the most common being the enterprise distributions backport the most important security fixes so it’s not necessary to get more recent versions.

The problem with this argument is that sometimes security fixes are not patches but are in-fact new features. TLS 1.2 is a great example of this, it has numerous security fixes in it that don’t exist in earlier incarnations of the protocol and the older versions of OpenSSL simply do not support it.

Another argument I hear is “make install” is so easy it doesn’t really matter that distributions do not carry the latest packages because you can just build it yourself. This argument has several issues, one of which is production systems should hardened with only the minimal binaries on it to be supportable, bringing in a development environment on is about as opposite of that as you can be.

So what is a server administrator to do? Thankfully there are several additional repositories available for Enterprise Linux Distributions that offer stable and recent builds of the most commonly used packages, two such repositories are:

Between these two (depending on your OS version) you can probably get the most recent OpenSSL, Nginx, and Apache distributions and all the goodness they carry.

In my case I use Centos 6.3, if you do also you can follow the steps here to add these repositories to you own systems.

Once you have added the repositories you can simply use the IUS replace plug-in to replace your current distribution of OpenSSL with the latest, for example:

yum replace openssl --replace-with=openssl10 --enablerepo=ius-testing

That’s it, now you can enable TLS 1.2 and any other modern TLS features carried by this build of OpenSSL. It is worth noting that at this time this build does not include support for ECC and ECDH which are required for forward secrecy with modern browsers, to get a version that supports these algorithms you will have to build your own.

Example Nginx SSL / TLS configuration

Configuring your server for SSL can be a little overwhelming. To help with this I am writing three posts (one for Nginx, Apache and IIS) with example configurations that (to the extent possible) result in the same configuration regardless of what server you are using.

Let’s start with Nginx, for this site :

  1. Running nginx/1.4.1 and openssl 1.0.1e
  2. All static content is handled by Nginx.
  3. All dynamic content is handled by Node.js and Express.
  4. We use the X-Frame-Options header to help protect from Click-Jacking.
  5. We use the X-Content-Security-Policy
    header to help protect from Cross-Site-Scripting.
  6. All requests for content received over http are redirected to https.
  7. Once the user visits the https version of the site the Strict-Transport-Security header instructs the browser to always start with the https site.
  8. We have chosen SSL cipher suites to offer a blend of performance and security.
  9. We have disabled SSL v2 and v3 and enabled all versions of TLS.
  10. We have enabled OCSP stapling.
  11. We have enabled SSL session caching.
  12. We have put all certificates and keys into their own folder (certs.d/).
  13. Set the owner of the of the certs.d folder to the process that the server runs as.
  14. We have restricted the certs.d folder and key files so only the owner can read and write (chmod 600).

Here is the configuration file:

server {
listen  80;

# tell users to go to SSL version this time
if ($ssl_protocol = "") {
rewrite     ^   https://$server_name$request_uri? permanent;


server {
listen  443 ssl;

# tell users to go to SSL version next time
add_header Strict-Transport-Security "max-age=15768000; includeSubdomains;";

# tell the browser dont allow hosting in a frame
add_header X-Frame-Options DENY;

# tell the browser we can only talk to self and google analytics.
add_header X-Content-Security-Policy "default-src 'self'; \
script-src 'self'; \
img-src 'self'";

ssl_protocols               TLSv1 TLSv1.1 TLSv1.2;

# ciphers chosen and ordered for mix of performance, interoperability and security
#ssl_ciphers                 AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH;

# ciphers chosen for security (drop RC4:HIGH if you are not worried about BEAST).
#ssl_ciphers                  RC4:HIGH:HIGH:!aNULL:!MD5;

# ciphers chosen for FIPS compliance.
#ssl_ciphers !aNULL:!eNULL:[email protected];

# ciphers chosen for forward secrecy an compatibility

ssl_prefer_server_ciphers   on;
ssl_certificate_key         certs.d/example.key;
ssl_certificate             certs.d/example.cer;

ssl_session_cache    shared:SSL:10m;
ssl_session_timeout  10m;

# enable ocsp stapling
ssl_stapling on;
ssl_trusted_certificate certs.d/example.cer;

# let nginx handle the static resources
location ~ ^/(htm/|html/|images/|img/|javascript/|js/|css/|stylesheets/|flash/|media/|static/|robots.txt|humans.txt|favicon.ico) {

root /usr/share/nginx/example/public;
access_log off;
expires @30m;

# redirect to node for the dynamic stuff
location / {
proxy_pass http://localhost:8003;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;

proxy_hide_header X-Powered-By;

#proxy_redirect off;
#proxy_set_header   X-Real-IP            $remote_addr;
#proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
#proxy_set_header   X-Forwarded-Proto $scheme;
#proxy_set_header   X-NginX-Proxy    true;

error_page  404              /404.html;

# redirect server error pages to the static page /50x.html
error_page   500 502 503 504  /50x.html;

location = /50x.html {
root   /usr/share/nginx/html;