FreeSWITCH es una plataforma de telefonía de código abierto capaz de actuar como centralita SIP, servidor de conferencias, IVR o pasarela WebRTC. En este tutorial instalarás FreeSWITCH en Debian 12 desde el repositorio oficial de paquetes de SignalWire, cerrarás los puntos débiles de la configuración de ejemplo, registrarás dos extensiones con un softphone y conectarás un trunk SIP de un proveedor para hacer y recibir llamadas externas.

Requisitos previos

  • Un servidor con Debian 12 (bookworm) de 64 bits, por ejemplo un VPS de CubePath con IP pública. Los paquetes oficiales de FreeSWITCH se publican para Debian; en Ubuntu tendrías que compilar desde el código fuente.
  • 2 GB de RAM como mínimo.
  • Un usuario no root con privilegios sudo.
  • Una cuenta gratuita en SignalWire para generar un token de acceso personal (Personal Access Token), necesario para descargar los paquetes.
  • Un softphone SIP en tu ordenador o móvil, como Linphone, MicroSIP o Zoiper.
  • Opcional: una cuenta con un proveedor de trunk SIP (usuario, contraseña y servidor) para llamadas externas.

Paso 1: Obtener el token de SignalWire

El repositorio de paquetes de FreeSWITCH requiere autenticación con un token de SignalWire. En el panel de SignalWire, abre tu perfil, entra en Personal Access Tokens y crea un token nuevo. Los tokens de la edición Community empiezan por pat_.

Guárdalo en una variable de la sesión actual para usarlo en los siguientes comandos:

read -rs FS_TOKEN

Pega el token y pulsa Intro. Con -s no se muestra en pantalla ni queda en el historial del shell.

Paso 2: Añadir el repositorio oficial e instalar FreeSWITCH

Instala las herramientas necesarias:

sudo apt update
sudo apt install curl gnupg2 ca-certificates

apt necesita el token para descargar del repositorio. Guárdalo en un archivo de credenciales de apt que solo root pueda leer:

echo "machine freeswitch.signalwire.com login signalwire password ${FS_TOKEN}" | sudo tee /etc/apt/auth.conf.d/freeswitch.conf > /dev/null
sudo chmod 600 /etc/apt/auth.conf.d/freeswitch.conf

Descarga la clave de firma del repositorio en /etc/apt/keyrings:

sudo install -m 0755 -d /etc/apt/keyrings
sudo curl --fail --netrc-file /etc/apt/auth.conf.d/freeswitch.conf \
  -o /etc/apt/keyrings/signalwire-freeswitch-repo.gpg \
  https://freeswitch.signalwire.com/repo/deb/debian-release/signalwire-freeswitch-repo.gpg

Crea el archivo del repositorio en formato deb822:

sudo tee /etc/apt/sources.list.d/freeswitch.sources > /dev/null <<EOF
Types: deb
URIs: https://freeswitch.signalwire.com/repo/deb/debian-release/
Suites: $(. /etc/os-release && echo "$VERSION_CODENAME")
Components: main
Signed-By: /etc/apt/keyrings/signalwire-freeswitch-repo.gpg
EOF

Actualiza el índice e instala el metapaquete, que incluye FreeSWITCH, sus módulos, los sonidos y la configuración de ejemplo en /etc/freeswitch:

sudo apt update
sudo apt install freeswitch-meta-all

Comprueba que el servicio está en marcha y responde a la consola fs_cli:

sudo systemctl status freeswitch
sudo fs_cli -x "status"
UP 0 years, 0 days, 0 hours, 1 minute, 12 seconds, 402 milliseconds, 85 microseconds
FreeSWITCH (Version 1.10.x ...) is ready
0 session(s) since startup
...

Paso 3: Proteger la configuración por defecto

La configuración de ejemplo está pensada para pruebas y tiene dos puntos que no deben llegar a un servidor con IP pública.

Cambiar la contraseña de las extensiones

Las extensiones de ejemplo 1000 a 1019 usan la contraseña global default_password, que por defecto es 1234. Cualquiera que la conozca puede registrarse y hacer llamadas a tu costa. Abre el archivo de variables:

sudo nano /etc/freeswitch/vars.xml

Busca esta línea y cambia 1234 por una contraseña larga y aleatoria (puedes generarla con openssl rand -base64 18):

<X-PRE-PROCESS cmd="set" data="default_password=your_strong_password"/>

Cerrar el Event Socket

El módulo Event Socket (puerto 8021) permite controlar FreeSWITCH por completo, y en la configuración de ejemplo escucha en todas las interfaces con la contraseña ClueCon. Limítalo a localhost:

sudo nano /etc/freeswitch/autoload_configs/event_socket.conf.xml
<configuration name="event_socket.conf" description="Socket Client">
  <settings>
    <param name="nat-map" value="false"/>
    <param name="listen-ip" value="127.0.0.1"/>
    <param name="listen-port" value="8021"/>
    <param name="password" value="ClueCon"/>
    <param name="apply-inbound-acl" value="loopback.auto"/>
  </settings>
</configuration>

fs_cli se conecta a 127.0.0.1:8021 con la contraseña ClueCon, así que seguirá funcionando. Si cambias también la contraseña, tendrás que pasársela con fs_cli -p.

Reinicia FreeSWITCH para aplicar ambos cambios y comprueba que el Event Socket ya solo escucha en localhost:

sudo systemctl restart freeswitch
sudo ss -tlpn | grep 8021
LISTEN 0      30         127.0.0.1:8021       0.0.0.0:*    users:(("freeswitch",pid=5310,fd=41))

Paso 4: Configurar el firewall

FreeSWITCH usa dos perfiles SIP: internal (puerto 5060) para tus extensiones y external (puerto 5080) para los trunks de proveedores. El audio viaja por RTP en un rango de puertos UDP. Debian 12 no trae UFW instalado; instálalo y permite SSH antes de activarlo:

sudo apt install ufw
sudo ufw allow OpenSSH

El puerto 5060 recibe escaneos constantes de bots que prueban contraseñas SIP. Si tus usuarios se conectan desde IP conocidas, abre el perfil interno solo para ellas (sustituye your_office_ip):

sudo ufw allow from your_office_ip to any port 5060 proto udp
sudo ufw allow from your_office_ip to any port 5060 proto tcp

Abre el perfil externo para tu proveedor (sustituye provider_ip por la IP o rango que te indique) y el rango RTP:

sudo ufw allow from provider_ip to any port 5080 proto udp
sudo ufw allow 16384:32768/udp
sudo ufw enable
sudo ufw status

Paso 5: Registrar extensiones y hacer una llamada de prueba

Comprueba que los dos perfiles SIP están activos:

sudo fs_cli -x "sofia status"
                     Name          Type                                       Data      State
=================================================================================================
                 external       profile             sip:[email protected]:5080      RUNNING (0)
                 internal       profile             sip:[email protected]:5060      RUNNING (0)
...

Configura el softphone con estos datos:

  • Usuario / extensión: 1000
  • Contraseña: la que pusiste en default_password
  • Dominio o servidor: your_server_ip
  • Puerto: 5060, transporte UDP

Verifica el registro desde el servidor:

sudo fs_cli -x "show registrations"
reg_user,realm,token,url,expires,network_ip,network_port,network_proto,hostname,metadata
1000,203.0.113.10,...,sofia/internal/sip:[email protected]:5060,...

1 total.

Llama al 9196: es la prueba de eco del dialplan de ejemplo y te devuelve tu propia voz. Si te oyes, la señalización SIP y el audio RTP funcionan. Registra otro dispositivo como 1001 y llama de uno a otro para probar llamadas internas. Otras extensiones útiles del dialplan de ejemplo son el 5000 (IVR de demostración) y el 3000 (sala de conferencias).

Paso 6: Conectar un trunk SIP

Para llamar a números externos, define un gateway en el perfil external. FreeSWITCH carga todos los archivos .xml de /etc/freeswitch/sip_profiles/external/:

sudo nano /etc/freeswitch/sip_profiles/external/mi_proveedor.xml
<include>
  <gateway name="mi_proveedor">
    <param name="username" value="your_sip_user"/>
    <param name="password" value="your_sip_password"/>
    <param name="realm" value="sip.provider.example"/>
    <param name="proxy" value="sip.provider.example"/>
    <param name="register" value="true"/>
  </gateway>
</include>

Vuelve a leer la configuración del perfil y comprueba el estado del gateway:

sudo fs_cli -x "sofia profile external rescan"
sudo fs_cli -x "sofia status gateway mi_proveedor"

Busca la línea State: el valor REGED indica que el proveedor ha aceptado el registro.

State   REGED

Llamadas salientes

Añade una regla al dialplan default que envíe por el gateway los números que empiecen por 0, quitando ese prefijo. FreeSWITCH incluye los archivos de /etc/freeswitch/dialplan/default/:

sudo nano /etc/freeswitch/dialplan/default/01_salientes.xml
<include>
  <extension name="salientes_mi_proveedor">
    <condition field="destination_number" expression="^0(\d{9,15})$">
      <action application="set" data="effective_caller_id_number=your_did"/>
      <action application="bridge" data="sofia/gateway/mi_proveedor/$1"/>
    </condition>
  </extension>
</include>

Sustituye your_did por el número que te ha asignado el proveedor. El formato del número de destino (con o sin prefijo internacional) depende del proveedor.

Llamadas entrantes

Las llamadas que llegan por el perfil external se procesan en el contexto public. Crea una regla que pase las llamadas a tu número a la extensión 1000:

sudo nano /etc/freeswitch/dialplan/public/01_entrantes.xml
<include>
  <extension name="entrante_did">
    <condition field="destination_number" expression="^(your_did)$">
      <action application="transfer" data="1000 XML default"/>
    </condition>
  </extension>
</include>

Recarga el XML y prueba una llamada saliente marcando 0 seguido de un número real, y una entrante llamando a tu número desde un móvil:

sudo fs_cli -x "reloadxml"
+OK [Success]

Solución de problemas

Para ver qué ocurre durante una llamada, abre la consola interactiva y sube el nivel de log:

sudo fs_cli

Dentro de la consola, /log debug muestra todo el detalle y sofia global siptrace on imprime los mensajes SIP. Sal con /exit. El log completo está en /var/log/freeswitch/freeswitch.log.

La llamada se establece pero no hay audio o solo se oye en un sentido. Es casi siempre un problema de RTP: revisa que el rango 16384:32768/udp está abierto y que la IP que anuncia FreeSWITCH es la pública. Compruébalo con sudo fs_cli -x "sofia status profile internal" | grep -i ext-rtp-ip.

El softphone no se registra (error 403). La contraseña no coincide. Recuerda que el cambio en vars.xml requiere reiniciar el servicio.

El gateway queda en FAIL_WAIT o UNREGED. Revisa usuario, contraseña y realm con los datos del proveedor, y que la regla de UFW permite su IP en el puerto 5080.

Conclusión

Tienes FreeSWITCH instalado en Debian 12 desde el repositorio oficial, con la configuración de ejemplo protegida, extensiones registradas y un trunk SIP para llamadas externas. Como siguientes pasos puedes sustituir las extensiones de ejemplo por las tuyas en /etc/freeswitch/directory/default/, añadir TLS al perfil interno para cifrar la señalización o habilitar mod_verto para llamar desde el navegador con WebRTC.