En esta parte usaremos una base de datos para registrar mediante una contraseña nuestros usuarios SIP dando un tanto mas de seguridad a nuestro pequeño sistema, y de tener en tablas todas las preferencias de nuestros usuarios, dominios, direcciones y grupos como veremos consecuentemente.
Partimos del hecho de que contamos con nuestra base de datos MySQl correctamente instalada y con nuestra contraseña de root configurada. Debemos realizar ciertas modificaciones al archivo opensipsctlrc (/usr/local/etc/opensips/opensipsctlrc), el cual debe quedar de la siguiente forma:
trantor:/usr/local/etc/opensips# cat opensipsctlrc | grep -v "#" | sed -e '/^$/d' SIP_DOMAIN=192.168.1.161 DBENGINE=MYSQL DBHOST=localhost DBNAME=opensips DBRWUSER=opensips DBRWPW="opensipsrw" DBROUSER=opensipsro DBROPW=opensipsro ALIASES_TYPE="DB" OSIPS_FIFO="/tmp/opensips_fifo" trantor:/home/gabriel#
Creamos la base de datos.
trantor:/home/gabriel/SIP# opensipsdbctl create MySQL password for root: INFO: test server charset INFO: creating database opensips ... INFO: Core OpenSIPS tables succesfully created. Install presence related tables? (y/n): y INFO: creating presence tables into opensips ... INFO: Presence tables succesfully created. Install tables for imc cpl siptrace domainpolicy carrierroute userblacklist? (y/n): y INFO: creating extra tables into opensips ... INFO: Extra tables succesfully created. trantor:/home/gabriel/SIP#
Cambiamos la configuración de opensips.cfg por la configuración que se muestra a continuación la cual simbólicamente denominaremos opensips.cfg.1.
####### Global Parameters ######### debug=3 log_stderror=no log_facility=LOG_LOCAL0 fork=yes children=4 port=5060 /* (default bind on all available) */ #listen=udp:192.168.1.161:5060 ####### Modules Section ######## #set module path mpath="/usr/local/lib/opensips/modules/" /* uncomment next line for MySQL DB support */ loadmodule "db_mysql.so" loadmodule "auth.so" loadmodule "auth_db.so" loadmodule "signaling.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.so" loadmodule "xlog.so" loadmodule "acc.so" # ----- mi_fifo params ----- modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo") modparam("rr", "enable_full_lr", 1) modparam("rr", "append_fromtag", 0) # ----- usrloc params ----- modparam("usrloc", "db_mode", 0) modparam("usrloc", "db_mode", 2) modparam("usrloc", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") # ----- uri params ----- modparam("uri", "use_uri_table", 0) # ----- acc params ----- /* what sepcial events should be accounted ? */ modparam("acc", "early_media", 1) modparam("acc", "report_ack", 1) modparam("acc", "report_cancels", 1) modparam("acc", "detect_direction", 0) modparam("acc", "failed_transaction_flag", 3) modparam("acc", "log_flag", 1) modparam("acc", "log_missed_flag", 2) modparam("acc", "db_flag", 1) modparam("acc", "db_missed_flag", 2) modparam("auth_db", "calculate_ha1", yes) modparam("auth_db", "password_column", "password") modparam("auth_db", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") modparam("auth_db", "load_credentials", "") route{ if (!mf_process_maxfwd_header("10")) { sl_send_reply("483","Too Many Hops"); exit; } if (has_totag()) { if (loose_route()) { if (is_method("BYE")) { setflag(1); # do accounting ... setflag(3); # ... even if the transaction fails } else if (is_method("INVITE")) { record_route(); } route(1); } else { if ( is_method("ACK") ) { if ( t_check_trans() ) { t_relay(); exit; } else { exit; } } sl_send_reply("404","Not here"); } exit; } if (is_method("CANCEL")) { if (t_check_trans()) t_relay(); exit; } t_check_trans(); if (!(method=="REGISTER") && from_uri==myself) { if (!proxy_authorize("", "subscriber")) { proxy_challenge("", "0"); exit; } if (!db_check_from()) { sl_send_reply("403","Forbidden auth ID"); exit; } consume_credentials(); # caller authenticated } if (loose_route()) { xlog("L_ERR", "Attempt to route with preloaded Route's [$fu/$tu/$ru/$ci]"); if (!is_method("ACK")) sl_send_reply("403","Preload Route denied"); exit; } # record routing if (!is_method("REGISTER|MESSAGE")) record_route(); # account only INVITEs if (is_method("INVITE")) { setflag(1); # do accounting } if (!uri==myself) { append_hf("P-hint: outboundrn"); route(1); } if (is_method("PUBLISH")) { sl_send_reply("503", "Service Unavailable"); exit; } if (is_method("REGISTER")) { if (!www_authorize("", "subscriber")) { www_challenge("", "0"); exit; } if (!db_check_to()) { sl_send_reply("403","Forbidden auth ID"); exit; } if (!save("location")) sl_reply_error(); exit; } if ($rU==NULL) { # request with no Username in RURI sl_send_reply("484","Address Incomplete"); exit; } # do lookup with method filtering if (!lookup("location","m")) { switch ($retcode) { case -1: case -3: t_newtran(); t_reply("404", "Not Found"); exit; case -2: sl_send_reply("405", "Method Not Allowed"); exit; } } # when routing via usrloc, log the missed calls also setflag(2); route(1); } route[1] { # for INVITEs enable some additional helper routes if (is_method("INVITE")) { t_on_branch("2"); t_on_reply("2"); t_on_failure("1"); } if (!t_relay()) { sl_reply_error(); }; exit; } branch_route[2] { xlog("new branch at $run"); } onreply_route[2] { xlog("incoming replyn"); } failure_route[1] { if (t_was_cancelled()) { exit; } }
Iniciamos OpenSIPS.
trantor:~# opensipsctl start INFO: Starting OpenSIPS : INFO: started (pid: 28716)
Agregamos el par de usuarios 1000 y 1001, a la base de datos y registramos nuestros agentes SIP.
gabriel@trantor:~$ sudo opensipsctl add 1000 1000 new user '1000' added gabriel@trantor:~$ sudo opensipsctl add 1001 1001 new user '1001' added
Mostramos la traza SIP del registro de un usuario almacenando previamente en nuestra base de datos.
U 192.168.1.162:5061 -> 192.168.1.161:5060 REGISTER sip:192.168.1.161 SIP/2.0. Via: SIP/2.0/UDP 192.168.1.162:5061;branch=z9hG4bK-6bdbbdbc. From: Bozada ;tag=ea98cc30d70f560fo1. To: Bozada . Call-ID: 5da1e386-fde63540@192.168.1.162. CSeq: 32475 REGISTER. Max-Forwards: 70. Contact: Bozada ;expires=3600. User-Agent: Linksys/SPA2102-3.3.6. Content-Length: 0. Allow: ACK, BYE, CANCEL, INFO, INVITE, NOTIFY, OPTIONS, REFER. Supported: x-sipura. . U 192.168.1.161:5060 -> 192.168.1.162:5061 SIP/2.0 401 Unauthorized. Via: SIP/2.0/UDP 192.168.1.162:5061;branch=z9hG4bK-6bdbbdbc. From: Bozada ;tag=ea98cc30d70f560fo1. To: Bozada ;tag=c97b4d1cb1f3d0da549e06a8d482ef63.be3a. Call-ID: 5da1e386-fde63540@192.168.1.162. CSeq: 32475 REGISTER. WWW-Authenticate: Digest realm="192.168.1.161", nonce="4b85d15b000000039d8eac02cb35f405c16770fd04ba2424". Server: OpenSIPS (1.6.1-notls (i386/linux)). Content-Length: 0. . U 192.168.1.162:5061 -> 192.168.1.161:5060 REGISTER sip:192.168.1.161 SIP/2.0. Via: SIP/2.0/UDP 192.168.1.162:5061;branch=z9hG4bK-896f8b1c. From: Bozada ;tag=ea98cc30d70f560fo1. To: Bozada . Call-ID: 5da1e386-fde63540@192.168.1.162. CSeq: 32476 REGISTER. Max-Forwards: 70. Authorization: Digest username="1000",realm="192.168.1.161",nonce="4b85d15b000000039d8eac02cb35f405c16770fd04ba2424",uri="sip:192.168.1.161",algorithm=MD5,response="5a8c46a3bd960218616aaed03240e631". Contact: Bozada ;expires=3600. User-Agent: Linksys/SPA2102-3.3.6. Content-Length: 0. Allow: ACK, BYE, CANCEL, INFO, INVITE, NOTIFY, OPTIONS, REFER. Supported: x-sipura. . U 192.168.1.161:5060 -> 192.168.1.162:5061 SIP/2.0 200 OK. Via: SIP/2.0/UDP 192.168.1.162:5061;branch=z9hG4bK-896f8b1c. From: Bozada ;tag=ea98cc30d70f560fo1. To: Bozada ;tag=c97b4d1cb1f3d0da549e06a8d482ef63.274d. Call-ID: 5da1e386-fde63540@192.168.1.162. CSeq: 32476 REGISTER. Contact: ;expires=3600. Server: OpenSIPS (1.6.1-notls (i386/linux)). Content-Length: 0. .
Y como un diagrama a veces vale mas, aquí mostramos la gráfica de la traza SIP anterior.
| 192.168.1.162 | 192.168.1.161 | Request: REGISTER | |(5061) ------------------> (5060) | | Status: 401 Unauthorized | |(5061) (5060) | | Status: 200 OK | |(5061) <------------------ (5060) |
Realizamos nuevamente una sencilla llamada del usuario 1001 al 1000, y esta es la traza SIP de la llamada, la principal diferencia respecto al esquema anterior, es la parte de la autentificación.
En este caso al realizar el INVITE de la llamada, el servidor responde con mensaje SIP 407 (autenticación requerida), nuestro agente SIP responde y si son correctos los parámetros dejara realizar el INVITE iniciando la llamada, el resto de la traza SIP es igual a la del post anterior.
| 192.168.1.163 | 192.168.1.161 (proxy) | 192.168.1.162 | INVITE SDP ( h261) | | |(5060) ------------------> (5060) | | | 407 Proxy Authentication Required | | |(5060) (5060) | | | INVITE SDP ( h261) | | |(5060) ------------------> (5060) | | | 100 Giving a try | | |(5060) (5061) | | | 100 Trying | | |(5060) <------------------ (5061) | | | 180 Ringing | | |(5060) <------------------ (5061) | | 180 Ringing | | |(5060) <------------------ (5060) | | | | 200 OK SDP ( h261) | | |(5060) <------------------ (5061) | | 200 OK SDP ( h261) | | |(5060) (5060) | | | | ACK | | |(5060) ------------------> (5061) | | BYE | | |(5060) ------------------> (5060) | | | | BYE | | |(5060) ------------------> (5061) | | | 200 OK | | |(5060) <------------------ (5061) | | 200 OK | | |(5060) <------------------ (5060) | |
Mediante el siguiente comando podemos observar a los usuarios registrados en el servidor.
trantor:~# opensipsctl ul show Domain:: location table=512 records=2 AOR:: 1000 Contact:: sip:1000@192.168.1.162:5061 Q= Expires:: 2336 Callid:: 5da1e386-fde63540@192.168.1.162 Cseq:: 32476 User-agent:: Linksys/SPA2102-3.3.6 State:: CS_SYNC Flags:: 0 Cflag:: 0 Socket:: udp:192.168.1.161:5060 Methods:: 5183 AOR:: 1001 Contact:: sip:1001@192.168.1.163:5060;transport=udp Q= Expires:: 3596 Callid:: d35fe6bb7fc5df8b6c76521a80310ba6@0.0.0.0 Cseq:: 2 User-agent:: SIP Communicator 1.0 CVS-Wed_Feb_24_19-45-25_CST_2010 State:: CS_NEW Flags:: 0 Cflag:: 0 Socket:: udp:192.168.1.161:5060 Methods:: 4294967295