I think it is important to use SSL certificates to protect communications over the commodity Internet, but I don’t need to spend the money for an SSL certificate when it is strictly for my personal use. So, I use self-signed certificates for SMTP, IMAP, POP and Web sites that are just for me. It gives me an encrypted connection between my server and my laptop (especially handy when I am travelling). Here is how I do it.

There are basically two types of self-signed certificates: those that are signed by a local certificate authority and those that aren’t. To determine which is needed depends on the requirements of the specific application. In this blog, I will cover both types of certificates and list with which applications I use each type. By the way, if you need a reminder about the typography used in this post, look here.

Creating a Self-Signed Certificate with a Certificate Authority

Essentially, this requires creating two self-signed certificates: one for the Certificate Authority and one for the server certificate.

  1. Create a local certificate authority (CA) on the server. I typically do this in the /etc/mail. As the root user, type cd /etc/mail; mkdir CA; cd CA, chmod 700 . to create the CA root directory and protect it.
  2. Type mkdir certs crl newcerts private; echo "01" > serial; touch index.txt to create the required directories and files for the local CA.
  3. Finish up by typing ln -s ../CA demoCA to insure the CA points to this working directory.
  4. Now, it’s time to create the CA certificate and key. I set it to be valid for the next 3650 days instead of the default 365. Type openssl req -nodes -new -days 3650 -x509 -keyout private/cakey.pem -out cacert.pem and here is a sample session that shows the dialogue produced by this command if run on a host called shemp.academ.com:
    Generating a 1024 bit RSA private key
    .........++++++
    ...............................++++++
    writing new private key to 'private/cakey.pem'
    -----
    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) [AU]:US
    State or Province Name (full name) [Some-State]:Texas
    Locality Name (eg, city) []:Houston
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:Academ
    Organizational Unit Name (eg, section) []:SSL Certs
    Common Name (eg, YOUR name) []:shemp.academ.com
    Email Address []:postmaster@shemp.academ.com
    
  5. Type openssl req -nodes -new -x509 -keyout server.key -out server.ucrt to produce the SSL certificate. Here is a sample session that shows the dialogue produced by this command if run on a host called shemp.academ.com
    Generating a 1024 bit RSA private key
    ...++++++
    ................++++++
    writing new private key to 'server.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) [AU]:US
    State or Province Name (full name) [Some-State]:Texas
    Locality Name (eg, city) []:Houston
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:Academ
    Organizational Unit Name (eg, section) []:SSL Certs
    Common Name (eg, YOUR name) []:shemp.academ.com
    Email Address []:postmaster@shemp.academ.com
    
  6. A certificate request must now be created. Type openssl x509 -x509toreq -in server.ucrt -signkey server.key -out server.csr to create the certificate request. Here is a sample session that shows the dialogue produced by this command if run on a host called shemp.academ.com:
    Getting request Private Key
    Generating certificate request
    
  7. Finally, sign this request with the CA certificate. Again, I set it to be valid for the next 3650 days instead of the default 365 days. Type openssl ca -policy policy_anything -days 3650 -out server.crt -infiles server.csr to generate the final signed certificate. Once again, the sample session on shemp.academ.com:
    Using configuration from /etc/ssl/openssl.cnf
    Check that the request matches the signature
    Signature ok
    Certificate Details:
            Serial Number: 1 (0x1)
            Validity
                Not Before: Mar  6 22:46:03 2010 GMT
                Not After : Mar  3 22:46:03 2019 GMT
            Subject:
                countryName               = US
                stateOrProvinceName       = Texas
                localityName              = Houston
                organizationName          = Academ
                organizationalUnitName    = SSL Certs
                commonName                = shemp.academ.com
                emailAddress              = postmaster@shemp.academ.com
            X509v3 extensions:
                X509v3 Basic Constraints:
                    CA:FALSE
                Netscape Comment:
                    OpenSSL Generated Certificate
                X509v3 Subject Key Identifier:
                    3C:37:11:AE:1F:60:44:F7:4D:08:90:BC:32:20:56:22:41:4E:C1:AF
                X509v3 Authority Key Identifier:
                    keyid:64:FD:A2:0D:2C:87:06:17:DA:2E:BB:07:CE:D0:85:D2:BB:31:FD:18
    
    Certificate is to be certified until Mar  3 22:46:03 2019 GMT (3650 days)
    Sign the certificate? [y/n]:y
    
    1 out of 1 certificate requests certified, commit? [y/n]y
    Write out database with 1 new entries
    Data Base Updated
    

For software (like sendmail) where this type of certificate is required, the CA certificate (cacert.pem), server certificate (server.crt), and server key (server.key) are required. As long as the hostname in these certificates matches what the software expects the hostname to be, these same certificates can be used with apache and cyrus-imapd.

Creating a Self-Signed Certificate without a Certificate Authority

  1. Make a fresh directory in your home directory to use as a work space for this work and cd into it.
  2. Next, protect that directory from access by others by typing chmod 700 . and only you (and root) will be able to get into the directory.
  3. To generate the key, type openssl genrsa -des3 -out server.key 1024. openssl prompts for a password. I use something easy to remember since I only need it for a short period of time.
  4. The next step is to create the self-signed certificate. Type openssl req -new -x509 -nodes -sha256 -days 3650 -key server.key -out server.crt. openssl prompts for several items of information. The County Name is the two letter
    Here is an example of making a self-signed certificate for the server named shemp.academ.com:

    Enter pass phrase for server.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) [AU]:US
    State or Province Name (full name) [Some-State]:TX
    Locality Name (eg, city) []:Houston
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:Academ
    Organizational Unit Name (eg, section) []:SSL Certificates
    Common Name (eg, YOUR name) []:shemp.academ.com
    Email Address []:postmaster@academ.com
    
  5. You probably don’t want to type the password for the key every time you start up the service using the SSL certificate, so remove the password from the key.
    • First, make a copy of the key. Type cp server.key server.key.orig.
    • Remove the password from the key. Type openssl rsa -in server.key.orig -out server.key

Use this key (server.key) and certificate (server.crt) for apache and cyrus-imapd on those systems where a SSL/TLS-enabled sendmail is not running.

Learning More

There are a number of good resources to read about SSL. Check http://www.openssl.org for the current status of the openssl software. You can read more in the book Network Security with OpenSSL where there is more extensive discussion of the process outlined in this posting in Chapter 5. A good web page on setting up sendmail to use STARTTLS properly is at http://www.technoids.org/starttlstut.html. The Apache Project provides details on using these certificates on their web server software at http://httpd.apache.org/docs/2.1/ssl/ssl_faq.html. I have updated my posting about cyrus to include how to add TLS/SSL to it.

When setting up IMAP servers, I look at two basic approaches. One is to setup IMAP as a service on a machine that will be doing other things (shared web hosting, mailing list service, SMTP relay/routing, interactive shell access via SSH, FTP server, etc.) that might be controlled through a control panel (cPanel, WebMIN/UserMIN/VirtualMIN, etc.). The other is to setup a machine that is a dedicated IMAP store. For the first case, I generally use Dovecot. For the second case, I use Cyrus. This posting concerns this second case. I will be also writing about the other case in a future post. By the way, if you need a reminder about the typography used in this post, look here.

When considering the system requirements, a key consideration is on how the IMAP server will be used. Will there be a large number of users? How many messages will need to be handled per hour? What IMAP clients are the users typically going to be using? One of the best discussions on this is in a book now 10 years old called Managing IMAP from Dianna Mullet & Kevin Mullet and published by O’Reilly. In Chapter 16 where they discuss performance tuning, they advise that Disk I/O is the biggest concern, followed by memory and then by bandwidth. In the last 10 years, there have been significant improvements in all three of these areas, but it is wise to be mindful of these same things when setting up a server. In particular, I would recommend the fastest disks connected the fastest possible way to the computing sub-system of your computer and a reasonably large chunk of memory for the system. For my latest generation IMAP servers (running Cyrus), I use Core Duo CPUs with 2Gb of memory and SATA 7200rpm Seagate Black 1TB drives. Setting up RAID is recommended as well as doing some kind of disk-to-disk backup. This will make it possible to recover quickly should something go awry. Because FreeBSD makes good use of multiple CPUs, parts of Cyrus can run on different CPUs at the same time and improve overall performance for certain tasks. My choices are based on my need to store a large number of messages for a long time, do lots of indexing to make searching easier, do inbound message sorting and filtering (using sieve) on a moderate number of messages per hour (less than a thousand). Those of you who are interested in doing this on Linux may want to read a more recent book called The Book of IMAP: Building a Mail Server with Courier and Cyrus where the authors, Peer Heinlein and Peer Hartleben, discuss the relative merits of the Ext3, ReiserFS 3 and ZFS on Linux (chapter 4). For small servers (20 users or less), they are satisfied with the performance of the standard Ext3 file system.

Since Cyrus maintains a common message store for all users (kinda like /var/mail for traditional Unix Mail), I recommend that this store be put on its own disk partition. I use a full 1TB drive for this. This will limit the growth of the store without using quotas. I also recommend that this store not be on the same partition as the MTA’s queue. There are a number of other database files that Cyrus uses. By default, these will be placed in the /var/imap directory. I recommend that the /var partition be bigger than you may normally use for these imap server systems. I have allocated 100GB /var on the systems I use. I don’t personally use OS quotas on these systems. I recommend that if you want to use quotas, you use the Cyrus built-in quota system. I don’t intend to discuss the details here, but you can read more about setting quotas up in The Book of IMAP: Building a Mail Server with Courier and Cyrusin Chapter 14.

As with any ports-based installation on FreeBSD (for recent versions of FreeBSD), it’s best to be sure the latest copy of the ports is on the system. portsnap is the easy way to get this done. As root, type portsnap update portsnap has been used to update /usr/ports before. If not, type portsnap fetch followed by portsnap extract.

Once the /usr/ports update is complete, type cd /usr/ports/mail/cyrus-imapd23 and type make to get the installation started. A page full of options is displayed. The defaults are fine, so tab down to OK and hit enter to move on. Now, type make all install.

Cyrus uses SASL to handle authentication, so if the cyrus-sasl2 package has not been installed previously, it will be installed to meet the prerequisites for cyrus-imapd23. I recommend using the Berkeley DB option and the defaults for the rest. Tab down to OK and hit enter to move on. There are some other things that cyrus-sasl2 will install in order to make it possible to build the package, but none of these will require further interaction.

When everything is done, there are still some post-installation tasks to do. Here is a list:

  • Add an entry for the sieve service to /etc/services. Typically, this is recommended to be port 4190 over TCP, but any port is fine as long as it is the same for all the systems that will access this system.
  • If my recommendation to put the mail store on its own partition was followed, then modify /usr/local/etc/imapd.conf to update the line that starts with partition-default:. Replace the default (/var/spool/imap) with the full path to the location where the mail store is mounted. On my systems, I use /store, so I have a line that looks like this: partition-default: /store.
  • To make use of the saslauthd for authentication, another line in /usr/local/etc/imapd.conf needs to be changed. This line starts with sasl_pwcheck_method:. Replace the default (auxprop) with saslauthd.
  • Make cyrus the name of the cyrus-imapd administrator by adding admins: cyrus to /usr/local/etc/imapd.conf
  • Set the password for cyrus in the SASL database. Type /usr/local/sbin/saslpasswd2 cyrus and then enter the password for this administrative account.
  • Prep the mail store by running /usr/local/cyrus/bin/mkimap.
  • Add cyrus_imapd_enable="YES" to /etc/rc.conf on the server
  • Setup logging.
    • Type touch /var/log/local6.log.
    • Add local6.debug /var/log/local6.log to /etc/syslog.conf
    • Restart syslogd by typing /etc/rc.d/syslogd restart
    • Add /var/log/local6.log 600 7 * @T00 JN to /etc/newsyslog.conf
  • Install the saslauthd daemon and start it.
    • Type cd /usr/ports/security/cyrus-sasl2-saslauthd and then make.
    • Select the Berkeley DB option and use the rest of the defaults. Tab down to OK and hit enter to move on.
    • Add saslauthd_enable="YES" to /etc/rc.conf on the server.
    • Add saslauthd_flags="-a sasldb" to /etc/rc.conf on the server.
    • Start the saslauthd server. Type /usr/local/etc/rc.d/saslauthd start.
  • Start the cyrus-imapd daemon by typing /usr/local/etc/rc.d/imapd start.
  • To add a mail user called jdoe, type su -m cyrus to become the system user cyrus and then login as the mail administrator cyrus using cyradm.
    • Type cyradm localhost and hit enter.
    • Type cm user.jdoe and hit enter.
    • Type quit to exit cyradm.
  • Set the password for jdoe in the SASL database. Type /usr/local/sbin/saslpasswd2 jdoe and then enter the password for this mail user account.
  • Validate the installed by typing imtest -a jdoe. Type the password entered in the previous step and hit return. Here is an example of the dialogue:
    testhost# imtest -a jdoe
    WARNING: no hostname supplied, assuming localhost
    S: * OK [CAPABILITY IMAP4 IMAP4rev1 LITERAL+ ID STARTTLS AUTH=NTLM AUTH=LOGIN AUTH=PLAIN AUTH=GSSAPI AUTH=DIGEST-MD5 AUTH=CRAM-MD5 SASL-IR COMPRESS=DEFLATE] testhost.example.com Cyrus IMAP v2.3.16 server ready
    C: A01 AUTHENTICATE DIGEST-MD5
    S: + bm9uY2U9InliSUF5Nmx3RlVJMFhlSkZraUI3SzloWitCOUFDWGFDVitmbmpTaHYwTkU9IixyZWFsbT0ic2hlbXAuYWNhZGVtLmNvbSIscW9wPSJhdXRoLGF1dGgtaW50LGF1dGgtY29uZiIsY2lwaGVyPSJyYzQtNDAscmM0LTU2LHJjNCxkZXMsM2RlcyIsbWF4YnVmPTQwOTYsY2hhcnNldD11dGYtOCxhbGdvcml0aG09bWQ1LXNlc3M=
    Please enter your password:
    C: dXNlcm5hbWU9InNiYXJiZXIiLHJlYWxtPSJzaGVtcC5hY2FkZW0uY29tIixub25jZT0ieWJJQXk2bHdGVUkwWGVKRmtpQjdLOWhaK0I5QUNYYUNWK2ZualNodjBORT0iLGNub25jZT0iWWZMMjFad2RrTzdGNDJIY0Y2S2tlZUJ1RFoxNDVhTkFOTHBJU25xTUZrVT0iLG5jPTAwMDAwMDAxLHFvcD1hdXRoLWNvbmYsY2lwaGVyPXJjNCxtYXhidWY9MTAyNCxkaWdlc3QtdXJpPSJpbWFwL2xvY2FsaG9zdCIscmVzcG9uc2U9YmNjMmE5OTdjZTQ5NTA5ZDczZWUyMDNlNWNlMzkzZTE=
    S: + cnNwYXV0aD1jM2FmOGMzMDc3OWY4OWFmNzg2MTE1NzhkNDQ3NzQ0Zg==
    C:
    S: A01 OK Success (privacy protection)
    Authenticated.
    Security strength factor: 128
    C: C01 CAPABILITY
    S: * CAPABILITY IMAP4 IMAP4rev1 LITERAL+ ID LOGINDISABLED AUTH=NTLM AUTH=LOGIN AUTH=PLAIN AUTH=GSSAPI AUTH=DIGEST-MD5 AUTH=CRAM-MD5 COMPRESS=DEFLATE ACL RIGHTS=kxte QUOTA MAILBOX-REFERRALS NAMESPACE UIDPLUS NO_ATOMIC_RENAME UNSELECT CHILDREN MULTIAPPEND BINARY SORT SORT=MODSEQ THREAD=ORDEREDSUBJECT THREAD=REFERENCES ANNOTATEMORE CATENATE CONDSTORE SCAN IDLE URLAUTH
    S: C01 OK Completed

    Note: The Digest-MD5 strings sent by the server may be poorly formatted in this example. I would have prefer that they wrap, but I am stilll learning how to get the formatting to look right for that. If you have a hint or trick that can help me wrap it properly, contact me.

To integrate this with sendmail the default local mailer needs deliver to cyrus. This is done by changing the /etc/mail/sendmail.cf file. Here are the steps:

  • Become the root user and type cd /etc/mail.
  • Type make to create the hostname-based mc file.
  • Add the following three lines to hostname-based mc file.
    define(`confLOCAL_MAILER',`cyrusv2')
    define(`CYRUS_MAILER_PATH',`/usr/local/cyrus/bin/deliver')
    MAILER(`cyrusv2')
  • Now type make stop; make all; make start.

The IMAP server is ready to receive SMTP mail for jdoe. Keep in mind that by default cyrus is setup to use an authentication scheme that requires NTLM, DIGEST-MD5, or GSSAPI. The IMAP client needs to be properly configured to use one of these authentication schemes. I use DIGEST-MD5.

What about using TLS/SSL?

It’s pretty easy to setup TLS/SSL on cyrus.

  • First, a properly signed certificate must be available that matches the hostname of the server on which cyrus is running. I have written a posting on setting up a self-signed certificate.
  • Next, the /usr/local/etc/imapd.conf configuration file must be modified to define the following items:
    • tls_cert_file: must have the full path to the file containing the server certificate.
    • tls_key_file: must have the full path to the file containing the server certificate key. Note that the cyrus user must be able to read the key file.
  • If you are using a certificate authority signed server certificate, tls_ca_file: must have the full path to the file containing the certificate authority certificate used to sign that server certificate.
Comments Off
 | Posted by | Categories: FreeBSD | Tagged: , , , , |