source article: http://www.cesnet.cz/doc/techzpravy/2007/tls-sip-server/#Mat06
CESNET technical report number 13/2007
also available in PDF, PostScript, and XML formats.
Jan Růžička
27.11.2007
1 Abstract
In this report we describe the setup of Transport Layer Security (TLS) in two major open source SIP servers (SER, OpenSer), which are used in the CESNET IP telephony network.
Keywords: security, SIP, TLS
2 Introduction
Today, most SIP [Ros02] IP telephony networks use UDP rather than TCP as a transport protocol. SIP authentication is carried by HTTP Digest mechanism and it is used for both user-to-proxy(or registrar) and proxy-to-proxy (interdomain) authentication. This mechanism is quite weak especially when used in open networks and there are many tools that can obtain a password from the intercepted communication. One way to protect signalling as well as credentials and to obtain additional authentication mechanism is to introduce TLS.
3 Prerequisites
There are several prerequisites that we have to meet before we can start configuring and testing TLS-enabled scenario. First, we need to install servers, configure DNS and obtain certificates. Then we can configure the servers and also test the clients. Figure shows the applied scenario.
3.1 SIP Server
The OpenSER project split from SER as a separate project. Although the two projects have a lot in common, they don't have exactly the same functionality, in particular as regards configuration file compatibility. Both servers usually run in the Linux environment. Hardware requirements to run the server are not high even in the production service. It is therefore more than suitable to run the test servers on virtual machines (i.e. Vmware or XEN). We skip the OS installation phase as it is well known. But be careful when using it on a larger scale, you might need to tune your system up to handle a large amount of persistent TLS connections (the same applies to plain TCP).
To install the SIP servers we can either use packages, if available, or compile them from the source code. Packages for selected distributions can be obtained either directly in distribution, from the producers of the software, for example Fedora packages, or in third-party repositories such as CESNET apt repository (see our wiki). It is necessary to use Openser 1.2. and SER 2.x.
In the case of SER you should check whether TLS is compiled in by running ser -V command and check whether tls module (tls.so) is located in the module directory (depends on distribution and package, e.g., /usr/local/lib/ser/modules):
ser -V version: ser 2.1.0-dev13 (i386/linux) flags: STATS: Off, USE_IPV6, USE_TCP, USE_TLS ......
The same can be done for OpenSer. TLS functionality is built directly into its core but you should check for the presence of tls_ops module.
openser -V version: openser 1.2.0-tls (i386/linux) flags: STATS: Off, USE_IPV6, USE_TCP, USE_TLS ......
Otherwise you have to compile the server from source code which you can easily download from the server website or via CVS. Be sure that you also install the openssl developer package if you want to compile the source.
In SER you can adjust compiled modules by using group_include
, include_modules
and exclude_modules
parameters for make. Parameter print-modules
shows a set of modules that will be compiled.
make group_include="standard" include_modules="tls" print-modules
To compile and install the sip server you should run:
make group_include="standard" include_modules="tls" all make group_include="standard" include_modules="tls" install
This will install a minimal feature set (without MySQL database and many others) to the /usr/local/ directory.
For OpenSER you need to set the make parameter TLS=1
and include tls_ops module. Now we have installed the servers and can proceed to DNS configuration.
3.2 DNS
Besides the common A and reverse record we need to setup SRV and NAPTR [RS02] records. According to the SIP RFC [Ros02], a server should support at least TCP and UDP which are by default listening on port 5060. We will also use SIP over TLS which listens usually on port 5061. SRV records allow to present service points (IP address and port) for selected service in selected domain. The example below shows a simple setup of the SIP service records for domain ten.cz:
_sip._udp.ten.cz IN SRV 100 1 5060 sipx.ten.cz. _sip._tcp.ten.cz IN SRV 100 1 5060 sipx.ten.cz. _sips._tcp.ten.cz IN SRV 100 1 5061 sipx.ten.cz.
SRV records cannot express any preference between services and transport protocols within service. The caller side picks the records according to their (remote) preference. If we want, according to [RS02], to define that TLS has the highest priority, followed by TCP and then UDP, we need to setup NAPTR records for ten.cz domain as follows:
IN NAPTR record 100 0 "s" "SIPS+D2T" "" _sips._tcp.ten.cz. IN NAPTR record 200 0 "s" "SIP+D2T" "" _sip._tcp.ten.cz. IN NAPTR record 300 0 "s" "SIP+D2U" "" _sip._udp.ten.cz.
You can see SRVs on the right side of the NAPTR records. The NAPTR records instruct the caller side in which order SRV (protocol and transport) should be used. Both NAPTR and SRV are not limited to IP telephony but can be used for any other service. To be able to understand SRV functionality better , you can imagine it as an extension of MX records used for mail service.
The first version of SER able to query NAPTR records is 2.1 (developer version) and it must be explicitly enabled (see the configuration section). On the other hand, OpenSER uses NAPTR automatically in stable version 1.2 and it even has a domain policy module that extends the usage of NAPTR to express peering policies. You may see sip and sips in SRV and NAPTR records. Sips stands for sip over tls. When resolving destination for sips uri only NAPTRs with sips in the service field can be taken. When resolving sip uri, both sip and sips NAPTRs can be used and if both sides supports TLS, transport can moved from UDP or TCP to TLS and thus security increases. Keep in mind that TLS works in a hop-by-hop manner so there isn't end-to-end signaling encryption and some hops can be even transported over TCP or UDP even if first hops are transported over TLS.
3.3 Certificates
To be able to use TLS, we need to have certificates at least for SIP servers. You can get them either from well known CA like Verisign, or your home CA like CESNET CA, or you can even use self-signed certificates. It is not recommended to use self-signed certificated for production service. There are many "HOWTOs" on the Internet which explain how to create a self-signed certificate, for example [Mat06]. For our test servers, we generated one self-signed certificate and got another one from CESNET CA.
3.4 Clients
To test User Agent (SIP client) TLS connection to the SIP server you need to find TLS enabled clients. We must admit that there are not many, but the situation is getting better. And even those which support TLS are rarely able to use client certificates. This means that TLS will be used to encrypt the connection and verify the server. For the test we chose Counterpath Eyebeam 1.5 Enhanced for Windows. The Client can be easily set up and can provide some debug logs. You should also upload CA certificate or a self-signed server certificate to the system certificate storage. The client cannot use the client certificate so the authentication will be carried by HTTP Digest. Even if the Client could use the client certificates, SIP servers are not easily ready to use them for SIP authentication on a larger scale. It seems that manufacturers do not plan to include any client certificate support.
4 Configuration
We suppose that readers are familiar with the basic SIP server configuration and therefore only focus on the part related to TLS. In any case, many hints can be found at OpenSER and SER project web pages. Before you start configuring the server you should prepare the server certificate, server key and CA list in the PEM format. CA list is a list of trusted entities that will be used to validate the incoming session. You get the CA list simply by concatenating the desired CA or server certificates. Please note that openssl used in both SIP servers requires a full certificate chain. This may cause problems for example if the opposite side has a SureServer EDU certificate (with SureServer EDU root) obtained from GlobalSign. But there is a GlobalSign root above the SureServer EDU root. Then you also need to insert GlobalSign root certificate into the CA list certificates obtained directly from GlobalSign will also be regarded as trusted.
Now let's discuss SER configurations and show differences in OpenSER. First you should enable TLS, define the address and port where TLS will be listening and load the TLS module.
# ------ global configuration parameters ------------ enable_tls=yes listen=tls:1.2.3.4:5061 # --------- module loading ----------------- loadmodule "/usr/local/lib/ser/modules/tls.so"
To enable NAPTR queries you need to set parameter and define preference (valid only for SER).
# ------ global configuration parameters ------------ dns_try_naptr=1 dns_tls_pref=3 dns_tcp_pref=2 dns_udp_pref=1 Then you should set TLS module parameters: # --------- setting module-specific parameters -------- modparam("tls", "private_key", "/etc/certs/key.pem") modparam("tls", "certificate", "/etc/certs/cert.pem") modparam("tls", "ca_list", "/etc/certs/ca_list.pem") modparam("tls", "require_certificate", 0) modparam("tls", "verify_certificate", 1) modparam("tls", "tls_method", "TLSv1") #modparam("tls", "tls_method", "SSLv23") modparam("tls", "tls_log", 2) modparam("tls", "handshake_timeout", 10) modparam("tls", "send_timeout", 10)
Parameter tls_log
is a separate control for TLS logging. If it is set to a lower value than debug, the TLS logs are printed even if common logs are suppressed. TLSv1 is RFC3261-compliant setting from tls_method
but SSLv23 is better for its extended compatibility. If you are sure that your neighbours are set to TLSv1, use TLSv1. TLSv1 client can make connection to a SSLv23 server but a SSLv23 client cannot talk to a TLSv1 server. Eyebeam is TLSv1 capable but Linksys SPA 942 needs SSLv23. Don't forget that a new TLS connection from the opposite site can be established during the call, for example if BYE is sent from callee side. Therefore it might be useful to have several TLS points. Unfortunately SIP servers are not able to work with revocation lists.
Verification options are set through require_certificate and verify_certificate parameters.
-
Require=0 and Verify=0 is the weakest setting which provides just an encrypted tunnel (if cipher is not NULL).
-
Require=0 and Verify=1 - if TLS client provides a certificate, it is verified. This setting allows your sip client to talk to SER without client certificate and in the same time to verify those who present the certificate.
-
Require=1 and Verify=1 is the strongest setting that forces the TLS client to provide a client certificate. If it is not provided, the connection fails.
A great deal of information, including the verification status, is written into @tls select (select framework allows to register module functions that can extract information from SIP messages, transports or IP datagrams and work with that information easily). See SER tls module documentation. The information can be easily queried and compared to gain additional functionality, for example comparing peer certificate common name stored in @tls.peer or dns name o SubjAtlName stored in @tls.peer.host.
By means of the @tls select, you can for example authenticate clients with a client certificate. To make it happen on a larger scale you will need mapping between CN (or some other attribute) and SER UID. @tls.peer.verified is very useful together with Require=0 and Verify=1 setting. You can check if the TLS client presented its certificate and whether it was verified and adjust to this for example the ringing tone to alert the user.
if (proto == TLS) { if (!@tls.peer.verified) { xlog("L_INFO","TLS Method: %rm RURI: %ru verified"); append_hf("Alert-info: http://sip.ces.net/tls.wav/r/n"); else { xlog("L_INFO","TLS Method: %rm RURI: %ru NOT verified"); } }
OpenSER configurations express the same idea by means of slightly different commands:
disable_tls = 0 listen = tls:1.2.3.4:5061 tls_verify_server = 1 tls_verify_client = 1 tls_require_client_certificate = 0 tls_method = TLSv1 tls_private_key = "/etc/certs/key.pem" tls_certificate = "/etc/certs/cert.pem" tls_ca_list = "/etc/certs/ca_list.pem"
You should also load a tls_ops module to gain similar functionality as provided by SER tls module ($tls
pseudo variables).
loadmodule "/usr/local/lib/openser/modules/tlsops.so"
Both SIP servers allow setting a different set of parameters depending on the listening port (server side) or target domain (client side). This can help to provide hosted solutions or to set different parameters for predefined partners.
Request routing can be done either automatically (NAPTR,SRV) by using the command t_relay() without parameters or by target specification as shown below (for SER):
# route domainB over TLS SER if (uri= ".*@ten.cz") { if (t_relay_to_tls("sip.ten.cz","5061")) { xlog("L_INFO","TLS DomainB Method: %rm RURI: /n "); } else {sl_reply_error();} break; }
The OpenSER part could differ in t_relay
part where
t_relay("tls:sipx.ten.cz:5061")
can be used. Actually t_relay_to_tls
is internally using t_relay
function and I like the OpenSER's availability to set transport protocols as a parameter of t_relay
. OpenSER uses function is_peer_verified instead of @tls.peer.verified in SER.
Both servers have extensive ways how to log information through syslog using xlog module as seen in this example:
command
xlog("L_INFO","TLS Method: %rm RURI: %ru, / TLSmy: %@tls.my.subject TLSpeer: %@tls.peer.subject / %@tls.peer.issuer verified: %@tls.peer.verified/n");
result
Nov 27 19:44:16 sipx ser[26204]: Recieved TLS Method: INVITE RURI: sip:99@ten.cz, TLSmy: sipx.ten.cz TLSpeer: sipx1.ces.net sipx1.ces.net Apr 22 08:10:31 2017 GMT verified: 1
5 Tests
First we try the connection between the Eyebeam SIP client and the SIP server. Ensure that you configure TLS as a transport protocol in account properties - security - signalling transport. Then let the client register. In the server log you can see something like the following:
LOG
Nov 27 17:59:18 sipx ser[21430]: tls_accept: new connection from 195.113.134.234:1386 using TLSv1/SSLv3 AES256-SHA 256 Nov 27 17:59:18 sipx ser[21430]: tls_accept: local socket:195.113.222.28:5061 Nov 27 17:59:18 sipx ser[21430]: tls_accept: client did not present a certificate Nov 27 17:59:18 sipx ser[21430]: Recieved TLS Method: REGISTER RURI: sip:ten.cz, TLSmy: sipx.ten.cz TLSpeer: verified: 0
netstat
tcp 0 0 195.113.222.28:5061 195.113.134.234:1386 ESTABLISHED 21431/ser
Above you see that the client didn't present the certificate but because we set require parameter to 0, connection was accepted. You can also see the established connection by using netstat command. It might also be useful to run wire shark at one of the sites to see not only SIP but also DNS communication. In the Eyebeam log below you can see successful handshake and client will show Ready status on the display if underlying digest authentication is OK.
EYEBEAM successful connection
[07-11-27]18:03:51.450 | Info | RESIP:TRANSPORT | "TLS connected" | [07-11-27]18:03:51.450 | Info | RESIP:TRANSPORT | "TLS sessions set up with TLSv1 TLSv1/SSLv3 AES256-SHA " | [07-11-27]18:03:51.450 | Debug | RESIP | "Found common name in cert of sipx.ten.cz" | [07-11-27]18:03:51.450 | Info | RESIP | "subjectAltName of TLS session cert contains DNS <sipx.ten.cz>" | [07-11-27]18:03:51.451 | Info | RESIP:TRANSPORT | "TLS handshake done for peer sipx.ten.cz" |
In case you for example forgot to store CA certificate in the system Eyebeam log shows the failure and the client will present it on the display as seen in Figure.
EYEBEAM unsuccessful connection
[07-11-27]18:12:06.222 | Debug | RESIP:TRANSPORT | "Trying to form TLS connection - acting as client" | [07-11-27]18:12:06.223 | Info | RESIP:TRANSPORT | "TLS handshake starting (client mode)" | [07-11-27]18:12:06.226 | Debug | RESIP:TRANSPORT | "TcpBaseTransport::processSomeReads() CONN: 02C76D10 1728 [ V4 195.113.222.28:5061 TLS target domain=sipx.ten.cz received on: Transport: [ V4 0.0.0.0:64868 TLS target domain=unspecified connectionId=0 ] connectionId=12 ]" | [07-11-27]18:12:06.227 | Error | RESIP | "Error when verifying server's chain of certificates: self signed certificate in certificate chain, depth=1 /DC=cz/DC=cesnet-ca/CN=CESNET CA" | [07-11-27]18:12:06.228 | Error | RESIP:TRANSPORT | "TLS handshake failed "| [07-11-27]18:12:06.228 | Error | RESIP:TRANSPORT | "error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed" |
Now we connect two SIP servers using TLS. As mentioned above, the SIP server can act as a TLS client and a TLS server during the same call. Configure the rewriting and routing manually or try to use NAPTR (t_relay without parameter). Register clients on both servers or use some automatic responder as Asterisk Echo test and try the call. In the log of the observed server (calee side) you can see information about incoming TLS connection and in the last line you can also see the successful verification flag. The observed SIP server is now acting as a TLS server.
TLS SERVER
Nov 27 19:44:16 sipx ser[26204]: tls_accept: new connection from 195.113.222.26:57090 using TLSv1/SSLv3 AES256-SHA 256 Nov 27 19:44:16 sipx ser[26204]: tls_accept: local socket: 195.113.222.28:5061 Nov 27 19:44:16 sipx ser[26204]: tls_accept: client certificate subject:/C=CZ/ST=Prague/L=Prague/O=CESNET SIP/OU=SIP Test/CN=sipx1.ces.net/emailAddress=janru@cesnet.cz Nov 27 19:44:16 sipx ser[26204]: tls_accept: client certificate issuer:/C=CZ/ST=Prague/L=Prague/O=CESNET SIP/OU=SIP Test/CN=sipx1.ces.net/emailAddress=janru@cesnet.cz Nov 27 19:44:16 sipx ser[26204]: Recieved TLS Method: INVITE RURI: sip:99@ten.cz, TLSmy : sipx.ten.cz TLSpeer : sipx1.ces.net sipx1.ces.net Apr 22 08:10:31 2017 GMT verified: 1
Now the call was connected and after some time the opposite site wants to terminate the call. So it sends BYE request and the observed SIP server is acting as a TLS client.
TLS CLIENT
Nov 27 20:06:23 sipx ser[26311]: tls_connect: new connection to 195.113.222.26:5061 using TLSv1/SSLv3 AES256-SHA 256 Nov 27 20:06:23 sipx ser[26311]: tls_connect: sending socket: 195.113.222.28:59653 Nov 27 20:06:23 sipx ser[26311]: tls_connect: server certificate subject:/C=CZ/ST=Prague/L=Prague/O=CESNET SIP/OU=SIP Test/CN=sipx1.ces.net/emailAddress=janru@cesnet.cz Nov 27 20:06:23 sipx ser[26311]: tls_connect: server certificate issuer:/C=CZ/ST=Prague/L=Prague/O=CESNET SIP/OU=SIP Test/CN=sipx1.ces.net/emailAddress=janru@cesnet.cz
If in trouble, you can see lines like the one below in your log, which indicates that either you don't have the CA certificate of the opposite site in your CA list or that the setting of tls_method of the two parties is incompatible.
Nov 27 15:55:40 sipx ser[15335]: ERROR: tls_server.c:381: SSL error:error:14094418:SSL routines:SSL3_READ_BYTES: tlsv1 alert unknown ca Nov 27 21:13:01 sipx ser[15335]: ERROR: tls_server.c:381: SSL error:error:1408F10B:SSL routines:SSL3_GET_RECORD: wrong version number
For the purpose of testing, cipher (tls_cipher_list
) could be set to NULL which means that no encryption will be used.
6 Conclusion
We demonstrated the configuration and test cases of SIP communication using TLS. We should remind that TLS works in a hop-by-hop manner and SIP clients usually don't have client certificates. This means that mutual verification is not possible. Also for inter-server communication where mutual verification is expected, it might be useful to have security and integrity mechanism contained in the SIP directly. Such mechanisms are outlined in SIP identity RFC [PJ06] and sip-saml draft [Tsc07]. But even those require that the first hop (from the client to the home SIP server) be secured by TLS. Presumably, it will take some time before these mechanisms can be tested. Until then, TLS presents an acceptable solution. Taking into account that the most common case is that only two proxies (caller and callee) are involved and they do not act as open relays, TLS seems to be a viable solution.
References
[Mat06] | Mates J.: OpenSSL Self-signed Test Certificates. Available online, 2006. |
[PJ06] | Peterson J., Jennings C.: Enhancements for Authenticated Identity Management in the Session Initiation Protocol (SIP). RFC 4474, IETF, 2006. |
[Ros02] | Rosenberg J. et al.: SIP: Session Initiation Protocol. RFC 3261, IETF, 2002. |
[RS02] | Rosenberg J., Schulzrinne H.: Session Initiation Protocol (SIP): Locating SIP Servers. RFC 3264, IETF, 2002. |
[Tsc07] | Tschofenig H. et al. SIP SAML Profile and Binding. Internet draft draft-ietf-sip-saml-03.txt, IETF, 2007. Work in progress. |