SNI - Server Name Identification (virtual hosting for SSL nodes)

uWSGI 1.9 (codenamed “ssl as p0rn”) added support for SNI (Server Name Identification) throughout the wholeSSL subsystem. The HTTPS router, the SPDY router and the SSL router can all use it transparently.

SNI is an extension to the SSL standard which allows a client to specify a “name” for the resourceit wants. That name is generally the requested hostname, so you can implement virtual hosting-like behavior like you do using the HTTP Host: header without requiring extra IP addresses etc.

In uWSGI an SNI object is composed of a name and a value. The name is the servername/hostname while the value is the “SSL context” (you can think of it as the sum of certificates, key and ciphers for a particular domain).

Adding SNI objects

To add an SNI object just use the —sni option:

  1. --sni <name> crt,key[,ciphers,client_ca]

For example:

  1. --sni "unbit.com unbit.crt,unbit.key"

or for client-based SSL authentication and OpenSSL HIGH cipher levels

  1. --sni "secure.unbit.com unbit.crt,unbit.key,HIGH,unbit.ca"

Adding complex SNI objects

Sometimes you need more complex keys for your SNI objects (like when using wildcard certificates)

If you have built uWSGI with PCRE/regexp support (as you should) you can use the —sni-regexp option.

  1. --sni-regexp "*.unbit.com unbit.crt,unbit.key,HIGH,unbit.ca"

Massive SNI hosting

One of uWSGI’s main purposes is massive hosting, so SSL without support for that would be pretty annoying.

If you have dozens (or hundreds, for that matter) of certificates mapped to the same IP address you can simply put them in a directory (following a simple convention we’ll elaborate in a bit) and let uWSGI scan it whenever it needs to find a context for a domain.

To add a directory just use

  1. --sni-dir <path>

like

  1. --sni-dir /etc/customers/certificates

Now, if you have unbit.com and example.com certificates (.crt) and keys (.key) just drop them in there following these naming rules:

  • /etc/customers/certificates/unbit.com.crt
  • /etc/customers/certificates/unbit.com.key
  • /etc/customers/certificates/unbit.com.ca
  • /etc/customers/certificates/example.com.crt
  • /etc/customers/certificates/example.com.key

As you can see, example.com has no .ca file, so client authentication will be disabled for it.

If you want to force a default cipher set to the SNI contexts, use

  1. --sni-dir-ciphers HIGH

(or whatever other value you need)

Note: Unloading SNI objects is not supported. Once they are loaded into memory they will be held onto until reload.

Subscription system and SNI

uWSGI 2.0 added support for SNI in the subscription system.

The https/spdy router and the sslrouter can dynamically load certificates and keys from the paths specified in a subscription packet:

  1. uwsgi --subscribe2 key=mydomain.it,socket=0,sni_key=/foo/bar.key,sni_crt=/foo/bar.crt

the router will create a new SSL context based on the specified files (be sure the router can reach them) and will destroy it when the last nodedisconnect.

This is useful for massive hosting where customers have their certificates in the home and you want them the change/update those files without bothering you.

Note

We understand that directly encapsulating keys and cert in the subscription packets will be much more useful, but network transfer of keys is somethingreally foolish from a security point of view. We are investigating if combining it with the secured subscription system (where each packet is encrypted) could be a solution.