OpenFire and Ciphers

OpenFire.

Running OpenFire for XMPP is fun, as it is a fully featured server that brings it’s own web-interface.  I have been running it for nearly a decade now.

Openfire is a real time collaboration (RTC) server licensed under the Open Source Apache License. It uses the only widely adopted open protocol for instant messaging, XMPP (also called Jabber). Openfire is incredibly easy to setup and administer, but offers rock-solid security and performance.

Scoring.

Most distribution bring openfire packaged and somewhat up-to-date,  but to be on the safe side you should install the .deb or .rpm files from the developers homepage.  Installation is pretty straightforward as configuration is done via the web-interface. You only need an up and running mysql (or mariadb) server and off you go. I will not go into installing said packages in this article, I assume you are able to get things running for yourself. If not, the remainder of this article is not for you – yet.

Issues start however getting a good grade over at xmpp.net:

xmpp.net score

Ciphers.

These scores are (somewhat) real-time (at least recent). OpenFire itsself has no way to configure any meaningful SSL/TLS context, besides setting encryption to off, optional or enforced. You can not set the cipher mode from within the web-interface. This is odd at first, but if you think about it — it makes sense. OpenFire itsself is “only” the running software on top of the Java-stack, so it’s great to restrict the Java-Stack to certain ciphers. This way no flaw in the software can re-enable faulty ciphers.

That being said you will get your ass handed to you from xmpp.net if you try to get your out-of-the-box OpenFire server certified as it would accept any and all ciphers (SSL2, SSL3, weak ciphers, rc4). Of course it’s easy to just allow one big-ass cipher, making your server the ultimately best secured (in terms of connection) around — also the loneliest. Because no one could connect because their cipher is not supported. The trick is to get the right mix of ciphers while not compromising security and not losing on the cipher score from xmpp.net.

So, to get to good on the grades while not kicking of any older clients that can’t handle TLS1.x or even deny server to server connections I recommend these ciphers enabled:

ciphers

In order to achieve this you need to install JDK of at least version 7 and make sure your OpenFire installation uses JDK/JRE7 instead of 6. In debian thats as easy as doing an “apt-get install openjdk-7-jre-headless“.  I am using the openjdk edition of Java, simply because it’s in the default repository and it works. Now the default installation has some OpenFire related quirks that we need to fix.

For starters TLS dialback will always fail and thus no server to server connections can be established. This is due to a, let’s call it bug, in OpenJDK that can not correctly validate remote certificates. Let’s remedy that by editing /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/security/java.security,  go to line 58 and disable (add a hash (#) at the beginning of the line

security.provider.10=sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/nss.cfg

Now to disable the weak ciphers. Edit the file /etc/java-7-openjdk/security/java.security, go to the end and add these two lines:

jdk.tls.disabledAlgorithms=SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA, SSL_DH_anon_EXPORT_WITH_RC4_40_MD5, SSL_DH_anon_WITH_3DES_EDE_CBC_SHA, SSL_DH_anon_WITH_DES_CBC_SHA, SSL_DH_anon_WITH_RC4_128_MD5, SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA, SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA, SSL_DH_DSS_WITH_DES_CBC_SHA, SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DH_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA, SSL_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_RC4_128_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, SSL_FORTEZZA_DMS_WITH_NULL_SHA, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT1024_WITH_DES_CBC_SHA, SSL_RSA_EXPORT1024_WITH_RC4_56_SHA, SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_FIPS_WITH_DES_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_RSA_WITH_IDEA_CBC_SHA, SSL_RSA_WITH_NULL_MD5, SSL_RSA_WITH_NULL_SHA, SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, SSL_DH_anon_EXPORT_WITH_RC4_40_MD5, SSL_DH_anon_WITH_RC4_128_MD5, SSL_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA, SSL_DHE_DSS_WITH_RC4_128_SHA, TLS_DHE_PSK_WITH_RC4_128_SHA, TLS_ECDH_anon_WITH_RC4_128_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_PSK_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS_KRB5_EXPORT_WITH_RC4_40_MD5, TLS_KRB5_EXPORT_WITH_RC4_40_SHA, TLS_KRB5_WITH_RC4_128_MD5, TLS_KRB5_WITH_RC4_128_SHA, TLS_PSK_WITH_RC4_128_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT1024_WITH_RC4_56_SHA, TLS_RSA_PSK_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
jdk.certpath.disabledAlgorithms=MD2, RSA keySize < 1024

Be sure that there are no other jdk.certpath.disabledAlgorithms and jdk.tls.disabledAlgorithms lines active in that file. This will enable all TLS ciphers, disabling SSLv2. I keep SSLv3 online because there are still too many users and servers out in the wild that use SSLv3 and I am not enough of a hardliner to block them out.

Certificates.

Next on: Certificates. The fact that you are reading this article means, that it is not enough for you for things to just work somehow. You want them to work right. For that you do need a CA signed certificate that is recognized by everyone — so no self-signed certificates, please. If you are on a budget (read: you want it free) you want to look into StartSSL, an Israeli certificate authority that gives 1-year domain validated certificates out for free. I like them so much that I enrolled for their paid plan, a mere 60$ or so per year. In return you are not only supporting their work, but also eligible for organization validated 2-year certificates. As many as you like.

So first of, generate your private key, always do this local, never accept private keys from any certificate-authority or anyone else. And protect it with whatever you think your clients private data is worth to you:

openssl genrsa -out yourdomain.key 4096 -batch
Generating RSA private key, 4096 bit long modulus
............................++
....++
e is 65537 (0x10001)

Of course,  replace “yourdomain” with your actual domain name. Also be aware that 4096 bit is the absolute maximum of bits OpenJDK/OpenFire will accept. You will have a yourdomain.key file lying around. Now, create a certificate signing request to send to your certificate-authority of choice:

openssl req -new -key yourdomain.key -out yourdomain.csr -sha512
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]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:yourdomain.com
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Be sure to actually fill out “Common Name” (your domain name) and your email address. You will end up with a yourdomain.csr. Send the contents of this file to your ca –be sure to not send your key-file contents-, and they in return should send you a yourdomain.crt file, your certificate and a ca-certificate (needed to trust the chain of signage). Place all files in, say /etc/ssl on your jabber-server:

  • yourdomain.key
  • yourdomain.crt
  • certificate-authority.crt

The yourdomain.csr file can now be discarded.  I made this little bash script to whack everything together, this works in Debian:

#! /bin/bash
JavaDir="/usr/share/openfire/resources/security" 
PASS="changeit"
cert="yourdomain"
certdir="/etc/ssl"
tmp="/root"
ca="/etc/ssl/certificate-authority.crt"
 
test -e "${JavaDir}/truststore" && rm -f "${JavaDir}/truststore"
test -e "${JavaDir}/keystore" && rm -f "${JavaDir}/keystore"
 
/etc/init.d/openfire stop
cat "${certdir}/${cert}.crt" "${ca}" > ${tmp}/"combined.crt"
keytool -import -trustcacerts -storepass $PASS -alias "StartSSL Class 2" -file "${ca}" -keystore "${JavaDir}/truststore"
openssl pkcs12 -export -in "${tmp}/combined.crt" -inkey "${certdir}/${cert}.key" -out "${tmp}/${cert}.p12" -name "${cert}" -CAfile "${ca}" -passout pass:"${PASS}"
keytool -importkeystore -deststorepass "$PASS" -srcstorepass "$PASS" -destkeystore "${JavaDir}/keystore" -srckeystore "${tmp}/${cert}.p12" -srcstoretype PKCS12 -alias "${cert}"
chmod 640 "${JavaDir}/truststore" "${JavaDir}/keystore"
chown openfire:openfire "${JavaDir}/truststore" "${JavaDir}/keystore"
ls -lha "${JavaDir}" *store*
/etc/init.d/openfire start

This script deletes your current keystore and truststore (java containers for certificates) and imports your certificate-authorities ca file as well as your own certificate and private key. In the end it should restart OpenFire, leaving you with a A/A scored OpenFire Server.

Of course you do not need to use the above script. You can import the certificates and keys directly from within the web-interface, too. But for automation (puppet) it’s always nice to have a command line approach.

If you are in any need of further help, contact me.

Cheers!

Christian

Touched base with Linux back in 1995, got hooked up on it ever since. I am using Linux for both private and office for two decades. Working as a System Administrator at a medium sized hosting company I get in touch with all kinds of trouble. All of which can be solved with Linux. In my blog I am sharing solutions to problems that I had to search for myself in hope that someone else out there might find them useful.

13 thoughts to “OpenFire and Ciphers”

  1. Hi. I uncovered the blog page the use of bing. This is the wonderfully prepared document. Let me make sure you take note of it and return to find out more of this helpful tips. We appreciate you the actual article. I’ll undoubtedly comeback.

  2. Thanks for the good work!
    Its similar to others I tested, but none worked. 🙂
    Do you have any idea, why I always get ‘Unable to access certificate store. The keystore may be corrupt.’?
    keystore and truststore are definitly rw for openfire user and the commands executed successfully.

    1. The error most commonly occurs when you entered a wrong/incorrect password. It will try to decrypt the {key|trust}store file with the wrong password and will only yield garbage, hence the “keystore corrupt”. Even if you did not enter a Password there is one. “changeit” or “changeme”. 🙂

  3. Hm,
    I tried that and changed the password to ‘changeme’.
    But the the server doesn’t even start:
    ava.io.IOException: Keystore was tampered with, or password was incorrect
    So, ‘changeit’ might be correct.

    But now, the keystore and truststore are changed through the script (keytool -list shows my certificates), restarted, but the GUI still shows the default certificates. 🙁
    But the xmpp.socket.ssl.keystore properties shows to the correct file. Are there any other properties I have to set?

    Thanks for your help!

    1. If you changed the password then yes, there is a setting in Openfire you need to fix.
      Server -> Server Manager -> System Properities -> passwordKey

      Create that if it doesn’t exist and set the value to your password.

  4. I dont know, what it was, but I reinstalled everything (now the latest nightly) and now it worked.
    But I had to use the pem from ca and not the crt (its startssl).
    But now its secure! 🙂

    Thanks a lot!

  5. Nice, thanks for the script. Worked perfect although openfire restarted to the initial installation screen afterwards.

  6. If someone (such as myself) is wanting to preserve the old keystore/truststore instead of nuking them, the following lines should rename the existing files appending a timestamp instead of deleting it, otherwise fantastic thanks it annoys me using a self-generated certificate when services like letsencrypt are available:

    test -e “${JavaDir}/truststore” && mv “${JavaDir}/truststore” “${JavaDir}/truststore”.$(date “+%s”)
    test -e “${JavaDir}/keystore” && mv “${JavaDir}/keystore” “${JavaDir}/keystore”.$(date “+%s”)

Leave a Reply

Your email address will not be published. Required fields are marked *