I spent way too much time trying to configure the sip container to use
TLS and since there is absolutely nothing in the documentation I was
fumbling for quite some time. As it turns out, it was a simple
copy-paste error (and my original attempt actually did work) but even
so, some information of how to configure the container and how to
verify that it actually works would have been quite nice. Therefore, I
wrote the following "quickstart" and hopefully it will save time for
someone else. Please comment!
= Configuring TLS =
In order to configure TLS you will have to obtain a public/private
key, a X.509 certificate, add those to the Java keystore and
optionally add certificates from a known CA (certicate authority). The
entire process can be confusing but in order to get a basic setup for
testing purposes up and running with minimal effort, this section
starts off with a simple Quickstart. However, for production
environment you need to obtain an officially signed certificate from a
known CA and that process is outlined in section XXX.
== Quickstart – Server side authentication ==
This section shows how to create a self signed certificate, how to add
that to the Java keystore and how to configure the SIP Servlet
Container to make use of this configuration. Note, this section should
only be used in a development environment and the main reason for this
quickstart section is to get you going right away as well as get you
comfortable with generating keys and certificates and adding them to
the Java keystore.
At a high-level, we will execute the following three steps:
1. Generate a public/private key pair and a self signed certificate
and add those to the Java keystore.
2. Configure the SIP Servlet Container to load our certificate from
the keystore.
3. Test!
=== Step 1 – Generate certificate ===
Generating a new key-pair and a certificate can be done in a few
different ways with a few different tools but here we will just use
the java keytool that comes with the JDK. Simple issue the following
command, which will generate a new public and private key, generate a
self-signed certificate and add it all to the Java keystore:
keytool -genkeypair -alias myserver -keyalg RSA -keysize 1024 -keypass
secret -validity 365 -storetype jks -keystore myserver.jks -storepass
secret -v -dname "CN=James Smith, OU=Engineering, O=My Company, L=My
City, S=My State, C=US"
A few things to point out:
-keystore specifies which keystore we should use/update. If the
keystore doesn't exist, a new one will be created for one. In the
above example, we named the keystore “myserver.jks” and it will be
saved in the current directory
-keypass and -storepass should be chosen wisely since with bad
passwords you won't have much protection anyway. Also, normally you
should never passwords on the command prompt, it is too easy for other
people to steal. If you leave these two options out, the keytool
command will ask you for it.
-keyalg specifies which algorithm to use when generating the keys and
the keysize how long those keys should be.
Note: the command -genkeypair is new in JDK 6 and was previously named
-genkey. The keytool in JDK 6 has some improvements over the previous
versions so it is recommended to use it instead.
See more about the Java keytool here:
http://docs.oracle.com/javase/6/docs/technotes/tools/solaris/keytool.html
=== Step 2 – Configure the SIP Servlet Container ===
The SIP Servlet Container relies on the JAIN SIP stack to support it
with TLS capabilities. As such, it is the JAIN SIP stack that we need
to configure to have it read our certificate we added to the key
store. The various configuration options are described in the javadoc
of the SipStackImpl [link] class but for this quickstart, we will be
using the following ones:
javax.net.ssl.keyStore – the filename and location of the keystore to use.
javax.net.ssl.keyStorePassword – the password to the keystore.
gov.nist.javax.sip.TLS_CLIENT_AUTH_TYPE – which type of authentication
we will require of the client.
The configuration options are JVM parameters and you will have to add
these to the command line when you start the server:
./bin/run.sh -Djavax.net.ssl.keyStorePassword=mysecret
-Dgov.nist.javax.sip.TLS_CLIENT_AUTH_TYPE=Disabled
-Djavax.net.ssl.keyStore=/path/to/your/keystore/myserver.jks
Once the server is up, we are ready to verify that we can get a TLS
connection using the certificate we previously added in Step 1.
Note: for this first part of the quickstart we will not require a
certificate from the client since this involves more configuration.
This is controlled by the gov.nist.javax.sip.TLS_CLIENT_AUTH_TYPE
parameter.
=== Step 3 – Test! ===
To verify your setup there are a few different tools that you can use.
openssl is an open source SSL toolkit and contains a generic SSL/TLS test client
SIPp – an open source SIP load testing tool that is capable of using
TLS. However, it requires some additional steps that we have not
addressed in the first parf of this quickstart so therefore we willl
not be using SIPp.
Using your favorite SIP client. Most SIP clients out there are capable
of establishing a TLS connection but you will have to consult its
documentation of how to configure TLS.
Using openssl:
Assuming that your server is running on localhost and is listening for
TLS on port 5081 the command would be:
openssl s_client -host 127.0.0.1 -port 5081
If you are successful you should see an output from openssl displaying
information about the server certificate (which should be the one we
generated in Step 1). If there are any issues with the setup, openssl
is pretty good about giving out information about what it thinks is
wrong.
Tip: if you add the following JVM parameter as well you will get a lot
of useful debug information:
-Djavax.net.debug=ssl
== Quickstart – require client certificate ==
In the first quickstart we generated a public and private key along
with a self-signed certificate and added them all into the Java
keystore. The server was then configured to use this information and
when a client connected, our certificate was served up to the client.
However, normally, the client and the server would like to verify each
others certificate to make sure they both trust each other and if not,
either of them will terminate the connection. In the first part of the
quickstart, the server did not require the client to present a
certificate when connecting (remember that we set the
gov.nist.javax.sip.TLS_CLIENT_AUTH_TYPE to disabled) so let's do that
now.
At a high-level, these are the tasks we need to execute:
generate a public/private key pair for the client along with a certificate.
The server need to add the client certificate to its keystore as a
trusted certificate.
Start the server with client authenticating enabled.
=== Step 1 – Generate client certificate ===
We will use the Java keytool for this step in the same we did for for
the server side in the previous quikstart. The command is exactly the
same and the only difference is that we store the information in a new
keystore called “myclient.jks”.
keytool -genkeypair -alias myclient -keyalg RSA -keysize 1024 -keypass
secret -validity 365 -storetype jks -keystore myclient.jks -storepass
secret -v -dname "CN=John Doe, OU=Engineering, O=Some Work, L=Some
City, S=Some State, C=US"
We have now generated a new keystore containing the clients
authentication information. However, the server needs to import the
client certificate into its trusted keystore so we need to extract the
certificate out of the client key store. This can also be done using
the Java keytool.
keytool -exportcert -alias myclient -file client.cert -keystore
myclient.jks -storepass secret -rfc
The certificate is saved in file “client.cert” and we will use this
file in the next step.
=== Step 2 – add the client certificate to the server trust store ===
When the client connects to the server, the server can require that
the client presents a certificate of its own. If the certificate is
trusted, the client connection is accepted. In order to import a
trusted certificate use the keytook “importcert” command:
keytool -importcert -file client.cert -storepass secret -keystore
myserver.jks -trustcacerts
=== Step 3 – Re-configure the server ==
Simply change the gov.nist.javax.sip.TLS_CLIENT_AUTH_TYPE from
“Disabled” to “Enabled” and start the server again.
=== Step 4 – Test ===
We will once again use openssl to verify our setup but now that the
client will be forced to present a certificate as well, we do need the
certificate's private key as well. The private key is embedded into
the keystore and was generated when we issued the “kenkeypair”
keytool-command. Unfortunately, the keytool does not have an option
for exporting the private key so we will have to write a small java
program to extract it for us. Luckily, it is not a lot of code:
[http://stackoverflow.com/questions/150167/how-do-i-list-export-private-keys-from-a-keystore]
Simply compile it:
javac DumpPrivateKey.java
and then use it to extract the private key:
java DumpPrivateKey myclient.jks secret myclient > clientprivate.key
Now that we have the private key of the client we can use openssl to
verify the setup again:
openssl s_client -host 127.0.0.1 -port 5081 -cert client.cert
-certform PEM -key clientprivate.key
If all goes well you should successfully establish a connection and
openssl will dump information about the certificate exchange.
== Production setup ==
TODO
http://www.informit.com/articles/article.aspx?p=407886
http://docs.codehaus.org/display/JETTY/How+to+configure+SSL
/Jonas
--
Vilius Panevėžys
Elitnet
Once I have received some more feedback I'll spend some time
re-writing it to fit the language of the official documentation and if
anyone feel like helping out proof reading I would very much
appreciate it.
/Jonas
2012/1/23 Vilius Panevėžys <vil...@elitnet.lt>:
So, finally found some time to add another small section regarding
production setup and turn the whole thing into docbook etc. I have
been trying to follow the convention regarding listings, variable
names etc etc but I'm sure I missed something...
Also, Jean suggested to split out the previous section regarding SIP
Servlet Application Security and merge it with my TLS section and move
both of them into a chapter of their own, called Security, which is
what I have done. For easy read, I have attached the html version of
that chapter (along with the css but no images) to this email but you
will also find the patch attached
/Jonas
2012/1/23 Ibrahima Gaye <ibrahi...@gmail.com>:
If so, how is that done?
I need to talk to a Microsoft OCS/Lync server, and it requires all
communication to be TLS encrypted.
I previously asked about the same setup, where the topic were the NTLM
authentication. That is fairly trivial to do it seems. Setting up the
SipServlet container to initiate a connection inside TLS are
unfortunately not very easy to figure out.
Cheers
/Jonas