[OpenSER-Users-ES] ¿Forwarding correcto?

Iñaki Baz Castillo ibc at aliax.net
Mon Aug 27 18:56:50 CEST 2007


Hola, después de pelearme unos cuantos días creo que ya tengo suficientemente 
bien implementado el tema del forwarding, es decir, que al llamar a un 
usuario se consulte si tiene otra URI asociada y se le llame a ambas en 
paralelo hasta que coja de una de ellas.

Lo primero me gustaría comentar que lo que en muchos sitios se explica 
como "forwarding" al mero hecho de poner un "append_branch()" me parece 
bastante incierto, hay que tener mucho cuidado ya que el nuevo branch no debe 
pasar de nuevo por un auth (o fallará en el lado cliente). Es decir, si 
alguien llama al "pepe" y se crea un nuevo branch a "juan", el nuevo branch 
que va a "pepe" consiste en un nuevo INVITE originado por OpenSer que pasaría 
de nuevo por el authenticate y demás (salvo que se añadan cabeceras para 
evitarlo o se testee la IP de origen y tal). Si no se tiene cuidado se 
volverá a pedir autenticación sobre ese INVITE para el cuál ya se había 
autenticado el usuario que llama y cuyo cliente fallará si recibe 
otro "authenticate" (lo he comprobado).

Bueno, y para complicarlo un poco más yo lo tengo puesto en modo multidominio, 
con restricciones de llamadas entre dominios (cada dominio decide quién puede 
llamar a qué miembros del dominio) y además permito forwarding a dominios 
distintos del local (estos dominios podrían ser a la vez locales o externos, 
pero debe implicar el mismo comportamiento pues pretendo independencia total 
de dominios).

Después de probar unas cuantas cosas he optado por hacer un "outbound" tal 
cuál al INVITE cuya URI se ha modificado con la del forwarding, sea el nuevo 
dominio el mismo u otro diferente (local o externo), por eso creo que 
un "outbound" es lo más sencillo: si el dominio es local ya volverá el 
paquete XD


Después de la chapa comento mi trocito de INVITE y el forwarding:


# -----------------------------------------------------------------
# INVITE
# -----------------------------------------------------------------
route[3] {

	# Comprobamos los aliases. Recordar que los alias son sólo del mismo dominio.
	route(10);  # Aliases.

	# Permisos.
	if (!route(4)) {  # Trusted.
		# Sólo pedimos autenticación si es el llamante es local.
		if (is_from_local()) {
			route(6);  # Auth.
		}
		route(7);  # Grupos.
		# Comprobamos los permisos ACL entre-dominios.
		route(5);  # ACL.
	}

	# Comprobamos los forwardings. Pueden apuntar a otros dominios.
	route(11);  # Forwarding.
	
	# Ahora buscamos el usuario llamado.
	route(12);  # Location.

}


Y el forwarding:

# -----------------------------------------------------------------
# Forwarding
# -----------------------------------------------------------------
route[11] {

	if ($hdr(Forwarding)) {
		xlog("L_INFO", "Encontrada cabecera 'Forwarding' -> No miramos 
tabla 'forwarding' para $ru\n");
		return(-1);
	}
	
	avp_db_query("SELECT uri FROM forwarding WHERE 
username='$rU'", "$avp(s:forwarding_uri)");
	if ($rc == 1) {
		
		# Cabecera para que el nuevo branch y el actual (via outbound)
		# no pasen por "trusted":
		append_hf("No-Trusted: Forwarding\r\n"); 
		
		# Cabecera para que el nuevo branch no vuelva a pasar por "forwarding":
		append_hf("Forwarding: Yes\r\n"); 
		
		# Cabecera para que el nuevo branch y el actual (via outbound)
		# no se tengan que volver a autenticar en "auth".
		append_hf("Authenticated: Yes\r\n");

		append_branch();
		$ru = $avp(s:forwarding_uri);
		
		remove_hf("Forwarding");  # En el INVITE original modificado a la URI del 
forwarding quitamos esta cabecera pues la URI del forwarding podría contener 
a su vez otro forwarding.
		
		# Enviamos el INVITE modificado con la URI del forwarding a outbound.
		# Si tiene que volver ya volverá.
		route(9);  # Outbound.
 		exit;
	}

}


En fin, ¿es correcto? Me funciona bien y por ejemplo tiene en cuenta el 
siguiente caso un poco "tramposo":

- Imaginemos dos dominios locales "a.com" y "b.com".
- b.com tiene puestos unos ACLs que impiden llamadas entrantes desde a.com.
- Un espavilado de a.com define un forwarding:  pepe at a.com -> juan at b.com
- Ahora imaginemos que luis at a.com llama a pepe at a.com por lo que también 
llamaría (o intentaría llamar) a juan at b.com.
- Si yo no hiciese el outbound final en el forwarding, o bien añado mucha 
lógica redundante sobre permisos, o mi OpenSer cometería el error de permitir 
la llamada a juan at b.com ya que el llamante se había autenticado **pero para 
llamar a alguien de su dominio, a pepe at a.com**.
- Por eso yo he optado por hacer un outbound, así la llamada vuelve a entrar, 
con la cabecera añadida y comprobando que viene de la IP de OpenSer evito que 
vuelva a tener que autenticarse, pero el INVITE pasa por el ACL's donde se le 
deniega la llamada al dominio b.com.


Pues eso, ¿qué os parece así? ¿estoy olvidando algo?

Gracias por cualquier opinión y sugerencia. Saludos.



-- 
Iñaki Baz Castillo




More information about the Users-es mailing list