Howto setup Nginx with Server Name Indication TLS Extensions on CentOS 5
Howto get multiple https web sites with different server certificates on a single IP address using Nginx and OpenSSL v1.0.0
OpenSSL has support from server name extensions (SNI) from version 0.9.8f and later. This has been enabled by default from v0.9.8f. CentOS (el5) ships with OpenSSL v0.9.8.e, and thus it is not a simple case of recompiling the package with the TLS extensions enabled.
The strategy taken to get an Nginx running with SNI is to use a modern version of OpenSSL, and produce an OpenSSL v0.9.8.e compatibility package with just the openssl version 6 libraries. This is the same concept as the CentOS/EL 'openssl097a' binary compatibility package which ships with version 4 libraries.
Using this strategy, the following steps have been identified:
- produce an OpenSSL v0.9.8e version 6 package
- produce an OpenSSL v1.0.0 version 10 package (with TLS extensions enabled - the default)
- produce an Nginx package compiled against the new OpenSSL library
- acquire/produce server certificates
- install and configure Nginx
OpenSSL v0.9.8e compatibility package
Take the standard CentOS/EL openssl-0.9.8e-12.el5_4.6.src.rpm source RPM. Rename the package to 'openssl098e' and remove everything from the package except the linked libraries.
The following patch is applied to the openssl.spec file to produce a new openssl098e.spec file.
$ rpmbuild -ba openssl098e.spec
This produces a src.rpm and x86_64.rpm.
OpenSSL v1.0.0 package
Take the standard Fedora 12 OpenSSL package, and rebuild. This puts the libraries in '/usr/{lib,lib64}' instead of '/{lib,lib64}', and the certificates are not included (the 'ca-certificates' package is required).
Note: No changes to the package are required. However given that Fedora is using a later version of rpm, it is necessary to extract the files on a machine with a later version of rpm2cpio.
Nginx package
As of writing Nginx v7.65 is the latest stable release. Get the RPM from the Fedora repository and rebuild it against the new OpenSSL v1.0.0 library.
Note: No changes to the package are required. However given that Fedora is using a later version of rpm, it is necessary to extract the files on a machine with a later version of rpm2cpio.
Install OpenSSL libraries and Nginx
Install the OpenSSL v1.0.0 package, and the OpenSSL098e v0.9.8e library compatibility package, and Nginx. Upgrade all the OpenSSL components at once so that dependencies are satisfied.
# rpm -Uvh openssl-1.0.0-2.RHL5.x86_64.rpm \ openssl098e-0.9.8e-12.RHL5.6.x86_64.rpm \ ca-certificates-2009-2.RHL5.noarch.rpm \ nginx-0.7.65-1.RHL5.x86_64.rpm
Note: x86_64 packages are presented here. On a fresh minimal CentOS v5.5 x86_64 install the i686 version of openssl was installed. This has to be removed otherwise dependencies are not met.
# rpm -e openssl-0.9.8e-12.el5_4.6.i686 trousers-0.3.1-4.el5.i386 ecryptfs-utils-75-5.el5.i386
Verify the OpenSSL package
Run the openssl version command to verify that the new package is being used.$ openssl version -a
Run the Nginx with the version option to verify that TLS SNI is enabled:
$ /usr/sbin/nginx -V
Certificates
Given the capability to have multiple secure web sites with independent server certificates, now we need to either generate certificates ourself or generate a certificate signing request (CSR) for a CA to sign. I chose to use StartSSL for free 1 year certificates:
I used the following script to generate a 4k RSA key and a certificate signing request (CSR):
#!/bin/bash umask 177 function makerequest { NAME=$1 [ -f ${NAME}.key ] || openssl genrsa 4096 > ${NAME}.key openssl req -new -key ${NAME}.key -extensions v3_ca \ -subj "/C=NZ/L=Christchurch/O=Lucid Solutions Ltd/CN=${NAME}.lucidsolutions.co.nz" \ -out ${NAME}.csr } makerequest www makerequest plone
Note: Given that these are free certificates, the StartSSL certificate ignores all the 'subject' information (as it isn't verified).
To view the certificate from the CA use the following OpenSSL command :
$ openssl x509 -noout -fingerprint -text -in <filename>
Nginx Configuration
Adding https support to an Nginx server is well documented on the web. Add server sections as required. This is a sample for a trivial static content web site:
ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ssl_protocols SSLv3 TLSv1; server { listen 443; server_name www.lucidsolutions.co.nz; keepalive_timeout 70; ssl on; ssl_certificate certs/www.startssl.crt; ssl_certificate_key certs/www.key; access_log /var/log/nginx/www.access.log main; location / { root /var/www/html/www; index index.html; } }
The certificate chain from the CA must be added to the file identified in the 'ssl_certificate' directive. The intermediate & CA certificates must be after the servers public key certificate.
IMPORTANT: Don't put anything but the CA and intermediate certificates after the servers public key certificate into the 'ssl_certificate' file. I appended the whole StartSSL CA bundle and it caused Internet Explorer to fail to negotiate a TLS/SSL connection on Windows Vista and Server 2008 (but all other browsers tested were ok, and IE on Windows 2008 R2 was ok). Nginx reported 'peer closed connection in SSL handshake while SSL handshaking' in the error log, and '"400" 0 "-" "-" "-"' in the access log. Use the following openssl command to verify the certificate chain:
$ openssl s_client -connect <host>:443 -tlsextdebug
Links
- Server Name Indication
- OpenSSL
- RFC-4366 Transport Layer Security (TLS) Extensions
- RFC-3546 Transport Layer Security (TLS) Extensions (Obsolete)
Free/Cheap CA's
Files/RPM's
The RPM's used in this howto are available via http and https.
ca-certificates-2009-2.RHL5.noarch.rpm ca-certificates-2009-2.RHL5.src.rpm nginx-0.7.65-1.RHL5.src.rpm nginx-0.7.65-1.RHL5.x86_64.rpm openssl-1.0.0-2.RHL5.src.rpm openssl-1.0.0-2.RHL5.x86_64.rpm openssl-devel-1.0.0-2.RHL5.x86_64.rpm openssl-perl-1.0.0-2.RHL5.x86_64.rpm openssl-static-1.0.0-2.RHL5.x86_64.rpm openssl098e-0.9.8e-12.RHL5.6.src.rpm openssl098e-0.9.8e-12.RHL5.6.x86_64.rpm
Note: The RPM files are not signed, and they are not in a yum repository.
Appendices
Nginx version information
When Nginx has been compiled with an OpenSSL library that supports TLS server name indication (SNI), the version information includes the string 'TLS SNI support enabled'.$ /usr/sbin/nginx -V
nginx version: nginx/0.7.65
built by gcc 4.1.2 20080704 (Red Hat 4.1.2-46)
TLS SNI support enabled
configure arguments: --user=nginx --group=nginx --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx
--conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log
--http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body
--http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi
--pid-path=/var/run/nginx.pid --lock-path=/var/lock/subsys/nginx --with-http_ssl_module
--with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module
--with-http_flv_module --with-http_gzip_static_module --with-http_random_index_module
--with-http_secure_link_module --with-http_stub_status_module --with-http_perl_module
--with-mail --with-mail_ssl_module --with-ipv6
--with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector
--param=ssp-buffer-size=4 -m64 -mtune=generic'
OpenSSL version information
$ openssl version -a
OpenSSL 1.0.0-fips 29 Mar 2010
built on: Sun Apr 18 13:31:34 NZST 2010
platform: linux-x86_64
options: bn(64,64) md2(int) rc4(8x,int) des(idx,cisc,16,int) blowfish(idx)
compiler: gcc -fPIC -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN
-DHAVE_DLFCN_H -DKRB5_MIT -m64 -DL_ENDIAN -DTERMIO -Wall -O2 -g -pipe
-Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4
-m64 -mtune=generic -Wa,--noexecstack -DMD32_REG_T=int -DOPENSSL_IA32_SSE2
-DOPENSSL_BN_ASM_MONT -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DWHIRLPOOL_ASM
OPENSSLDIR: "/etc/pki/tls"
engines: aesni dynamic
OpenSSL library versions
Taken from the top of the OpenSSL spec file:
0.9.5a soversion = 0 0.9.6 soversion = 1 0.9.6a soversion = 2 0.9.6c soversion = 3 0.9.7a soversion = 4 0.9.7ef soversion = 5 0.9.8ab soversion = 6 0.9.8g soversion = 7 0.9.8jk + EAP-FAST soversion = 8 1.0.0 soversion = 10
Nginx libraries
Nginx compiled against the standard CentOS/EL OpenSSL libraries uses version '6' of the libraries. This is useful when checking a legacy Nginx v6.xx that doesn't have the '-V' option.
# ldd `which nginx` libcrypt.so.1 => /lib64/libcrypt.so.1 (0x0000003e9c400000) libpcre.so.0 => /lib64/libpcre.so.0 (0x0000003e9d400000) libssl.so.6 => /lib64/libssl.so.6 (0x00002ac4ed150000) libcrypto.so.6 => /lib64/libcrypto.so.6 (0x00002ac4ed39d000) libz.so.1 => /usr/lib64/libz.so.1 (0x0000003e9c800000) libperl.so => /usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi/CORE/libperl.so (0x0000003e9f800000) libresolv.so.2 => /lib64/libresolv.so.2 (0x0000003e9d800000) libnsl.so.1 => /lib64/libnsl.so.1 (0x0000003e9cc00000) libdl.so.2 => /lib64/libdl.so.2 (0x0000003e9ac00000) libm.so.6 => /lib64/libm.so.6 (0x0000003e9c000000) libutil.so.1 => /lib64/libutil.so.1 (0x0000003e9bc00000) libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003e9b800000) libc.so.6 => /lib64/libc.so.6 (0x0000003e9a800000) libgssapi_krb5.so.2 => /usr/lib64/libgssapi_krb5.so.2 (0x0000003e9e400000) libkrb5.so.3 => /usr/lib64/libkrb5.so.3 (0x0000003e9ec00000) libcom_err.so.2 => /lib64/libcom_err.so.2 (0x0000003e9d000000) libk5crypto.so.3 => /usr/lib64/libk5crypto.so.3 (0x0000003e9e000000) /lib64/ld-linux-x86-64.so.2 (0x0000003e9a400000) libkrb5support.so.0 => /usr/lib64/libkrb5support.so.0 (0x0000003e9e800000) libkeyutils.so.1 => /lib64/libkeyutils.so.1 (0x0000003e9f000000) libselinux.so.1 => /lib64/libselinux.so.1 (0x0000003e9b000000) libsepol.so.1 => /lib64/libsepol.so.1 (0x0000003e9b400000)
StartSSL public key certificate
openssl x509 -noout -fingerprint -text -in plone.startssl.crt
SHA1 Fingerprint=F0:ED:93:17:04:38:10:F6:82:75:BA:93:72:B4:83:D2:83:55:C2:EF Certificate: Data: Version: 3 (0x2) Serial Number: 94429 (0x170dd) Signature Algorithm: sha1WithRSAEncryption Issuer: C=IL, O=StartCom Ltd., OU=Secure Digital Certificate Signing, CN=StartCom Class 1 Primary Intermediate Server CA Validity Not Before: Apr 6 02:37:26 2010 GMT Not After : Apr 7 09:47:03 2011 GMT Subject: description=175568-HtQhRoB3uBjsOPc3, C=NZ, O=Persona Not Validated, OU=StartCom Free Certificate Member, CN=plone.lucidsolutions.co.nz/emailAddress=postmaster@lucidsolutions.co.nz Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (4096 bit) Modulus: 00:c8:0f:c7:d9:9d:2b:e7:13:df:3f:52:fc:e8:64: 2c:b8:57:c9:49:f8:12:62:48:33:a5:62:8f:dd:6c: 9b:6d:16:1f:ec:75:ac:0d:14:eb:eb:cf:06:55:3d: 62:75:73:78:7f:b4:00:6e:c4:88:93:7b:70:03:3e: bc:d7:2d:1d:05:e9:a0:88:94:fc:ba:57:80:f5:c8: 6a:d7:32:9b:5d:3e:8e:e2:14:90:42:fe:3b:8f:e4: c4:18:eb:31:21:42:24:b6:ac:00:70:f9:49:d6:85: 67:fc:56:ac:8a:7a:0d:23:17:7f:fa:ac:a3:3c:5b: eb:c6:a2:f1:88:6e:0c:08:7b:26:f7:35:45:fe:13: 5d:45:ad:ff:d9:84:c1:a3:da:28:e2:45:9b:db:b4: c9:60:04:e4:9d:65:17:62:05:38:3e:69:75:e7:83: 17:b2:cd:ae:77:39:e4:d0:e5:c1:9e:79:aa:60:2f: 07:94:e8:f8:87:b5:c7:14:a2:2c:1a:58:05:e3:18: 8a:21:c9:c7:55:bf:30:49:f2:dc:55:a2:92:d4:8a: 53:52:f6:2b:b1:41:a8:86:01:fe:e8:54:55:12:ed: 2c:f8:ed:1b:cd:b1:88:88:03:7d:1a:17:95:ff:f8: 3d:97:be:f6:72:57:b8:fe:75:87:55:04:2b:b3:50: 0e:36:4a:ce:00:71:d3:39:97:b7:7c:20:83:f0:e4: 9b:1d:9b:16:a1:1e:7c:a3:81:10:f3:d0:0a:32:cd: 16:ec:ec:6c:ba:fc:ca:7f:f5:40:9a:23:5c:3f:0c: d5:67:59:6f:d2:a2:48:77:3e:05:21:1a:77:3d:d1: eb:4e:b1:55:cd:87:65:c4:1c:3e:fb:85:7a:2e:38: 41:83:a3:f5:b5:0b:95:1d:e1:77:4d:75:ee:c9:7d: 79:d6:98:82:9f:75:92:0c:83:ee:b9:9e:9e:56:e6: 66:2c:ac:2c:7b:2c:92:21:d7:84:2d:60:22:bd:42: 59:2f:a1:05:e1:82:d3:4c:15:ec:0d:0c:bc:14:88: 46:7d:9b:ee:13:9b:ad:23:cb:b6:27:fa:2d:f1:08: 1a:fb:d4:17:7f:5c:cc:08:a9:36:2a:6c:cd:a5:67: 96:92:b5:3f:fa:6e:32:0b:79:8e:7c:be:28:96:f5: 46:f5:6b:cc:4a:85:d2:63:16:b9:04:d5:76:52:c5: 01:aa:bd:8d:ba:76:15:43:de:a2:8f:63:db:dd:77: a9:e9:79:2a:69:d6:86:4b:33:9c:7f:96:2e:25:de: e5:86:d2:13:4b:41:7a:d2:9e:99:a4:c4:d9:35:96: 2b:b9:52:b5:c7:0a:8f:86:82:a6:3f:e6:f7:df:33: 27:12:4b Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE X509v3 Key Usage: Digital Signature, Key Encipherment, Key Agreement X509v3 Extended Key Usage: TLS Web Server Authentication X509v3 Subject Key Identifier: 84:5B:F9:86:84:1B:A8:8A:2A:2C:88:B6:B9:E8:4D:E3:AF:20:49:CE X509v3 Authority Key Identifier: keyid:EB:42:34:D0:98:B0:AB:9F:F4:1B:6B:08:F7:CC:64:2E:EF:0E:2C:45 X509v3 Subject Alternative Name: DNS:plone.lucidsolutions.co.nz, DNS:lucidsolutions.co.nz X509v3 Certificate Policies: Policy: 1.3.6.1.4.1.23223.1.2.1 CPS: http://www.startssl.com/policy.pdf CPS: http://www.startssl.com/intermediate.pdf User Notice: Organization: StartCom Ltd. Number: 1 Explicit Text: Limited Liability, see section *Legal Limitations* of the StartCom Certification Authority Policy available at http://www.startssl.com/policy.pdf X509v3 CRL Distribution Points: Full Name: URI:http://www.startssl.com/crt1-crl.crl Full Name: URI:http://crl.startssl.com/crt1-crl.crl Authority Information Access: OCSP - URI:http://ocsp.startssl.com/sub/class1/server/ca CA Issuers - URI:http://www.startssl.com/certs/sub.class1.server.ca.crt X509v3 Issuer Alternative Name: URI:http://www.startssl.com/ Signature Algorithm: sha1WithRSAEncryption 9d:4b:16:7a:39:3d:b3:58:10:08:a6:62:33:31:cc:04:5c:43: c6:49:d7:86:59:6f:52:ba:ef:78:c2:82:b4:05:c7:54:5c:73: 62:5f:c4:a1:e3:5e:0f:b8:ab:55:76:36:5c:68:e6:f3:61:42: 3d:1e:ee:30:e3:fc:51:f9:f4:78:fd:d1:76:b3:63:9c:0a:6c: 89:f2:ae:a1:0c:06:7c:2d:5f:01:49:ee:5c:9e:f4:c9:f8:9d: 59:5e:fe:e4:97:a4:c8:c4:1b:22:99:91:43:ae:b5:8f:66:95: e5:37:bf:1c:ec:d2:fe:94:c5:08:3a:d7:74:ee:07:da:3f:37: 7c:bf:e4:83:93:a1:17:89:97:8f:43:92:e3:f1:3f:41:d7:59: 0e:6d:16:b5:35:78:6b:cb:af:2b:34:72:0a:36:3c:68:5f:01: 01:51:e1:f9:3d:82:91:05:a3:bd:d5:b9:c6:01:1f:e2:9b:2e: 06:f3:6b:89:d6:dc:90:bd:54:4f:46:99:1e:53:b2:32:ca:1e: 08:d5:31:75:1d:1b:cb:fd:15:ed:d2:46:72:ae:67:ee:0b:af: 89:9b:ee:c5:91:77:7c:52:b0:a4:00:e1:b5:a8:64:c5:e0:a5: ae:3a:e0:bf:dc:28:df:2a:0a:54:31:98:74:51:8a:b5:80:a5: 28:35:fe:f5