...
User Agent A -> proxy domainA
Prerequisites
...
This example is based on
- Debian 4r0
- OpenSER version 1.2 with tls
...
- If TLS support is not included in your installation, get OpenSER 1.2 with TLS. This example uses the source code at
http://www.openser.org/pub/openser/latest/src/openser-1.2.0-tls_src.tar.gz - Carefully observe the installation notes:
http://www.openser.org/mos/view/-OpenSER-Installation-Notes/ - Special care should be taken to install the packages:
- mysql-server
- libmysqlclient-dev
- libssl0.9.8-dev
- Make sure you build openser including TLS. There are several options, like changing the line in the makefile to the following:
TLS=1
and that you include mysql support:
make all include_modules="mysql"
make install - note that the compiled version puts openser in different directory compared to the openser package. The config file is in
/usr/local/etc/openser/openser.cfg
and the modules are in
/usr/local/lib/openser/modules
and the certificate information is in
/usr/local/etc/openser/tls/user - run mysqldb.sh to create the database
- add add the certificate chain of the other proxy in PEM domainA and domainB in PEM format to the CA list file in
/usr/local/etc/openser/user/user-calist.pem.
You can open the file in a text editor and add the certificate string at the end of the file. - add routing logic in the openser.cfg file:
...
- put the private key and public key of the server certificate in
/usr/local/etc/openser/tls/user/user_privkey.pem and
/usr/local/etc/openser/tls/user/user_cert.pem
(you're free to choose file names and locations, these are the config defaults)
This example config shows the necessary minimal elements:
No Format |
---|
\# \----------\- global configuration parameters \-----------------------\-
debug=3 # debug level (cmd line: \-dddddddddd)
fork=yes
log_stderror=no # (cmd line: \-E)
children=4
sip_warning=yes
\# disable these if you do not allow UDP. UDP is obligatory
\# in the SIP RFC
listen=<sip server IP address>
port=5060
disable_tls = 0
listen = tls:<sip server IP address>:5061
tls_verify_server = 1
tls_verify_client = 1
tls_require_client_certificate = 0
tls_method = TLSv1
tls_certificate = "/usr/local/etc/openser/tls/user/user-cert.pem"
tls_private_key = "/usr/local/etc/openser/tls/user/user-privkey.pem"
tls_ca_list = "/usr/local/etc/openser/tls/user/user-calist.pem"
alias="<sip server domain name: domainA.net"
mpath="/usr/local/lib/openser/modules/"
loadmodule "mysql.so"
loadmodule "sl.so"
loadmodule "tm.so"
loadmodule "rr.so"
loadmodule "maxfwd.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
loadmodule "textops.so"
loadmodule "mi_fifo.so"
loadmodule "uri_db.so"
loadmodule "auth.so"
loadmodule "auth_db.so"
loadmodule "xlog.so"
\# \----------------\- setting module-specific parameters \--------------\-
modparam("mi_fifo", "fifo_name", "/tmp/openser_fifo")
\# change the read-write mysql account password and adjust this line:
modparam("usrloc", "db_mode", 2)
modparam("usrloc", "db_url", "mysql://openser:openserrw@localhost/openser")
\# change the read-only mysql account password and adjust this line:
modparam("auth_db", "db_url", "mysql://openserro:openserro@localhost/openser")
modparam("auth_db", "calculate_ha1", yes)
modparam("auth_db", "password_column", "password")
modparam("rr", "enable_full_lr", 1)
\# \------------------------- request routing logic \------------------\-
\# main routing logic
route{
# initial sanity checks \-\- messages with
# max_forwards==0, or excessively long requests
if (\!mf_process_maxfwd_header("10")) {
sl_send_reply("483","Too Many Hops");
exit;
};
if (msg:len >= 2048 ) {
sl_send_reply("513", "Message too big");
exit;
};
# if somene claims to belong to our domain in From,
# challenge him (skip REGISTERs \-\- we will chalenge them later)
if (from_uri==myself) {
setflag(1);
if ( (method=="INVITE" \|\| method=="SUBSCRIBE" \|\| method=="MESSAGE")
&& \!(src_ip==myself) ) {
if (\!(proxy_authorize("domainA", "subscriber" ))) {
proxy_challenge("domainA","0"/*no-qop*/);
exit;
};
if (\!check_from()) {
log("LOG: From Cheating attempt in INVITE\n");
sl_send_reply("403",
"That is ugly \-\- use From=id next time (OB)");
exit;
};
};
}
else if ( method=="INVITE" && uri\!=myself ) {
sl_send_reply("403", "No relaying");
exit;
};
# we record-route all messages \-\- to make sure that
# subsequent messages will go through our proxy; that's
# particularly good if upstream and downstream entities
# use different transport protocol
if (\!method=="REGISTER")
record_route();
# subsequent messages withing a dialog should take the
# path determined by record-routing
if (loose_route()) {
# mark routing logic in request
append_hf("P-hint: rr-enforced\r\n");
route(1);
};
# check for requests targeted out of our domain
if (\!uri==myself) {
# mark routing logic in request
append_hf("P-hint: outbound\r\n");
# if you have some interdomain connections via TLS
if(uri=~"@sipx1.ces.net") {
t_relay("tls:sipx1.ces.net:5061");
xlog("L_INFO", "Time \[%Tf\] Route to ces.net :%rm RURI:%ru FROM:%fu TO:%tu \n buffer %mb \n flags \n %mf \n");
exit;
} else if(uri=~"@sipx.ten.cz") { t_relay("tls:sipx.ten.cz:5061");
xlog("L_INFO", "Time \[%Tf\] Route to ten.cz :%rm
RURI:%ru FROM:%fu TO:%tu \n buffer %mb \n flags \n
%mf \n"); exit;
}
route(1);
};
# if the request is for other domain use UsrLoc
# (in case, it does not work, use the following command
# with proper names and addresses in it)
if (uri==myself) {
if (method=="REGISTER") {
# digest authentication
if (\!www_authorize("domainA", "subscriber")) {
www_challenge("domainA", "0");
exit;
};
save("location");
exit;
};
lookup("aliases");
if (\!uri==myself) {
append_hf("P-hint: outbound alias\r\n");
route(1);
};
};
route(1)
}
route\[1\] {
if (\!t_relay()) {
sl_reply_error();
};
exit;
}
|
Test
Make sure that the certificate chain (CA list) is installed on the UA. For instance, when using Eyebeam 1.5 under MS Windows, import the chain (in PEM format with file extension .cer) into the windows certificate store by double clicking.
...
- Invalid TLS version: though TLS 1.0 should be used according to the SIP RFC, TLS 2/3 is supported by both proxies and UAs
- Client certificate verification should be disabled
- CA certificate cannot be verified: make sure the correct chain is on the server and on the UA
- Common name of the server certificate does not match DNS name of the server
...
Reminder: this example is based on a compiled version of openSER where the config is in /usr/local/etc/openser and the certificates are in /usr/local/etc/openser/tls/user, which might differ when installed from packages.
This recipe is based on the tutorial in http://www.voipuser.org/forum_topic_7222.html with adjustments for the openser version. See also http://www.openser.org/docs/tls.html#TLS-EXAMPLE for hints on TLS and examples of how to differentiate ring tones of the UA based on the source of a call to let the end-user know if the call can be trusted or not.