Asterisk & carriers PSTN
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?)PSTN Internet / DSL dedicado Carrier PSTN RDSI primario SIP RTP
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)PSTN
RDSI primario
BD
SIP
¡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?
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 entrantes a los usuarios Hace el accounting y lo guarda en BD (¿Radius?)
Servidor DB
Mapeo DID <> usuario SIP (¿DNS ENUM?) > ¡centralizado! Guarda los registros de los usuarios > ¡centralizado! Guarda los CDR > ¡centralizado!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 STUNPSTN RDSI primario BD Proxy & Registrar SIP Proxy RTP RTP SIP RTP
“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
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)
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
Macro para limitación de llamadas salientes
[globals] MAX_OUTBOUND_CALLS = 15 [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
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: "Amancio" <sip:amancio@SIP_PROVIDER>;tag=as2d2bf44e
To: <sip:999000111@SIP_PROVIDER>
Contact: <sip:amancio@ADDRESS_CLIENT> Call-ID: 318448b03164e77873d8e21a311ee21
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($["${SIP_HEADER(P-Asserted-Identity)}"!=""]?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($["${SIP_HEADER(Privacy)}"="id"]?privacy:end-privacy) exten => _XX.,n(privacy),NoOp(--- Privacy: id ---)
exten => _XX.,n,SetCallerPres(prohib_not_screened) exten => _XX.,n(end-privacy),NoOp
; ### Dial vía 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
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 (un poco “ñapa”) Antes de enviar el INVITE al proxy, añadimos la cabecera “P AssertedIdentity” Y en caso de CallerID oculto, también “Privacy: id”
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: "Unknown" <sip:Unknown@IP_ASTERISK>
; No muy SIP RFC, lo más correcto sería:
; From: "Anonymous" <sip:[email protected]>
; Nosotros añadimos el "Privacy: id" 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 El proxy quitará el PAssertedIdentity antes de rutar el INVITE al usuario