investigación de los Avances tecnológicos del siglo XXI
[VoIP2Day 2008] Asterisk & Carriers PSTN
1. Asterisk & carriers PSTN
“ ...because PSTN does exist ”
Iñaki Baz Castillo <ibc@aliax.net>
2. Comenzando como proveedor VoIP
Empezamos con un único Asterisk
Tarjeta de primario con conexión a carrier
Usuarios SIP
Reciben llamadas a sus DID's asignados:
999000111 <> sip:amancio@provider
Hacen llamadas con CallerID su DID asignado
DID's mapeados directamente en el dialplan (¿AGI/DB?)
Llamadas entre usuarios vía SIP (¿gratis?)
4. Crecemos...
Aumenta el número de clientes
Necesitamos más capacidad de llamadas
Un único servidor se queda corto
Necesitamos más capacidad (líneas RDSI y servidores)
Ponemos más Asterisk en paralelo
Más conexiones de primario con nuevos carriers
Cada Asterisk tiene sus propios usuarios y DID's
Añadimos un host para BD
Todos los Asterisk usan esta BD (CDR centralizado)
6. ¡Problemas!
Si cae un Asterisk:
Sus usuarios no pueden ni hacer ni recibir llamadas
Si cae un enlace de primario:
Los usuarios con DID en ese primario no pueden recibir llamadas
(lógico) pero tampoco hacerlas a través de otro Asterisk
¿Por qué no?
Descentralización:
¿Mapeo en llamadas entre usuarios locales? ¿BD?
Conclusión: Hemos creado islas independientes
8. Proveedor VoIP escalable (I)
Un SIP proxy + registrar delante
Todos los usuarios se registran aquí y no en los Asterisk
El proxy ruta llamadas outbound a cualquier gateway (Asterisk)
Si un gateway falla ruta la llamada por otro (“dispatcher”)
Podemos mostrar cualquier CallerID a través de cualquier gateway
El proxy ruta las llamadas a los usuarios
Servidor DB
Mapeo DID <> usuario SIP > ¡centralizado!
Guarda los registros de los usuarios > ¡centralizado!
Guarda los CDR > ¡centralizado!
9. Proveedor VoIP escalable (II)
Batería de Asterisk a modo de gateway SIP/PSTN
Asterisk “sin cerebro” (meros gateways)
Rutan las llamadas desde PSTN al proxy central
Pega: cada Asterisk tiene sus bloques de DID's entrantes
Difícil de mejorar si tenemos distintos carriers
Proxy RTP para encaminar audio en llamadas entre usuarios
Necesario si alguno de los usuarios está tras NAT sin STUN
11. “Y más mejor...”
Redundancia en el proy/registrar
Usamos, por ejemplo, HeartBeat
Si el nodo 1 cae, el nodo 2 toma el control (incluso de la IP de
servicio)
“Aquí no ha pasado nada”
Redundancia BD
Podemos usar BD en clustering con replicación mastermaster
Redundancia en cada gateway (Asterisk)
Redundancia de primarios (ej: RedPhone)
Si su Asterisk cae el dispositivo encamina el primario a otro nodo
12. Asterisk como gateway SIP/PSTN (I)
Configuración SIP (sip.conf)
[proxy]
type = peer ; Lo identificamos por su IP origen
host = IP_PROXY
port = 5060
insecure = invite ; El proxy no debe autenticarse
qualify = no
canreinvite = no
disallow = all
allow = g729
allow = alaw
allow = ulaw
dtmfmode = rfc2833
nat = yes ; Modo “Comedia” (soluciona RTP tras NAT)
context = from-proxy
13. Asterisk como gateway SIP/PSTN (II)
Control de llamadas salientes concurrentes
Cada Asterisk con tarjeta de 4 primarios: 120 canales
Conectado a un carrier que nos entrega DID's
El carrier nos ruta llamadas a esos DID's sólo por estos primarios
Hay que reservar algunos canales para entrantes (las llamadas
salientes pueden hacerlo por cualquier otro primario)
Creamos una lógica en Asterisk para limitar el número de
llamadas salientes
14. Macro para limitación de llamadas salientes
[macro-check-outbound]
; ${ARG1} = ${EXTEN}
exten => s,1,Set(GROUP()=outbound_calls)
exten => s,n,GotoIf($[${GROUP_COUNT(outbound_calls)} >
${MAX_OUTBOUND_CALLS}]?deny,1)
; ### Llamada permitida, que continúe el dialplan
exten => s,n,MacroExit
; ### Llamada no permitida por exceder MAX_OUTBOUND_CALLS ->
; respondemos SIP 503
exten => deny,1,Hangup(42) ; AST_CAUSE_SWITCH_CONGESTION (SIP 503)
; http://www.voip-info.org/wiki/index.php?page=Asterisk+variable+hangupcause
Cuando el proxy reciba este 503 intentará sacar la llamada por otro
gateway
15. Asterisk como gateway SIP/PSTN (III)
CallerID en llamadas outbound
El proxy añade la cabecera “PAssertedIdentity” y Asterisk hará
honor a esa cabecera:
INVITE sip:+34999000111@IP_ASTERISK;user=phone SIP/2.0
Record-Route: <sip:IP_PROXY;lr=on>
Via: SIP/2.0/UDP ADDRESS_PROXY;branch=z9hG4bK7817.9f2e1eb2.0
Via: SIP/2.0/UDP ADDRESS_CLIENT;branch=z9hG4bK0bd0861e;rport=10001
From: quot;Amancioquot; <sip:amancio@SIP_PROVIDER>;tag=as2d2bf44e
To: <sip:999000111@SIP_PROVIDER>
Contact: <sip:amancio@ADDRESS_CLIENT>
Call-ID: 318448b03164e77873d8e21a311ee21
P-Asserted-Identity: <sip:987654321@SIP_PROVIDER;user=phone>
En caso de solicitar privacidad (número oculto) el proxy añade:
Privacy: id
16. Dialplan
[from-proxy]
; ### Comprobar llamadas outbound simultáneas
exten => _XX.,1,Macro(check-outbound,${EXTEN})
; ### Extraemos el PAI para crear el verdadero CallerID.
exten => _XX.,n,GotoIf($[quot;${SIP_HEADER(P-Asserted-Identity)}quot;!=quot;quot;]?pai:end-pai)
exten => _XX.,n(pai),NoOp(--- P-Asserted-Identity ---)
exten => _XX.,n,Set(UCLID=${CUT(CUT(SIP_HEADER(P-Asserted-Identity),@,1),:,2)})
exten => _XX.,n,Set(CALLERID(all)=${UCLID} <${UCLID}>)
exten => _XX.,n(end-pai),NoOp
; ### ¿Privacidad solicitada (número oculto)?
exten => _XX.,n,GotoIf($[quot;${SIP_HEADER(Privacy)}quot;=quot;idquot;]?privacy:end-privacy)
exten => _XX.,n(privacy),NoOp(--- Privacy: id ---)
exten => _XX.,n,SetCallerPres(prohib_not_screened)
exten => _XX.,n(end-privacy),NoOp
; ### Dial via PRI
exten => s,n,Dial(Zap/g1/${ARG1})
exten => s,n,Hangup ; ¡¡ IMPORTANTE para que dé un
; código de error coherente !!
Importante: No escondemos el CallerID al carrier, sino que se lo
entregamos solicitando que no le sea entregado al destino final.
17. Asterisk como gateway SIP/PSTN (IV)
CallerID en llamadas inbound
El CallerID lo obtenemos siempre con ${CALLERID(all)} (incluso
aunque sea oculto).
Debemos averiguar si viene con número oculto.
Antes de enviar el INVITE al proxy, añadimos la cabecera “P
AssertedIdentity”
Y en caso de CallerID oculto, también “Privacy: id”
18. Dialplan
[from-pstn]
; ### Añadimos P-Asserted-Identity: CallerID real. Muy útil si la llamada
; viene con CallerID oculto.
exten => _XX,1,SIPAddHeader(P-Asserted-Identity:
<sip:${CALLERID(num)}@SIP_PROVIDER>)
; ### ¿Privacy? Si viene con número oculto Asterisk lo traduce a:
; From: quot;Unknownquot; <sip:Unknown@IP_ASTERISK>
; No muy SIP RFC, lo más correcto sería:
; From: quot;Anonymousquot; <sip:anonymous@anonymous.invalid>
; Nosotros añadimos el quot;Privacy: idquot; y el proxy esconderá el From
exten => _XX,n,GotoIf($[${MATH(${CALLINGPRES}>30)}=TRUE]?privacy:
end-privacy)
exten => _XX,n(privacy),SIPAddHeader(Privacy: id)
exten => _XX,n(end-privacy),NoOp
; ### Llamada al proxy
exten => _XX,n,Dial(SIP/proxy/${EXTEN})
exten => _XX,n,Hangup()
El proxy localizará al usuario SIP correspondiente a dicho DID