[SR-Users-ES] Sin Audio con llamadas a PSTN con caller detras de NAT, audio correcto entre usuarios detras de NAT con VoIP pura

rubenrojas - Trc.es rubenrojas en trc.es
Lun Dic 14 17:05:15 CET 2009


Buenos días,

Tenia aparcado este proyecto y lo he vuelto a retomar,
Creo que he conseguido la razón de la falta de audio pero aun no consigo la solución,
por lo que veo el cuando voy a reenviar al Asterisk desde el Proxy el "Contact" no tiene puerto
¿Como puedo agregarle el puerto al "Contact"?

Esto es lo que sucede:
CLIENTE_DETRAS_DE_NAT -> PROXY ====> INVITE Contact sip:30000000 en 192.168.254.121:5060
PROXY -> PSTN ====> INVITE Contact sip:30000000 en 212.4.97.115:43433
PSTN -> PROXY ====> Session Progress Contact sip:91XXXXXXX en 192.168.1.231
PROXY -> CLIENTE_DETRAS_DE_NAT ====>  Session Progress Contact sip:91XXXXXXX en 192.168.1.231
PSTN -> PROXY ====> 200 OK Contact sip:91XXXXXXX en 192.168.1.231
PROXY -> CLIENTE_DETRAS_DE_NAT ====> 200 OK Contact sip:91XXXXXXX en 192.168.1.231

el 192.168.254.121 es mi CLIENTE_DETRAS_DE_NAT
el 212.4.97.115 es la dirección publica de mi cliente
el 192.168.1.231 es mi Asterisk

he intentado colocar el puerto sin exito con:

rewritehostport("192.168.1.231:5060");
 y 
t_relay("udp:192.168.1.231:5060");

muchas gracias de antemano


----- Mensaje original -----
De: "rubenrojas - Trc.es" <rubenrojas en trc.es>
Para: sr-users-es en lists.sip-router.org
Enviados: Miércoles, 1 de Julio de 2009 11:20:51 GMT +01:00 Amsterdam / Berlín / Berna / Roma / Estocolmo / Viena
Asunto: [SR-Users-ES] Sin Audio con llamadas a PSTN con caller detras de NAT, audio correcto entre usuarios detras de NAT con VoIP pura

Buenos días,
ya la semana pasada me ayudaron a lograr que el audio funcionara bien mediante el RTPProxy cuando ambos usuarios se encontraban detrás de una NAT y registrando el Contact con IPs locales y el Received con la IP Publica y el puerto de NAT

Lo que vengo a preguntar hoy es la evolución de dicho problema, ahora las llamadas a PSTN no tienen audio cuando el usuario que llama esta detras de una NAT y no puede registrarse con su IP Pública en el Contact.

estoy utilizando el modulo dispatcher para realizar roundrobin entre dos asterisk (192.168.1.230 y 192.168.1.231), esto va perfecto cuando la llamada viene desde un telefono SIP con IP Publica y la llamada no tiene audio cuando la llamada viene desde un telefono SIP detras de una NAT que forza a registrar al Contact con la IP Privada.

esto se resolvia con llamadas VoIP puras realizando fix_nated_contact() y force_rtp_proxy() en la ruta onreply_route[]. En este caso luego de hacer el dispatch hacia los Asterisk, el asterisk me devuelve la llamada al kamailio cuando la han aceptado pero no puede ubicar al llamante con su IP privada ocasionada por el NAT y tampoco llega al onreply_route[] para realizar el fix_nated_contact() y el force_rtp_proxy()

Podrían ayudarme a conseguir ¿porque la llamada con la que me conecta el Asterisk no pasa por el onreply_route[] que utilizan las llamadas VoIP puras?

muchas gracias de antemano...

aquí coloco mi cfg

**************************************************************************************************

#
# $Id: kamailio.cfg 5800 2009-04-20 11:01:49Z miconda $
#
# Kamailio (OpenSER) SIP Server - basic configuration script
#     - web: http://www.kamailio.org
#     - svn: http://openser.svn.sourceforge.net/viewvc/openser/
#
# Direct your questions about this file to: <users en lists.kamailio.org>
#
# Refer to the Core CookBook at http://www.kamailio.org/dokuwiki/doku.php
# for an explanation of possible statements, functions and parameters.
#
# There are comments showing how to enable different features in th econfig
# file. Such commented code starts with #X# where X is a letter to identify
# a feature. Delete entire #X# if you want to enable that feature. Next are
# sed commands that help you enable such features.
#
# *** To enamble mysql execute:
#     sed -i 's/#m#//g' kamailio.cfg
#
# *** To enamble authentication execute:
#     - enable mysql
#     sed -i 's/#a#//g' kamailio.cfg
#     - add users using 'kamctl'
#
# *** To enamble persistent user location execute:
#     - enable mysql
#     sed -i 's/#u#//g' kamailio.cfg
#
# *** To enamble presence server execute:
#     - enable mysql
#     sed -i 's/#p#//g' kamailio.cfg
#
# *** To enamble nat traversal execute:
#     sed -i 's/#n#//g' kamailio.cfg
#     - install RTPProxy: http://www.rtpproxy.org
#     - start RTPProxy:
#        rtpproxy -l _your_public_ip_ -s udp:localhost:7722
#
# *** To enhance accounting execute:
#     - enable mysql
#     sed -i 's/#c#//g' kamailio.cfg
#     - add following columns to database
# ALTER TABLE acc ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT '';
# ALTER TABLE acc ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT '';
# ALTER TABLE acc ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT '';
# ALTER TABLE acc ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT '';
# ALTER TABLE acc ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT '';
# ALTER TABLE missed_calls ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT '';
# ALTER TABLE missed_calls ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT '';
# ALTER TABLE missed_calls ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT '';
# ALTER TABLE missed_call ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT '';
# ALTER TABLE missed_calls ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT '';
#


####### Global Parameters #########

debug=3
log_stderror=no
log_facility=LOG_LOCAL0

fork=yes
children=4

/* uncomment the following lines to enable debugging */
#debug=6
#fork=no
#log_stderror=yes

/* uncomment the next line to disable TCP (default on) */
#disable_tcp=yes

/* uncomment the next line to enable the auto temporary blacklisting of 
   not available destinations (default disabled) */
#disable_dns_blacklist=no

/* uncomment the next line to enable IPv6 lookup after IPv4 dns 
   lookup failures (default disabled) */
#dns_try_ipv6=yes

/* uncomment the next line to disable the auto discovery of local aliases
   based on revers DNS on IPs (default on) */
#auto_aliases=no

/* uncomment the following lines to enable TLS support  (default off) */
#disable_tls = no
#listen = tls:your_IP:5061
#tls_verify_server = 1
#tls_verify_client = 1
#tls_require_client_certificate = 0
#tls_method = TLSv1
#tls_certificate = "/usr/local/etc/kamailio/tls/user/user-cert.pem"
#tls_private_key = "/usr/local/etc/kamailio/tls/user/user-privkey.pem"
#tls_ca_list     = "/usr/local/etc/kamailio/tls/user/user-calist.pem"


port=5060

/* uncomment and configure the following line if you want Kamailio to 
   bind on a specific interface/port/proto (default bind on all available) */
#listen=udp:192.168.1.2:5060


####### Modules Section ########

#set module path
mpath="/usr/local/lib/kamailio/modules/"

/* uncomment next line for MySQL DB support */
loadmodule "db_mysql.so"
loadmodule "mi_fifo.so"
loadmodule "sl.so"
loadmodule "tm.so"
loadmodule "rr.so"
loadmodule "pv.so"
loadmodule "maxfwd.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
loadmodule "textops.so"
loadmodule "uri_db.so"
loadmodule "siputils.so"
loadmodule "xlog.so"
loadmodule "acc.so"
/* uncomment next lines for MySQL based authentication support 
   NOTE: a DB (like db_mysql) module must be also loaded */
loadmodule "auth.so"
loadmodule "auth_db.so"
/* uncomment next line for aliases support
   NOTE: a DB (like db_mysql) module must be also loaded */
#loadmodule "alias_db.so"
/* uncomment next line for multi-domain support
   NOTE: a DB (like db_mysql) module must be also loaded
   NOTE: be sure and enable multi-domain support in all used modules
         (see "multi-module params" section ) */
loadmodule "domain.so"
/* uncomment the next two lines for presence server support
   NOTE: a DB (like db_mysql) module must be also loaded */
loadmodule "presence.so"
loadmodule "presence_xml.so"
loadmodule "presence_mwi.so"#manually added

loadmodule "nathelper.so"

#modulo dispatcher agregado por mi
loadmodule "dispatcher.so"

# ----------------- setting module-specific parameters ---------------


# ----- mi_fifo params -----
modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")


# ----- rr params -----
# add value to ;lr param to cope with most of the UAs
modparam("rr", "enable_full_lr", 1)
# do not append from tag to the RR (no need for this script)
modparam("rr", "append_fromtag", 0)


# ----- rr params -----
modparam("registrar", "method_filtering", 1)
/* uncomment the next line to disable parallel forking via location */
# modparam("registrar", "append_branches", 0)
/* uncomment the next line not to allow more than 10 contacts per AOR */
#modparam("registrar", "max_contacts", 10)


# ----- uri_db params -----
/* by default we disable the DB support in the module as we do not need it
   in this configuration */
modparam("uri_db", "use_uri_table", 0)
modparam("uri_db", "db_url", "")


# ----- acc params -----
/* what sepcial events should be accounted ? */
modparam("acc", "early_media", 1)
modparam("acc", "report_ack", 1)
modparam("acc", "report_cancels", 1)
/* by default ww do not adjust the direct of the sequential requests.
   if you enable this parameter, be sure the enable "append_fromtag"
   in "rr" module */
modparam("acc", "detect_direction", 0)
/* account triggers (flags) */
modparam("acc", "failed_transaction_flag", 3)
modparam("acc", "log_flag", 1)
modparam("acc", "log_missed_flag", 2)
modparam("acc", "log_extra", 
	"src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd")
/* uncomment the following lines to enable DB accounting also */
#c#modparam("acc", "db_flag", 1)
#c#modparam("acc", "db_missed_flag", 2)
#c#modparam("domain", "db_url",
#c#	"mysql://openser:openserrw@localhost/openser")
#c#modparam("acc", "db_extra",
#c#	"src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd")


# ----- usrloc params -----
/* uncomment the following lines if you want to enable DB persistency
   for location entries */
#u#modparam("usrloc", "db_mode",   2)
#u#modparam("usrloc", "db_url",
#u#	"mysql://openser:openserrw@localhost/openser")

# ----- auth_db params -----
/* uncomment the following lines if you want to enable the DB based
   authentication */
#a#modparam("auth_db", "calculate_ha1", yes)
#a#modparam("auth_db", "password_column", "password")
#a#modparam("auth_db", "db_url",
#a#	"mysql://openser:openserrw@localhost/openser")
#a#modparam("auth_db", "load_credentials", "")

#parametros de autentificacion modificados manualmente
modparam("auth_db", "user_column", "username")
modparam("auth_db", "domain_column", "domain")
modparam("auth_db", "password_column", "ha1")
modparam("auth_db", "password_column_2", "ha1b")
modparam("auth_db", "calculate_ha1", 0)
#modparam("auth_db", "use_domain", 0)
modparam("auth_db", "use_domain", 1)#0 encendemos con 1 porque utilizaremos multi-domain
modparam("auth_db", "load_credentials", "rpid")
modparam("auth_db", "db_url",
	"mysql://openser:openserrw@localhost/openser")


# ----- alias_db params -----
/* uncomment the following lines if you want to enable the DB based
   aliases */
#modparam("alias_db", "db_url",
#	"mysql://openser:openserrw@localhost/openser")


# ----- domain params -----
/* uncomment the following lines to enable multi-domain detection
   support */
modparam("domain", "db_url",
	"mysql://openser:openserrw@localhost/openser")
modparam("domain", "db_mode", 1)   # Use caching


# ----- multi-module params -----
/* uncomment the following line if you want to enable multi-domain support
   in the modules (dafault off) */
modparam("alias_db|auth_db|usrloc|uri_db", "use_domain", 1)


# ----- presence params -----
/* uncomment the following lines if you want to enable presence */
modparam("presence|presence_xml", "db_url",
	"mysql://openser:openserrw@localhost/openser")
modparam("presence_xml", "force_active", 1)
modparam("presence", "server_address", "sip:212.4.107.250:5060")

# -- nathelper
modparam("nathelper", "rtpproxy_sock", "udp:127.0.0.1:7722")
modparam("nathelper", "natping_interval", 15)
modparam("nathelper", "ping_nated_only", 0)
modparam("nathelper", "sipping_bflag", 7)
modparam("nathelper", "sipping_from", "sip:pinger en 212.4.107.250")
modparam("registrar|nathelper", "received_avp", "$avp(i:80)")
modparam("usrloc", "nat_bflag", 6)
modparam("nathelper", "sipping_method", "OPTIONS")

# ----- dispatcher params -----
modparam("dispatcher", "db_url", "mysql://openser:openserrw@localhost/openser")
modparam("dispatcher", "table_name", "dispatcher")
modparam("dispatcher", "setid_col", "setid")
modparam("dispatcher", "destination_col", "destination")
modparam("dispatcher", "flags_col", "flags")
modparam("dispatcher", "priority_col", "priority")
modparam("dispatcher", "force_dst", 1)
modparam("dispatcher", "dst_avp", "$avp(i:271)")#default es null, debe setearse si deseamos hacer loadbalancing failover
modparam("dispatcher", "grp_avp", "$avp(i:272)")#default es null, debe setearse si deseamos hacer loadbalancing failover
modparam("dispatcher", "cnt_avp", "$avp(i:273)")#default es null, debe setearse si deseamos hacer loadbalancing failover
modparam("dispatcher", "hash_pvar", "$avp(i:273)")#default es null, debe setearse si deseamos hacer hashing over custom message parts


####### Routing Logic ########


# main request routing logic

route{

	if (!mf_process_maxfwd_header("10")) {
		sl_send_reply("483","Too Many Hops");
		exit;
	}

	# NAT detection
	route(4);

	if (has_totag()) {
		# sequential request withing a dialog should
		# take the path determined by record-routing
		if (loose_route()) {
			if (is_method("BYE")) {
				setflag(1); # do accounting ...
				setflag(3); # ... even if the transaction fails
			}
			route(1);
		} else {
			if (is_method("SUBSCRIBE") && uri == myself) {
				# in-dialog subscribe requests
				route(2);
				exit;
			}
			if ( is_method("ACK") ) {
				if ( t_check_trans() ) {
					# non loose-route, but stateful ACK; must be an ACK after a 487 or e.g. 404 from upstream server
					t_relay();
					exit;
				} else {
					# ACK without matching transaction ... ignore and discard.\n");
					exit;
				}
			}
			sl_send_reply("404","Not here");
		}
		exit;
	}

	#initial requests

	# CANCEL processing
	if (is_method("CANCEL"))
	{
		if (t_check_trans())
		{
			t_relay();
		}
		exit;
	}

	t_check_trans();

	# authentication
	route(3);

	# record routing
	if (!is_method("REGISTER|MESSAGE"))
	{
		record_route();
	}

	# account only INVITEs
	if (is_method("INVITE")) {
		setflag(1); # do accounting
	}
	##if (!uri==myself)
	/* replace with following line if multi-domain support is used */
	if (!is_uri_host_local())
	{
		append_hf("P-hint: outbound\r\n"); 
		# if you have some interdomain connections via TLS
		##if($rd=="tls_domain1.net") {
		##	t_relay("tls:domain1.net");
		##	exit;
		##} else if($rd=="tls_domain2.net") {
		##	t_relay("tls:domain2.net");
		##	exit;
		##}
		route(1);
	}

	# requests for my domain

	if( is_method("PUBLISH|SUBSCRIBE"))
	{
		route(2);
	}

	if (is_method("REGISTER"))
	{
                if (isflagset(5))
                {
                        setbflag(6);
                }

		if (!save("location"))
		{
			sl_reply_error();
		}
		exit;
	}

	if ($rU==NULL) {
		# request with no Username in RURI
		sl_send_reply("484","Address Incomplete");
		exit;
	}

	# apply DB based aliases (uncomment to enable)
	##alias_db_lookup("dbaliases");

	if (!lookup("location")) {
		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] {
	if (check_route_param("nat=yes")) {
		setbflag(6);
		setbflag(7);# sipping
	}
	if (isflagset(5) || isbflagset(6)) {
		route(5);
	}

	/* example how to enable some additional event routes */
	if (is_method("INVITE")) {


                               	if (uri=~ "sip:6[0-9]{8}*@")
				{
                                	xlog("L_INFO", "ES UN MOVIL DESDE ROUTE 1");
                                        if (($src_ip!="192.168.1.230")&&($src_ip!="192.168.1.231"))
					{
                                        	xlog("L_INFO", " NO PROVIENE DEL ASTERISK ENVIAMOS A ROUTE 10 PARA SU DISPATCH");
                                                route(10);
                                        }
                                }else{
                                        if (uri=~ "sip:9[0-9]{8}*@")
					{
                                        	xlog("L_INFO", "ES UN FIJO DESDE ROUTE 1");
                                                if ( ($src_ip!="192.168.1.230") && ($src_ip!="192.168.1.231") )
						{
                                                	xlog("L_INFO", " NO PROVIENE DEL ASTERISK ENVIAMOS A ROUTE 10 PARA SU DISPATCH");
                                                        route(10);
                                                }
                                        }
				}      


		#t_on_branch("1");
		t_on_reply("1");
		t_on_failure("1");
	}

	if (!t_relay()) {
		sl_reply_error();
	}
	exit;
}


# Presence route
/* uncomment the whole following route for enabling presence server */
route[2]
{
	if (!t_newtran())
	{
		sl_reply_error();
		exit;
	};

	if(is_method("PUBLISH"))
	{
		handle_publish();
		t_release();
	}
	else
	if( is_method("SUBSCRIBE"))
	{
		handle_subscribe();
		t_release();
	}
	exit;
	
	# if presence enabled, this part will not be executed
	if (is_method("PUBLISH") || $rU==null)
	{
		sl_send_reply("404", "Not here");
		exit;
	}
	return;
}

# Authentication route
/* uncomment the whole following route for enabling authentication */
route[3] {
	if (is_method("REGISTER"))
	{
		# authenticate the REGISTER requests (uncomment to enable auth)
		if (!www_authorize("", "subscriber"))
		{
			www_challenge("", "0");
			exit;
		}

		if ($au!=$tU) 
		{
			sl_send_reply("403","Forbidden auth ID");
			exit;
		}
	}
# Auth only on registration
#a#	} else {
#a#		# authenticate if from local subscriber (uncomment to enable auth)
#a#		if (from_uri==myself)
#a#		{
#a#			if (!proxy_authorize("", "subscriber")) {
#a#				proxy_challenge("", "0");
#a#				exit;
#a#			}
#a#			if (is_method("PUBLISH"))
#a#			{
#a#				if ($au!=$tU) {
#a#					sl_send_reply("403","Forbidden auth ID");
#a#					exit;
#a#				}
#a#			} else {
#a#				if ($au!=$fU) {
#a#					sl_send_reply("403","Forbidden auth ID");
#a#					exit;
#a#				}
#a#			}
#a#
#a#			consume_credentials();
#a#			# caller authenticated
#a#		}
#a#	}
	return;
}

# Caller NAT detection route
/* uncomment the whole following route for enabling Caller NAT Detection */
route[4]{
	force_rport();
	if (nat_uac_test("19")) {
		if (method=="REGISTER") {
			fix_nated_register();
		} else {
			fix_nated_contact();
		}
		setflag(5);
	}
	return;
}

# RTPProxy control
/* uncomment the whole following route for enabling RTPProxy Control */
route[5] {
	if (is_method("BYE")) {
		unforce_rtp_proxy();
	} else if (is_method("INVITE")){
		force_rtp_proxy();
	}
	if (!has_totag()) add_rr_param(";nat=yes");
	return;
}

route[10] {

        t_on_failure("2");      #si falla va a la ruta 2 creada a mano
        #comenzamos a hacer round robin con el dispatcher
        #reemplazamos la parte que contiene el dominio por el 1er dispatcher target del grupo 1 de dispatchers
        ds_select_dst("1", "4");        #algoritmo 4 hace round robin al proximo GW Asterisk para conversaciones hacia la PSTN

        t_relay();
        exit;
}


branch_route[1] {
	xdbg("new branch at $ru\n");
}


onreply_route[1] {
	xdbg("incoming reply\n");

	if ((isflagset(5) || isbflagset(6)) && status=~"(183)|(2[0-9][0-9])") {
		force_rtp_proxy();
	}
	if (isbflagset(6)) {
		fix_nated_contact();
	}
}


failure_route[1] {
	if (is_method("INVITE")
			&& (isbflagset(6) || isflagset(5))) {
		unforce_rtp_proxy();
	}

	if (t_was_cancelled()) {
		exit;
	}

	# uncomment the following lines if you want to block client 
	# redirect based on 3xx replies.
	##if (t_check_status("3[0-9][0-9]")) {
	##t_reply("404","Not found");
	##	exit;
	##}

	# uncomment the following lines if you want to redirect the failed 
	# calls to a different new destination
	##if (t_check_status("486|408")) {
	##	sethostport("192.168.2.100:5060");
	##	append_branch();
	##	# do not set the missed call flag again
	##	t_relay();
	##}
}

failure_route[2] {

        if(ds_next_dst())
	{
                t_on_failure("2");#si falla va al siguiente GW Asterisk
                t_relay();#relay al siguiente GW
        } else {
                exit;
        }

}
**************************************************************************************************

_______________________________________________
SR-Users-ES mailing list
SR-Users-ES en lists.sip-router.org
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users-es

_________________________________________________________________ 
Este mensaje ha sido escaneado en busca de virus por MailScanner.





Más información sobre la lista de distribución SR-Users-ES