Modifying Freeswitch’s XML interfaces to support custom SSL client + server certificates

As you can see from the previous post, there was a lot of work left to be done in order to secure communications between Freeswitch’s XML interfaces and our web servers. I researched the other possible security options with libcurl using https, as well as SSL encryption options in general. Libcurl already supported a bunch of different SSL certificate options that were not being used in Freeswitch, presumably because nobody had ever cared enough to implement them before.

It seemed that the most secure setup possible was to implement client & server SSL certificate authentication (both ends check each other’s certs). I used this resource as an introduction to Client Authentication with SSL. This guide also explained how to become your own certificate authority and sign your own client + server certificates. Becoming our own CA is perfect for our setup because, unlike a browser scenario, libcurl wouldn’t be popping up a message telling our users that we are an untrusted/unofficial CA.

The first thing to do was to modify Freeswitch to support the various SSL options that libcurl provides. It wasn’t actually very difficult to accomplish this. Mod_xml_curl is a concise piece of code (~450 lines) so I studied it over for a while to figure out how the existing options were set using the XML config.

I changed the option ‘ignore-cacert-check’ to ‘enable-cacert-check’. Since the checks were already disabled by default in the module, I am not changing the default behavior and instead providing an option for those who want that extra security. When this new option is set to true, libcurl will check to make sure that the web server’s certificate is authorized by one of the big public CAs (or whichever CA cert we supply it manually). I also added the following options to mod_xml_curl:

  1. ’ssl-cert-path’ provides the path of the client’s public SSL certificate, which it sends to the web server during the handshake.
  2. ’ssl-key-path’ gives the path of the client’s private SSL key, which it uses to decode information coming back from the web server (must be kept PRIVATE!).
  3. ’ssl-key-password’ gives the plaintext password of the client’s private SSL key that was chosen when the key was generated. In this case, the password doesn’t provide much extra security since if an intruder can access the private key file they can also access the password now stored in your Freeswitch config files.
  4. ’ssl-version’ is an optional parameter that allows you to specify which verison of the SSL protocol must be used during communication. Accepted values are ‘SSLv3′ and ‘TLSv1′. Version 2 of SSL is not secure and is disabled by default in libcurl. Not setting this option will allow either SSLv3 or TLSv1 to be used.
  5. ’ssl-cacert-file’ should give the path of a file containing the web server’s CA certificate and is only required if you are acting as your own CA instead of paying for one of the public CAs.
  6. ‘enable-ssl-verifyhost’ should be set to true to override the default behavior of mod_xml_curl, which is to ignore whether or not the hostname on the server’s cert matches the hostname of the server.

I’ve submitted patches for both mod_xml_curl and mod_xml_cdr to implement these changes, so hopefully you’ll see them show up in an upcoming build of Freeswitch!

I may cover implementation of these details on a Ruby webserver in the future, but for now you should reference the following article: SSL Client Certificate Authentication in Ruby on Rails

FUCKED