Autenticación en OpenSIPS con MySQL

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

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: