Preparation
Versions prior to Apache v2.2.12 and OpenSSL v0.9.8j required a dedicated IP address for each certificate. With Server Name Indication (SNI) there is no need to request a new IP every time a certificate needs to be installed for a domain.
SNI can secure:
- Multiple Apache sites with a single certificate
- Multiple subdomains of a domains with multiple certificates
- Multiple domains from a single IP address
With that said, you don't have to request a dedicated IP address for sites that use SSL certificates.
In order to create certificates or certificate signing requests (CSR) and use them, openssl, apache, and mod_ssl must be installed on the system.
If you are purchasing an SSL certificate from a company such as DigiCert or GoDaddy you need to generate a Certificate Signing Request (CSR):
$ openssl req -out CSR.csr -new -newkey rsa:2048 -nodes -keyout privateKey.key $ openssl req -out CSR.csr -key privateKey.key -new $ openssl x509 -x509toreq -in certificate.crt -out CSR.csr -signkey privateKey.key
The first command creates a new CSR and private key. If you don't need a new private key, then you can create a new CSR based on your existing key by using the second command. A third way to create a CSR is to use an existing certificate, but you need the private key in order to do so. The req sub-command creates and processes certificate requests by taking various commandline options. When the --out option is used in conjunction with the req sub-command, it takes a parameter that specifies where the CSR will be placed.
The --new option specifies that we want to create a new private key causing OpenSSL to ask the user for values for relevant fields.--newkey takes the form of <algorithm:bits>. In the above example, we are creating a private key using the RSA algorithm with a length of 2048 bits. Other algorithms support the format of <algorithm:file> where file contains the parameters for the algorithm specified. This file is generated by using the genpkey sub-command.
--nodes specify that the key is not to be password protected.
--keyout specifies the name of the file to write the private key to.
The x509 sub-command is used to view information about, convert, and sign certificates specified by the -in option. The -x509toreq specifies that a CSR is to be generated from the certificate. The -signkey is used to pass the private key that's required when generating the CSR.
If you can get away with a self-signed certificate:
$ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout privateKey.key -out certificate.crt
Most of the command-line options used in creating a self-signed certificate are used in creating a CSR from a new or existing private key. The -x509 outputs the self-signed certificate rather a CSR, which is valid for the number of days specified by -days option.
Verifying
$ openssl req -text -noout -verify -in request.csr
The above retrieves the containing in the signing request by displaying the text (-text, -noout). The -verify command-line option indicates that the user wants to verify the file specified by -in.
To ensure that private key is valid, run the following command.
$ openssl rsa -in private.key -check
To print the certificate:
$ openssl x509 -in certificate.crt -noout -text Certificate: Data: Version: 3 (0x2) Serial Number: a2:42:e1:14:66:96:5c:8f Signature Algorithm: sha256WithRSAEncryption Issuer: C=US, ST=Texas, L=Dallas, O=Paulus World, OU=IT, CN=paulusworld.com/emailAddress=webmaster@paulusworld.com Validity Not Before: Oct 12 07:46:50 2016 GMT Not After : Oct 12 07:46:50 2017 GMT Subject: C=US, ST=Texas, L=Dallas, O=Paulus World, OU=IT, CN=paulusworld.com/emailAddress=webmaster@paulusworld.com Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:f4:5f:d8:67:ea:dd:bd:c4:ad:75:4a:40:42:2e: a6:0a:6f:af:7d:e4:1d:c9:c8:04:ec:ae:8e:07:58: 4a:1d:49:3b:a7:0a:4f:02:79:cc:4d:5e:11:c8:24: 47:77:be:ff:b6:f2:55:1f:8a:f3:61:18:5f:96:08: 27:7e:2b:50:fb:97:45:69:82:c2:ff:71:bb:89:6e: 63:35:d6:5e:4b:df:87:9a:81:b0:73:c4:fb:69:d4: e7:40:3e:7d:65:7a:a0:86:69:ea:09:a0:ee:c1:e1: 4f:54:b4:e7:f2:3c:25:b8:ad:c4:5b:25:af:25:37: b8:bb:e5:31:09:b7:47:4d:94:48:ee:b8:bd:1c:1f: 95:88:04:eb:e6:73:22:3b:0a:39:a6:c1:d3:65:0e: 28:0d:6b:5d:17:9d:20:71:21:2b:d9:5e:65:0f:cf: 87:d0:cd:90:4e:a9:65:4f:81:15:f9:1a:8a:3c:23: aa:0e:e7:c8:32:51:ce:f9:f3:63:da:12:6a:6d:65: 6a:dd:0f:02:6e:1b:26:d3:59:de:aa:c7:8b:37:d7: ed:31:ad:a8:5d:f8:2d:b7:e6:fa:70:29:96:cd:e3: 94:e3:18:fa:ed:29:16:11:c4:e3:34:fc:73:a7:ce: 9d:83:f6:ff:c5:fa:a1:85:7d:27:40:3e:71:71:c3: 94:fd Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: 9D:99:53:68:2E:77:28:48:34:4B:44:53:85:6C:CB:24:9F:B7:F0:7A X509v3 Authority Key Identifier: keyid:9D:99:53:68:2E:77:28:48:34:4B:44:53:85:6C:CB:24:9F:B7:F0:7A X509v3 Basic Constraints: CA:TRUE Signature Algorithm: sha256WithRSAEncryption 86:e6:80:9f:d8:9e:e1:2a:7a:1b:bd:fa:a5:1a:60:30:dd:ee: cb:d7:8a:17:4e:90:35:2c:d3:24:ba:29:b5:c9:64:a2:1d:f2: 9c:77:46:fd:d8:d5:5e:91:af:b6:37:42:b2:4f:72:e4:99:7d: 57:be:a5:25:41:9a:9e:19:b7:be:09:7e:84:2f:87:b0:54:a7: b2:82:1c:4c:9d:54:09:e7:86:97:b6:f2:c9:94:4b:59:e2:ed: 55:e7:46:f8:17:75:19:12:bc:70:f9:81:c8:f3:d7:c3:b4:9b: c9:66:e5:f3:80:46:08:ab:44:84:27:ca:c5:8c:b6:c1:79:93: 9f:75:e4:d5:9a:77:70:95:5c:85:d7:38:87:ad:96:f1:21:f0: 8a:42:b6:6c:46:cd:6e:95:35:f2:57:4e:ef:48:47:29:22:20: cc:56:86:08:fb:96:4b:c0:0d:1b:93:c6:6c:02:98:9d:25:21: ed:3d:8a:ff:e0:09:c7:bb:de:78:2b:87:14:72:ba:22:2b:8d: ed:5d:f9:1f:36:5e:d0:8e:db:c1:82:72:75:bd:45:72:a9:61: 50:99:25:b8:58:7f:4f:70:a4:76:36:1a:15:c8:c6:95:4f:e1: 4d:b0:5b:a0:04:2a:5f:e8:4f:97:ec:b4:7b:cc:06:fb:37:90: d4:aa:84:3a
To check a PKCS#12 file:
$ openssl pkcs12 -info -in keyStore.p12
Configuration
The minimal configuration lines that are needed are to enable SSL:
<VirtualHost *:443> ServerName www.example.com SSLEngine On SSLCertificateFile "/path/to/file.crt" SSLCertificateKeyFile "/parth/to/file.key" </VirtualHost>
The default and global SSL configuration settings are stored in a separate file located either in the /etc/httpd, /etc/apache or a subdirectory within the aforementioned directories.
When setting up a domain on a server that isn't managed by a control panel such as Plesk or cPanel, I break up the configuration for each virtual host based on domain. Each HTTP and HTTPS virtual host configuration lives in their own file located in either vhosts or ssl_vhosts, respectively.
<VirtualHost *:80> ServerName example.com ServerAlias www.example.com ServerAdmin webmaster@example.com ErrorLog "/path/to/logs/error_log" CustomLog "/path/to/logs/access_log" combined DocumentRoot "/path/to/web/root" <Directory "/path/to/web/root"> Options -Indexes -FollowSymLinks AllowOverride None # Redirects & Rewrites Include example.inc Require all granted </Directory> </VirtualHost>
<VirtualHost *:443> ServerName example.com ServerAlias www.example.com ServerAdmin webmaster@example.com ErrorLog "/path/to/logs/ssl-error_log" CustomLog "/path/to/logs/ssl-access_log" combined SSLEngine On # Specify Protocol SSLProtocol -All +TLSv1.2 SSLHonorCypherOrder On SSLCipherSuite SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5 SSLCertificateFile "/path/to/file.crt" SSLCertificateKeyFile "/path/to/file.key" SSLCertificateChainFile "/path/to/bundle.ctr" DocumentRoot "/path/to/we/root" <Directory "/path/to/web/root"> Include example_com.inc </Directory> </VirtualHost>
Troubleshooting
In the event that an error arises that the private key doesn't match or that the site isn't trusted, use these commands to verify that the SSL certificate was installed correctly:
$ openssl x509 -noout -modulus -in certificate.crt | openssl md5 $ openssl rsa -noout -modulus -in privateKey.key | openssl md5 $ openssl req -noout -modulus -in CSR.csr | openssl md5
To verify a certificate using the commandline:
$ openssl s_client -showcerts -connect example.com:443
Converting Certificates
Convert a DER file (.crt .cer .der) to PEM
$ openssl x509 -inform der -in certificate.cer -out certificate.pem
Convert a PEM file to DER
$ openssl x509 -outform der -in certificate.pem -out certificate.der
Convert a PKCS#12 file (.pfx .p12) containing a private key and certificates to PEM
$ openssl pkcs12 -in keyStore.pfx -out keyStore.pem -nodes
You can add -nocerts to only output the private key or add -nokeys to only output the certificates.
Convert a PEM certificate file and a private key to PKCS#12 (.pfx .p12)
$ openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.crt -certfile CACert.crt