Posted in: https, ngnix

Multiple Sites behind single IP

I run several websites from my home server,  some should be secured with https as they require people to login – eg webmail, wordpress etc.  I don’t have enough IP addresses to give each webserver it’s own public IP, so I need a way to allow many virtual https sites against one IP.

Following some research, Server Name Indication is the best way to solve this.  Thjs means that https is terminated on my reverse proxy, and http only is forwarded internally on my DMZ.  The following drawing shows the setup;

I am running nginx on FreeBSD 9, and nginx SNI natviley,  all that is really required is multiple server stanzas, each with their own SSL certificates.

How to configure it.

I am assuming that you already have your server setup, and have nginx installed and running.

Firstly each https url target needs a SSL certificate,  I won’t go through this here, but I’ll be using self signed certificates.  You can see how to create self signed certs on this page.

Once you have the SSL certificates in place, ensure that the directory they are in, and the files them selves have the correct permissions (700/600), the nginx.conf config file needs the server stanzas adding.

In this example I have two ssl websites to secure,  bowie.rjctest.co.uk, and moon.rjctest.co.uk  the proxy server resolves these names to the internal IP addresses.

The following table shoes the DNS resolution of these host names.

HostnameInternal IPExternal IP
bowie.rjctest.co.uk10.34.56.4454.67.89.12
moon.rjctest.co.uk10.34.56.3354.67.89.12

The configuration file for nginx should contain the following server stanzas for the ssl sites;

server {
 listen 443;
 server_name bowie.rjctest.co.uk;
 ssl on;
 ssl_certificate ssl/bowie.rjctest.co.uk.crt;
 ssl_certificate_key ssl/bowie.rjctest.co.uk.key;
 ssl_session_timeout 5m;
 access_log logs/ssl-access-bowie.log;
 error_log logs/ssl-error-bowie.log;
 ssl_protocols SSLv2 SSLv3 TLSv1;
 ssl_ciphers RC4:HIGH:!aNULL:!MD5;
 ssl_prefer_server_ciphers on;
 keepalive_timeout 60;
 ssl_session_cache shared:SSL:10m;
 location / {
  proxy_pass http://bowie.rjctest.co.uk:80;
  proxy_set_header Host $host;
  proxy_set_header X-Forwarded-Proto https;
  proxy_set_header X-Forwarded-For $remote_addr;
  }
 }
 server {
 listen 443;
 server_name moon.rjctest.co.uk;
 ssl on;
 ssl_certificate ssl/moon.rjctest.co.uk.crt;
 ssl_certificate_key ssl/moon.rjctest.co.uk.key;
 ssl_session_timeout 5m;
 access_log logs/ssl-access-moon.log;
 error_log logs/ssl-error-moon.log;
 ssl_protocols SSLv2 SSLv3 TLSv1;
 ssl_ciphers RC4:HIGH:!aNULL:!MD5;
 ssl_prefer_server_ciphers on;
 keepalive_timeout 60;
 ssl_session_cache shared:SSL:10m;
 location / {
  proxy_pass http://moon.rjctest.co.uk:80;
  proxy_set_header Host $host;
  proxy_set_header X-Forwarded-Proto https;
  proxy_set_header X-Forwarded-For $remote_addr;
  }
}

I have added configuration lines to use different log files for each ssl site, and also added the following config so that the originating client ip is passed to the http server, and that the webserver is aware that this a ssl connection that has been proxied.  For more detail see the following page:

proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $remote_addr;

References

I’ve used the following pages for reference in creating my setup.

http://nginx.org/en/docs/http/configuring_https_servers.html

http://blog.supportpro.com/2013/07/multiple-ssl-certificates-on-a-single-ip-using-nginx/

http://en.wikipedia.org/wiki/Server_Name_Indication#Browsers_with_support_for_TLS_server_name_indication.5B6.5D