BookinglyTech News
Software

FARA CRM añade llamadas desde el navegador con Asterisk y WebRTC

El CRM libre sobre FastAPI y React publica cómo integró voz en el navegador usando el Asterisk o FreePBX que la empresa ya tenga, sin softphone ni PBX en la nube.

3 min de lecturaDev.to0 vistas

FARA CRM, un CRM libre y de código abierto montado sobre FastAPI y React, ha contado cómo añadió llamadas de voz desde el propio navegador apoyándose en el Asterisk o el FreePBX que la empresa ya tenga desplegado. La idea: el empleado pulsa un número dentro del CRM y habla ahí mismo, sin un softphone en cada portátil, sin configurar SIP en Zoiper y sin pagar un PBX en la nube.

El montaje es enteramente gratuito y open source: Asterisk o FreePBX como centralita, JsSIP (licencia MIT) como cliente SIP en el navegador, coturn como relay TURN y FastAPI como proxy entre navegador y PBX. Todo el código está en el repositorio del proyecto.

Solo la señalización pasa por el servidor

La decisión de arquitectura que sostiene el resto es que únicamente la señalización SIP atraviesa el backend. Son mensajes de texto pequeños —register, call, colgar— y el audio va directo entre el navegador y Asterisk, con coturn como caída cuando no hay camino posible. El servidor web no transporta voz.

En FreePBX hay que marcar webrtc=yes en la extensión PJSIP: ese único flag activa DTLS, ICE y AVPF de golpe. Si se deja fuera, la llamada revienta con un 488 Not Acceptable Here que JsSIP reporta como Incompatible SDP. También hay que dar de alta una extensión aparte para el navegador si el empleado conserva su teléfono de escritorio, levantar WSS con certificado real —Let's Encrypt vale— en el puerto TCP 8089, abrir UDP 10000–20000 para RTP y servir el CRM por HTTPS, porque el navegador solo concede acceso al micrófono en páginas seguras.

El proxy en FastAPI, que vive en la ruta sip.py del repositorio, cumple tres funciones: encaja con una CSP que solo permite conexiones al propio dominio, deja la dirección del PBX en los ajustes del CRM para que un administrador la cambie sin tocar nginx, y comprueba que el usuario tenga una línea en esa centralita antes de dejarle pasar. Hay un detalle que rompe la conexión sin dar ninguna pista: hay que responder al handshake con accept(subprotocol="sip").

En el frontend, JsSIP se configura con una WebSocketInterface y un objeto UA que registra la extensión; llamar es un ua.call(). Las entrantes llegan por el evento newRTCSession y se atienden con session.answer(). En FARA CRM el marcador es un botón en la cabecera y, al contestar, se abre sola la ficha del cliente.

TURN para las redes difíciles

En oficinas con NAT estricto o UDP bloqueado las llamadas conectan "a veces". coturn viaja en el mismo docker-compose que el CRM y arranca con él. En lugar de cuentas fijas por empleado, acepta credenciales efímeras firmadas con un secreto compartido: el backend genera un usuario con marca de expiración y una contraseña HMAC-SHA1 en base64. El navegador recibe el relay por UDP y por TCP, y el TCP es lo que salva los cortafuegos corporativos. La configuración mínima de coturn incluye denied-peer-ip para los rangos privados, de modo que el relay no pueda alcanzar la red interna.

Que el código quepa en pocas líneas no lo hace trivial: el escollo real no está en el proxy, está en la configuración de la centralita y en la red. Y queda abierto lo de siempre en este terreno, que es cómo se protege un relay expuesto a internet cuando el tráfico pasa por él.