I would like to host multiple domains and subdomains on my server and be able to use SSL encryption with some of them. Typically, you need to have one certificate for each domain, and you can only have one certificate per IP address, because the SSL protocol is negotiated based on the IP address before the browser sends the host name.
Certificates usually cost money, for each domain and subdomain, renewable every year. Enter CAcert: this non-profit organization provides free certificates based on a Web of Trust approach, similar to PGP/GPG. CAcert is working to get its root certificate included in more and more browsers, but it still has a long way to go, and it may never succeed in getting into MSIE. If you can live with that, CAcert is a great choice.
The information in this section is taken from here and boiled down to what you need. Save the following shell script as CAcert-csr.sh:
#!/bin/sh # csr.sh: Certificate Signing Request Generator # Copyright(c) 2005 Evaldo Gardenali <evaldo@gardenali.biz> # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # ChangeLog: # Mon May 23 00:14:37 BRT 2005 - evaldo - Initial Release # Mon Apl 09 14:34:56 CET 2005 - hs - Added some comments, create DH file # be safe about permissions LASTUMASK=`umask` umask 077 # OpenSSL for HPUX needs a random file RANDOMFILE=$HOME/.rnd # create a config file for openssl CONFIG=`mktemp -q /tmp/openssl-conf.XXXXXXXX` if [ ! $? -eq 0 ]; then echo "Could not create temporary config file. exiting" exit 1 fi echo "Private Key and Certificate Signing Request Generator" echo "This script was designed to suit the request format needed by" echo "the CAcert Certificate Authority. www.CAcert.org" echo printf "Short Hostname, used for the file name (ie. imap big_srv www2 / example): " read HOST printf "FQDN/CommonName (ie. www.example.com / example.com) : " read COMMONNAME echo "Type SubjectAltNames for the certificate, one per line. Enter a blank line to finish" echo "(probably want to repeat FQDN here!)" SAN=1 # bogus value to begin the loop SANAMES="" # sanitize while [ ! "$SAN" = "" ]; do printf "SubjectAltName: DNS:" read SAN if [ "$SAN" = "" ]; then break; fi # end of input if [ "$SANAMES" = "" ]; then SANAMES="DNS:$SAN" else SANAMES="$SANAMES,DNS:$SAN" fi done # Config File Generation cat <<EOF > $CONFIG # -------------- BEGIN custom openssl.cnf ----- HOME = $HOME EOF if [ "`uname -s`" = "HP-UX" ]; then echo " RANDFILE = $RANDOMFILE" >> $CONFIG fi cat <<EOF >> $CONFIG oid_section = new_oids [ new_oids ] [ req ] default_days = 730 # how long to certify for default_keyfile = $HOME/${HOST}_privatekey.pem distinguished_name = req_distinguished_name encrypt_key = no string_mask = nombstr EOF if [ ! "$SANAMES" = "" ]; then echo "req_extensions = v3_req # Extensions to add to certificate request" >> $CONFIG fi cat <<EOF >> $CONFIG [ req_distinguished_name ] commonName = Common Name (eg, YOUR name) commonName_default = $COMMONNAME commonName_max = 64 [ v3_req ] EOF if [ ! "$SANAMES" = "" ]; then echo "subjectAltName=$SANAMES" >> $CONFIG fi echo "# -------------- END custom openssl.cnf -----" >> $CONFIG echo "Running OpenSSL..." openssl req -batch -config $CONFIG -newkey rsa:2048 -out $HOME/${HOST}_csr.pem openssl gendh 512 >$HOME/${HOST}_dh.pem echo "Copy the following Certificate Request and paste into CAcert website to obtain a Certificate." echo "When you receive your certificate, you 'should' name it something like ${HOST}_server.pem" echo cat $HOME/${HOST}_csr.pem echo echo The Certificate request is also available in $HOME/${HOST}_csr.pem echo The Private Key is stored in $HOME/${HOST}_privatekey.pem echo rm $CONFIG #restore umask umask $LASTUMASK
Run this shell script to create a private key and a certificate request. The "Short Hostname" (first prompt) is just a file name; I recommend using a name that identifies the host, purpose, and date. The "FQDN/CommonName" (second prompt) will be used to identify your certificate on the CAcert website. On the next prompt(s) you can specify any number of domains and subdomains (like example.com, www.example.com, and/or *.example.com (*.example.com does not cover example.com!)).
Register each domain with cacert.org and finally create the server certificate by pasting the certificate request into the entry field at cacert.org.
Download the CAcert root certificate (and the class 3 intermediate certificate if you've created a class 3 certificate) in PEM format.
In Plesk go to Server|Certificates|Create, enter a name for the new certificate, e.g. something like "CAcert-YYYY-MM-DD", paste
into the three entry fields, and click the [Send Text] button.
Plesk will add the new certificate and display it with the three required icons. You don't need the CSR within Plesk. Now go to Server|IP Addresses and select the new certificate for the IP address(es) you want. This makes the web server use the new certificate.
Plesk uses other certificates for email:
These files combine the private key, certificate, CA root certificate(s), and the Diffie-Hellmann Parameters in composite files (simple concatenation). They start out as Plesk certificates, and if you want to use your own certificates, you can replace them. Isn't it nice to get free multi-site certificates from CAcert.org?
The SMTP certificate (including the private key!) needs to be world-readable, so you want to create a separate one just for that purpose. It should list the mail server (MTA) name as well as all the names of the domain-specific SMTP hosts.
If you've replaced qmail-smptd with qpsmtpd as your SMTP server, you can enable TLS support with the tls plugin — just add
tls ../ssl/qpsmtpd-server.crt ../ssl/qpsmtpd-server.key ../ssl/qpsmtpd-ca.crt
to your plugins file, and create and deploy the files.
I started out separating SMTP (mail.example.com) and POP3 (pop.example.com) to make it easier to migrate email accounts from one server to another, but it turns out that moving a mail server can be done in one piece, and I currently don't see any benefit in this separation.
On the contrary, if you use two different server names and different certificates from a certificate authority (CA) whose root certificate may not be installed in the client email program, then you'll have to ask your users to accept not one but two certificates. That's a lot to ask...
For now I will keep the separate server names, but I'm installing copies of a combined certificate covering mail.example.com, pop.example.com, imap.example.com as well as variants for each hosted domain for SMTP, POP3, and IMAP. Fortunately, CAcert supports creating such combined certificates, which allows this flexibility.
The CAcert root certificates are available at
Later, after updating the certificates, I suddenly started to get timeout messages, because qmail was unable to send mail to some 5 to 10% of the recipients:
TLS connect failed: error:140943F2:SSL routines:SSL3_READ_BYTES:sslv3 alert unexpected message; connected to xx.xx.xx.xx.
I'm not going to try again; this message has been in the queue too long.
Indeed, these messages started coming in for mails that had been queued one week (!) earlier. What a nasty surprise. It turned out that there was a mismatch of the pieces that went into qmail's certificate. Fixing the /var/qmail/control/servercert.pem
file cured the issue and the blocked messages started to go out over the course of a day.