Google starts to love https from months back and recommends all websites to be encrypted with SSL over HTTP. Rumor said google gives higher rank to those websites have https than websites without ssl. If you have budget, go ahead and buy signed certificates comodo, geotrust, thawte, godaddy, symantec, etc… If you just want to have SSL for testing servers or non critical websites, self-signed SSL certificates are a great choice since you don’t need to spend a dime. The only problem with self-signed ssl certificates is web browsers won’t validate self-signed certificates unless you import them.
What are the differences between signed and self-signed SSL certificates?
CA (Certificate Authorities) signed certs:
- You have to pay a fee to get CA signed certs
- CA guaranteed you/your website is legit
- Web browsers knows/accepts CA certs
- No security warning from web browsers
Self-signed certs:
- No cost certs
- Web browsers won’t recognize self-signed certs unless you import them
- Anyone can issue self-signed certs by themselves
- Web browsers will warns clients SSL is not trusted
Install Nginx 1.6.x on CentOS 6
Enough talking, first let’s install nginx by adding nginx’s official repository
# nano /etc/yum.repos.d/nginx.repo
with the content
[nginx] name=nginx repo baseurl=http://nginx.org/packages/centos/6/$basearch/ gpgcheck=0 enabled=1
Install nginx web server / proxy server
# yum install nginx
To start nginx
# service nginx start
To start nginx automatically at boot/reboot
# chkconfig nginx on
Allow HTTP and HTTPS on iptables
To make sure you allow http and https traffic on your server, allow port 80 and 443 with iptables rules
# iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT # iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT # iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # iptables-save
Create SSL directory in the Nginx directory
We are going to store our private key and self-signed ssl certificate in /etc/nginx/ssl. You can change this location to wherever you want, but I like to keep them inside nginx directory since we only use the key and certificate for nginx. So let’s create the new ssl directory inside nginx
# mkdir /etc/nginx/ssl
Generate private key and self-signed ssl certificate
# openssl req -x509 -nodes -sha256 -days 356 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt
- openssl: it’s the command to generate, check, debug, convert, and mange openssl certificates, keys and other files
- reg: openssl reg is one of openssl’s tool/utility to create a certificate request (CSR)
- -x509: is a certificate display and signing tool, rather creating certificate signing request (CSR), we use -x509 option to tell openssl reg to create a self-signed certificate.
- -nodes: this option tells openssl not to encrypt private key so nginx can read the file.
- -sha256: to create sha256 fingerprint/signatures instead of sha1 (openssl uses sha1 by default). SHA-256 has been improved to enhance the certificate’s security (stronger and longer hash)
- -days: to set the number of days that the ssl certificate will be valid for. Default value is 30 days, in our sample I used 365 days which is a year. You can set it much longer if you want to.
- -newkey rsa:2048: to create a new self-signed certificate with a new 2048 bit rsa private key at the same time.
- -keyout: this option tells openssl where to save the generated private key.
- -out: tells openssl where to save the self-signed certificate.
openssl will ask you to enter for Country, State, Location, Organization name & unit, hostname, and email address. You don’t have to type in anything and leave those fields empty by hitting enter since the certificate is self-signed.
Generating a 2048 bit RSA private key ..........................................................................................................................+++ .+++ writing new private key to 'nginx.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:us State or Province Name (full name) []:california Locality Name (eg, city) [Default City]:westminster Organization Name (eg, company) [Default Company Ltd]:namhuy.net Organizational Unit Name (eg, section) []: Common Name (eg, your name or your server's hostname) []:namhuy.net Email Address []:
Generate DHE parameter
Even though we are using self-signed ssl certificate, it does not mean we can’t do anything to improve security. I stumble upon an article talks about Strong SSL Security on nginx, the address to that article is at the end of this article in References section. In Strong SSL Security on nginx, raymii.org wrote about various SSL attacks and ways to deal with them. In that article he mentioned about Ephemeral Diffie-Hellman (DHE) which I’m interested in. Diffie-Hellman (DH) has been around for a while but not many people use it. Diffie-Hellman is a key agreement protocol means SSL client and SSL server use the same protocol with a pre-master key using the Diffie-Hellman algorithm.The server will send the client a prime number and a generator. The keys are in clear text and it’s not a secret key, but they must be signed.
So it’s time for us to generate some DHE permanent. (this process may take a long time since we are going to generate 4096 bit key). You can grab a cup of tea while waiting for openssl generate DH parameters.
# openssl dhparam -out /etc/nginx/ssl/dhparam.pem 4096
Configure Nginx to accept SSL/HTTPS
You can insert this nginx’s configurations to your current Nginx site configure file or create a new Nginx configure file just for SSL. For our article, I will just create a new Nginx configure file for ssl.
# nano /etc/nginx/conf.d/ssl.conf
with the content
server { listen youripaddress:443 ssl; server_name yourdomainname; ssl on; ssl_certificate /etc/nginx/ssl/nginx.crt; ssl_certificate_key /etc/nginx/ssl/nginx.key; ssl_dhparam /etc/nginx/ssl/dhparam.pem; ssl_session_timeout 60m; ssl_session_cache shared:SSL:10m; ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers AES256+EECDH:AES256+EDH:!aNULL; ssl_prefer_server_ciphers on; add_header Strict-Transport-Security max-age=63072000; add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; location / { root /var/www/html; index index.html index.htm index.php; } }
Don’t forget to adjust server_name, location block, and .php block if you run PHP. Replace youripaddress and yourdomainname to yours, if you don’t have an dedicated IP address for your website, you can leave youripaddress empty and just use
listen 443 ssl;
Test and Restart Nginx
You will have to restart Nginx for the configurations to take affect.
# nginx -t # service nginx restart
Well because the ssl certificate is self-signed, web browsers can’t verify and firefox gives the error “could not verify this certificate because the issuer is unknown ” or google chrome gives “The identity of this website has not been verified. Server’s certificate is not trusted”
Redirect HTTP traffic to HTTPS
If you decide you use https as default rather than http for your website, you can redirect all http traffic to https permanently on nginx with this configure
server { listen ipaddress:80; server_name www.namhuy.net; return 301 https://$server_name$request_uri; } server { listen ipaddress:443 ssl; server_name www.namhuy.net; # the rest of your nginx's configures go here. }
Using openssl to verify SSL Certificate
This is just for your information, after digging about SSL topic, I found out it’s interesting what information openssl verification process give out about the certificate. So I guess it’s good to share the info. You can see exactly what kind of SSL certificate the server is running, protocol, cipher, and such with openssl verify command.
You can use this command below to verify your SSL certificates, it’s obviously we are creating/using self-signed ssl certificate so openssl gives back return code: 18 (self signed certificate) 🙂
# openssl s_client -showcerts -connect namhuy.net:443 < /dev/null
Sample output
CONNECTED(00000003) depth=0 C = us, ST = california, L = westminster, O = namhuy.net, CN = namhuy.net verify error:num=18:self signed certificate verify return:1 depth=0 C = us, ST = california, L = westminster, O = namhuy.net, CN = namhuy.net verify return:1 --- Certificate chain 0 s:/C=us/ST=california/L=westminster/O=namhuy.net/CN=namhuy.net i:/C=us/ST=california/L=westminster/O=namhuy.net/CN=namhuy.net --- Server certificate -----BEGIN CERTIFICATE----- MIIDnzCCAoegAwIBAgIJAKJR/oBgTGAMMA0GCSqGSIb3DQEBCwUAMGYxCzAJBgNV BAYTAnVzMRMwEQYDVQQIDApjYWxpZm9ybmlhMRQwEgYDVQQHDAt3ZXN0bWluc3Rl cjERMA8GA1UECgwIbGx2bi5uZXQxGTAXBgNVBAMMEGNyaXNzaWMubGx2bi5uZXQw HhcNMTQxMjA4MDMxODU2WhcNMTUxMTI5MDMxODU2WjBmMQswCQYDVQQGEwJ1czET MBEGA1UECAwKY2FsaWZvcm5pYTEUMBIGA1UEBwwLd2VzdG1pbnN0ZXIxETAPBgNV BAoMCGxsdm4ubmV0MRkwFwYDVQQDDBBjcmlzc2ljLmxsdm4ubmV0MIIBIjANBgkq hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqIf+8BXFxW8raE9WjvJZUirHDFS2mYyG 4XQhRsvTslLdwKCva0v2LgLedM95a39KSEnWjN5ZUdoVhkkwyG/KZPD9fxz9JCKd SAIk0oE8w2E96B0P3yHXCCJ3TYiXEkg9jxmTsObLaFt5L5XGh19d4MYv+Xs8R9Cr q7SmzqcwH7/GEV9I4KOH2m55Hb3J1sArEkgFJnlaXrhg1CIdFBq6q62OEYrGZfnP XgR+CxvShCEnSAtlpzBRnLgdIggyYpC5nTKCTnrQdQbFwChfzYlF3yVKbe36px7h ch9MMKXIH44xPbr302iiMuWlDOBcKT9y31qXyb5qKEdm5LTWWmYoawIDAQABo1Aw TjAdBgNVHQ4EFgQUFZwEMNAv/KUCpDNf6b8w8+YT/b0wHwYDVR0jBBgwFoAUFZwE MNAv/KUCpDNf6b8w8+YT/b0wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC AQEARMa6M79KmXFxdTbZxHo7KHKLHaVN78Sln2avDXMmtTrrxxYXNScjC5Nio55I 4ZHotFNi5K8ofzPOzsYnCZ0qp0Qmkz0h9l3oZD1HuqeEAqgY3yGCsx6/ix5btw9u e1POVyNZudD6wUNDZGLeIzmq8nMc2tbw0ZGB3zOiLG9Jq6z5nobYKklN5KWYVLDA 3BS2AXDWnfOyIKroHvVy/XtV9Y2LmTsJZTHRduMRLxv0+TfSdohngddlVIxh4YsC Vr95P2C1CY4uOfRwwjm+S5jhjnx31nq87ZOADcnQDA3ng5s10dqjGOEbYDnCL5JN tbL6ygc/uakrZQneDcNvN7/2zQ== -----END CERTIFICATE----- subject=/C=us/ST=california/L=westminster/O=namhuy.net/CN=namhuy.net issuer=/C=us/ST=california/L=westminster/O=namhuy.net/CN=namhuy.net --- No client certificate CA names sent Server Temp Key: ECDH, prime256v1, 256 bits --- SSL handshake has read 1606 bytes and written 375 bytes --- New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384 Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES256-GCM-SHA384 Session-ID: 5E21EAF10F4C8F982868B404A941D2771DD67D5E49103CDFF069EBF0285214B5 Session-ID-ctx: Master-Key: 1D63417742EE7D696330CD14FE67C619E78B0918818AD2F10D4BBDB4EC4005634EBD5D1A145FBBF031F636D953341FEB Key-Arg : None Krb5 Principal: None PSK identity: None PSK identity hint: None TLS session ticket lifetime hint: 3600 (seconds) TLS session ticket: 0000 - 61 21 58 c7 1c 5f b5 db-39 d3 10 85 f6 c6 cf e4 a!X.._..9....... 0010 - 1a b3 7a a6 00 f0 b1 22-d6 15 12 6b eb 05 5b 27 ..z...."...k..[' 0020 - d7 9f 77 89 47 94 8e 57-ab 46 e9 7f eb 0b cb ec ..w.G..W.F...... 0030 - 3d aa ef 61 93 1e 58 79-a0 40 b6 b2 38 ec 2e db [email protected]... 0040 - 15 56 d8 74 4c 06 b9 14-e3 cd bc cf e0 18 77 bc .V.tL.........w. 0050 - 57 e6 09 a9 f8 14 7d 2a-54 22 5d c3 2d 52 49 21 W.....}*T"].-RI! 0060 - 56 fd 96 0e f2 fa c4 66-51 b9 2f d9 5f da d2 68 V......fQ./._..h 0070 - 0e 0b 2d 8a 72 2a a9 b8-b7 13 7c 86 55 5d 9c fb ..-.r*....|.U].. 0080 - 0f d8 b4 1f 43 a0 c7 67-70 4d c7 29 6e 18 47 21 ....C..gpM.)n.G! 0090 - 02 d0 19 2d fe 35 17 95-00 b2 a9 19 cd 4a 3a 40 ...-.5.......J:@ 00a0 - 7a b3 3f ed 74 a0 90 b3-6f 1d 68 4d fb ee 8e 42 z.?.t...o.hM...B Start Time: 1418043711 Timeout : 300 (sec) Verify return code: 18 (self signed certificate) --- DONE
References
- “X509.” Openssl. N.p., n.d. Web. 08 Dec. 2014. <https://www.openssl.org/docs/apps/x509.html>.
- “Strong SSL Security on Nginx – Raymii.org.” Raymii.org. Raymii, n.d. Web. 08 Dec. 2014. <https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html>.
- Pornin, Thomas. “Diffie-Hellman and Its TLS/SSL Usage.” N.p., n.d. Web. 26 Aug. 2013. <http://security.stackexchange.com/questions/41205/diffie-hellman-and-its-tls-ssl-usage>.
- “Security/Server Side TLS.” – MozillaWiki. N.p., n.d. Web. 09 Dec. 2014. <https://wiki.mozilla.org/Security/Server_Side_TLS>.