Locking more of the web down behind TLS and SSL
Tags: serversThis is another case of yak shaving that all started with trying to implement imapproxy to proxy internal IMAP connections between Dovecot and SquirrelMail on my public servers.
Implementing imapproxy was a simple drop-in. All that was required was some server-side configuration to get Dovecot to listen to the server port that imapproxy uses, and then get imapproxy to listen on the public (external) port for clients to connect to.
In my /etc/dovecot/dovecot.conf
, I set up the following:
protocols = imap imaps protocol imap { listen = 127.0.0.1:14300 ssl_listen = *:993 } ... ssl_cert_file = /etc/ssl/certs/dovecot-ssl.crt ssl_key_file = /etc/ssl/private/dovecot-ssl.key
In /etc/imapproxy.conf
, I configured it as follows:
server_hostname 127.0.0.1 listen_port 143 listen_address 127.0.0.1 server_port 14300 ... tls_cert_file /etc/ssl/certs/dovecot-ssl.crt tls_key_file /etc/ssl/private/dovecot-ssl.key
Restarting both, and now IMAP connections are proxied and kept open for the duration of the session. It is visibly faster now when interacting with IMAP over that connection.
For SquirrelMail, I had to tweak accordingly as well to listen on port 14300
on host 127.0.0.1
. Under SquirrelMail’s config (Option 2 → A → 5 under the configure script), I changed the port to 14300
. That now gets SquirrelMail talking to imapproxy, speeding up webmail by several orders of magnitude.
But it was still in the clear. Unfortuntely, there’s no easy way to just plug SquirrelMail into IMAP over SSL… so I had to use stunnel to do that:
/usr/bin/stunnel -P/var/run/ -c -d 1430 -r 127.0.0.1:993
Now I went back into SquirrelMail’s config and changed the port to 1430
from 14300
. Now SquirrelMail is talking to the local imapproxy → Dovecot over SSL instead of plain text.
But now my Dovecot certs needed to be regenerated because they were close to expiring, and with the recent Debian PRNG problem, it was better to just re-gen all certs and keys anyway.
To do that, I had to do the following:
$ openssl genrsa -out dovecot-ssl.key 4096 $ openssl req -new -key dovecot-ssl.key -out dovecot-ssl.csr
I pasted the contents of that final CSR (dovecot-ssl.csr
above) into the form at CACert and had them generate a new server certificate for my mail host: mail.gnu-designs.com, where my Dovecot instance resides. With that, I put those keys in their proper location and configured /etc/dovecot/dovecot.conf
accordingly:
ssl_cert_file = /etc/ssl/certs/dovecot-ssl.crt ssl_key_file = /etc/ssl/private/dovecot-ssl.key
Restarted Dovecot and now I’m properly secured with stronger, less vulnerable keys and certs.
But what about locking down SquirrelMail behind SSL as well?
To do that, I had to update my DNS to point mail.gnu-designs.com to a separate physical IP on the same machine. With Apache, you can’t have more than one SSL VirtualHost behind the same physical IP. Each new SSL host you want to deploy has to be on its own physical IP address.
So I had to change my DNS to point mail.gnu-designs.com from its present IP to a new IP on the same host. Now comes the tricky part… configuring Apache.
Since I run Debian, the Apache configuration is a bit… non-standard. In /etc/apache2/ports.conf
, I had to change the Listen
directive to listen on port 443
of that new IP.
Listen 72.36.135.43:443 Listen 72.36.135.43:80
And a VirtualHost stanza for that new SSL vhost had to be created..
Now my regular non-SSL stanza can be changed to look like this:
<VirtualHost *:80> ServerName mail.gnu-designs.com Redirect permanent / https://mail.gnu-designs.com/ </VirtualHost>
This will redirect non-SSL clients to the SSL version of the site, so their session is secured behind SSL on port 443
. One last poke to make it possible to use the SSL VirtualHosts without having to import the upstream Root CA Certificate:
SSLCACertificateFile ssl.certificates/cacert-root.crt
From the Apache 2.x documentation:
This directive sets the all-in-one file where you can assemble the Certificates of Certification Authorities (CA) whose clients you deal with. These are used for Client Authentication. Such a file is simply the concatenation of the various PEM-encoded Certificate files, in order of preference.
I duplicated the same process for my other SSL vhost; spam.gnu-designs.com, for the DSPAM web interface.
If you’re not using dspam to reduce your spam by 99.9%, you should be. It runs circles around every OSS and commercial product I’ve tried, and I’ve been running it for years (see my previous posts on dspam for more background and hard data).
Conclusion:
I did a few things here:
- Set up an IMAP proxy in front of Dovecot, my IMAP server which dramatically increased the responsiveness of the IMAP server
- Configured that proxy to speak SSL (imaps on port 993) as well as plain imap (port 143)
- Configured SquirrelMail to talk to the IMAP proxy over SSL only, using stunnel
- Locked down two of my public-facing Apache vhosts with SSL (webmail and dspam)
- Regenerated all SSL certificates and keys with stronger encryption using CACert
- Imported the CACert root certificate and made it global within all of my Apache SSL vhosts
Now everything is a bit more secure than it was before… for now.
Last note: As I was writing this post, I realized that WordPress was eating some characters in my
<code> … </code> blocks. I looked around for a plugin to try to alleviate that, and found several, none of which worked properly.
I tried Code Auto-Escape which at first glance looked promising, but all it did was encode my code blocks into a single-line base64 string, and output that. Blech.
Then I tried one called Code Markup which had a very detailed explanation and several ways to use it. It too failed miserably on the most basic of code blocks (the Apache stanzas above).
It referenced several other markup and syntax highlighting plugins (geshi, highlighting with Enscript, etc.), none of these worked as advertised either.
What I finally found that DID work, was a a Java-based tool called Code Format Helper for WordPress. Basically you paste your code block into the small java applet, and it converts all of the entities to encoded entities. You then paste that into your WordPress post and submit that. You can see in the above post that it works perfectly.
Voila!