Sept. 21, 2013, 2:33 p.m. by mati

Recently, Thijs Alkemade published a three-part blog post on "The State of TLS security on XMPP". Part 1 covers the quality of TLS encryption on client-to-server (c2s) connections, while part 2 covers server-to-server (s2s) connections (and part 3 covers clients, not of interest in this article). Thijs also graded encryption quality, and as it turns out, jabber.at was in the top-spot in encryption quality. This may give us a reason to celebrate, but it does draw a sad picture of the quality of encryption on the Jabber/XMPP network: We didn't exactly take any extraordinary steps to secure our server. This post is aimed at giving a few hints at Jabber server administrators, I hope it helps improving quality. While the tips given here apply to any server on any platform, examples here are tested on Debian/Ubuntu only (but should work on any Unix-like operating system in most cases).

Your operating system

Definitely a no-brainer: Keep your operating system up to date. I don't just mean "install all security updates", but also upgrade to the most recent stable version. Judging by the s2s-results there are 30 servers using Linux 2.6.32 and 22 servers using Linux 3.2.0. While you can't tell for sure, most Linux 2.6.32 servers are either Ubuntu 10.04 ("Lucid Lynx") or Debian 6.0 ("Squeeze"), while most Linux 3.2.0 servers are either Ubuntu 12.04 ("Precise Pangolin") or Debian 7.0 ("Wheezy"). That means that at least one third of the list (Prosody doesn't return the Linux version) use an outdated operating system. That is just sad (and sloppy system administration). Ubuntu 12.04 was released 15 months ago, Debian 8.0 was released four months ago. I am aware that the older versions are still officially supported, but neither Ubuntu nor Debian mean "new security ciphers" by that. If you look at the results of i.e. swissjabber.ch you will see that they get a low score primarily due to the lack of TLSv1.1/1.2 support and due to the few supported secure ciphers. So put an upgrade to the most recent (stable) release on the top of your todo-list, if you haven't already updated.

Your SSL certificate

Getting a "good" SSL certificate is not that hard. The two free options that I know of are CAcert.org or StartSSL. The latter has the advantage that it's accepted by all browsers and by Thijs' script used in his blog posts. We use StartSSL, so I can only guide you through their website, but I'm sure any other Certificate Authority is similar. When creating a certificate, you should always create your private key locally, create a CSR ("Certificate Signing Request") and submit that to your Certificate Authority. First use OpenSSL to create a private key and CSR (replace "jabber.at" with your own hostname):
openssl genrsa -out /etc/ssl/private/jabber.at.key 4096 openssl req -new -key /etc/ssl/private/jabber.at.key \     -out /etc/ssl/jabber.at.csr -utf8 -batch -subj "/CN=jabber.at/"
What you enter as a subject is mostly irrelevant, the StartSSL interface strips anything but the Common Name. Do make sure that the Common Name is the same as the domain used by your jabber server, though. You now need your Certificate Authority to sign your CSR. If you use StartSSL, first verify your domain via Control Panel → Validations Wizard → Domain Name Validation. Then click Certificates Wizard → Web Server SSL/TLS certificate (don't bother with the XMPP option). Click "Skip" at the first step ("Generate Private Key") so you can paste the CSR-file you just created (/etc/ssl/jabber.at.csr in the above example). You might also want to add 'www.' as a SubjectAltName later on in the wizard, if you intend to use the certificate for your webserver as well. Either way, the webinterface will present you with the signed certificate, save this to i.e. /etc/ssl/public/jabber.at.pem. The only thing left is make your Jabber server software use your shiny new certificate. For ejabberd, concatenate your private and public key (the default configuration uses the path in this example):
cat /etc/ssl/private/jabber.at.key /etc/ssl/public/jabber.at.pem > /etc/ejabberd/ejabberd.pem

Your Jabber server software

Keeping your Jabber server software up to date is as important as your operating system. You can always compile your own software or obtain it via some other sources, i.e. their website. If you use ejabberd and Debian/Ubuntu, you can also use our apt-repositories (replace "precise with your own distro as appropriate):
echo "deb http://apt.jabber.at/ precise ejabberd" > /etc/apt/sources.list.d/ejabberd.list apt-get update apt-get install fsinf-keyring apt-get update apt-get install ejabberd ejabberd-mod-admin-exta
As an added bonus, our repositories contain 21 modules from the ejabberd-modules SVN repository. Just do apt-cache search -n ejabberd to see what's available. If you use Prosody, check their download page to get their newest version. They even provide APT repositories for Debian/Ubuntu.

Your server software configuration

We use ejabberd, which can be a bit hard to configure. If you're interested, our configuration is available in a public git repository. You might take few hints from there. These are some of the crucial points in the configuration (with minor adaptions from our configuration):
{define_macro, 'CERT_LOCATION', "/etc/ejabberd/ejabberd.pem" }.

{listen, [
    {5222, ejabberd_c2s,    [zlib, starttls_required, inet6,
                             {access, everybody}, {shaper, c2s_shaper},
                             {certfile, 'CERT_LOCATION'},
                             {max_stanza_size, 65536}
                            ]},
    {5223, ejabberd_c2s,    [zlib, tls, inet6,
                             {access, everybody}, {shaper, c2s_shaper},
                             {certfile, 'CERT_LOCATION'},
                             {max_stanza_size, 65536}
                            ]},
    % server to server connections:
    {5269, ejabberd_s2s_in,  [inet6,
                              {access, everybody}, {shaper, s2s_shaper},
                              {max_stanza_size, 131072}]},

    % ... any additional config
]}.

% Allow STARTTLS on s2s connections:
{s2s_use_starttls, optional}.
% REQUIRE STARTTLS for s2s connections - breaks gmail.com, otherwise works like a charm:
%{s2s_use_starttls, required}.
{s2s_certfile, 'CERT_LOCATION'}.

% First try IPv6, then try IPv4:
{outgoing_s2s_options, [ipv6, ipv4], 10000}.
You might want to note:
  • We do require StartTLS on all (both c2s and s2s) connections. For c2s connections, this causes no problems whatsoever, we haven't seen an unencrypted connection for at least a year before requiring STARTTLS. For s2s connections, you're not so lucky: All servers hosted by google (including gmail.com) do not allow any encryption. So you either set this to optional or you have to live with no gmail.com connectivity (we chose the latter).
  • We have IPv6 support. If you don't, get an IPv6 address as soon as possible. This is the future, isn't it?

Conclusion

That's basically it. We didn't do any complex OpenSSL configuration. No super-secret Linux tricks. A standard, up to date, server will provide great encryption for your users. Add a valid SSL/TLS certificate and some minor configuration, and you'll have top notch encryption.