Criando Chamadas WebRTC com Asterisk em Docker

Quer permitir chamadas de voz diretamente pelo navegador usando WebRTC e integrá-las ao Asterisk? Neste post, vou te mostrar passo a passo como rodar o Asterisk dentro de um container Docker, configurar os transportes necessários e conectar um frontend WebRTC usando JavaScript (com JsSIP).

A ideia aqui é montar um ambiente completo, mas simples o suficiente para você testar localmente ou em um servidor de homologação. Vamos começar configurando o Asterisk no Docker.

🐳Subindo o Asterisk com Docker (com WebRTC)

Para ter controle total sobre os módulos e dependências do Asterisk — incluindo suporte ao WebRTC e ao codec Opus — usaremos uma imagem personalizada baseada no Debian Bookworm.

📦Dockerfile

Crie um arquivo Dockerfile com o conteúdo abaixo:

Dockerfile
FROM debian:bookworm-slim

RUN apt-get update && apt-get install -y \
    wget curl build-essential \
    libedit-dev uuid-dev libjansson-dev libxml2-dev \
    unixodbc unixodbc-dev odbc-postgresql libpq-dev \
    && apt-get clean

WORKDIR /usr/src
RUN wget http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-20-current.tar.gz \
    && tar xvf asterisk-20-current.tar.gz \
    && cd asterisk-20.* \
    && contrib/scripts/install_prereq install \
    && ./configure --with-pjproject-bundled --with-jansson-bundled \
    && make menuselect.makeopts \
    && menuselect/menuselect --enable codec_opus --enable res_odbc --enable cdr_adaptive_odbc --enable res_config_odbc menuselect.makeopts \
    && make -j$(nproc) && make install && make samples && make config && ldconfig

RUN mkdir -p /opt/asterisk-config

COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

CMD ["/entrypoint.sh"]

🔁Script de inicialização

Crie um arquivo entrypoint.sh ao lado do seu Dockerfile:

Bash
#!/bin/bash

CONFIG_SRC="/opt/asterisk-config"
CONFIG_DEST="/etc/asterisk"

cp -r "$CONFIG_SRC/"* "$CONFIG_DEST/"

exec asterisk -vvv -f

🛠️ Build e execução do container

Agora, para construir e rodar o container:

Bash
docker build -t asterisk-webrtc .

🌐 Criando uma rede Docker dedicada

Antes de usarmos o Docker Compose, é uma boa prática criar uma rede personalizada para isolar e facilitar a comunicação entre os serviços da stack (como o Asterisk e, futuramente, um possível backend ou frontend).

Execute o seguinte comando para criar uma rede Docker chamada asterisk-webrtc-network:

Bash
docker network create asterisk-webrtc-network

📦 Usando Docker Compose

Agora, vamos substituir o comando manual de docker run por um docker-compose.yml, que facilita o gerenciamento da stack como um todo.

Crie um arquivo docker-compose.yml com o seguinte conteúdo:

YAML
name: asterisk-webrtc

services:
  asterisk:
    image: asterisk-webrtc # Sua image local
    container_name: asterisk
    ports:
      - "8089:8089"   # WebSocket TLS (WSS)
      - "8088:8088"   # WebSocket (WS) ou HTTP API
    volumes:
      - ./asterisk:/opt/asterisk-config
      - ./etc/odbc.ini:/etc/odbc.ini
      - ./etc/odbcinst.ini:/etc/odbcinst.ini
    networks:
      - voip-asterisk

networks:
  voip-asterisk:
    external: true

💡 Importante: Certifique-se de que o diretório ./asterisk contenha os arquivos de configuração como pjsip.conf, http.conf, etc., e que os arquivos odbc.ini e odbcinst.ini estejam na pasta ./etc.

⚙️ 2. Configurações do Asterisk para WebRTC

Agora que o container está rodando, precisamos configurar o Asterisk para suportar chamadas WebRTC, armazenamento de CDR (Call Detail Records), comunicação via WebSocket, entre outros pontos essenciais.

Vamos começar com os arquivos de configuração um a um. Todos devem ser colocados no diretório ./asterisk, que é montado dentro do container em /opt/asterisk-config.

📄 cdr_adaptive_odbc.conf

Este arquivo configura o Asterisk para gravar os registros de chamadas (CDR) diretamente em um banco de dados via ODBC. Neste caso, usamos uma conexão chamada asterisk que deve ser definida em res_odbc.conf.

INI
[asterisk]
connection=asterisk
table=cdr
  • connection=asterisk: nome da conexão ODBC (deve bater com res_odbc.conf)
  • table=cdr: nome da tabela onde os registros de chamadas serão gravados

💡 Essa configuração é opcional para chamadas WebRTC, mas recomendada em ambientes de produção para registrar todas as ligações.

📄 extconfig.conf

Este arquivo define que algumas configurações do Asterisk devem ser carregadas dinamicamente de um banco de dados via ODBC. Isso é útil para gerenciar endpoints SIP (usuários) de forma centralizada.

INI
[settings]
ps_endpoints => odbc,asterisk
ps_auths => odbc,asterisk
ps_aors => odbc,asterisk
  • ps_endpoints, ps_auths, ps_aors: são partes do módulo PJSIP, que define usuários, autenticações e associações.
  • odbc,asterisk: significa que os dados virão de uma fonte ODBC chamada asterisk (configurada em res_odbc.conf).

✅ Essencial para ambientes onde os dados de usuários são armazenados no banco, como sistemas multiusuário ou integrações com backends web.

📄 extensions.conf

Este é o dialplan do Asterisk — a “lógica de chamadas”. No exemplo abaixo, estamos criando um contexto chamado webrtc, que atende qualquer número (_.) e tenta discar para o endpoint SIP correspondente.

  • _.: coringa que corresponde a qualquer número discado.
  • Dial(PJSIP/${EXTEN},60): tenta estabelecer a chamada com o endpoint SIP identificado por ${EXTEN}, com timeout de 60 segundos.
  • Hangup(): encerra a chamada caso o dial falhe ou termine.

⚠️ Certifique-se de que os usuários/dispositivos WebRTC estejam registrados com nomes que combinem com os valores que você vai discar (ex: ramais como 1001, alice, etc.).

📄 http.conf

Este arquivo ativa o servidor HTTP interno do Asterisk e também o suporte a WebSocket (WS/WSS), necessário para que navegadores possam se conectar via WebRTC.

INI
[general]
enabled=yes
bindaddr=0.0.0.0
bindport=8088

tlsenable=yes
tlsbindaddr=0.0.0.0:8089
tlscertfile=/etc/asterisk/keys/asterisk-local-cert.pem
tlsprivatekey=/etc/asterisk/keys/asterisk-local-key.pem
  • enabled=yes: ativa o servidor HTTP.
  • bindaddr=0.0.0.0 / bindport=8088: escuta requisições HTTP normais.
  • tlsenable=yes: habilita o suporte a HTTPS/WSS.
  • tlsbindaddr=0.0.0.0:8089: escuta conexões seguras.
  • tlscertfile e tlsprivatekey: certificados TLS para WebSocket seguro (WSS).

🔒 Importante: para funcionar em navegadores modernos, é obrigatório usar WSS (WebSocket seguro) com certificado válido — inclusive em ambientes de teste. Você pode gerar um autoassinado ou usar Let’s Encrypt.

📄 pjsip.conf

Este é um dos arquivos mais importantes — ele define os transportes, endpoints (usuários), autenticação e associação dos dispositivos SIP. Começamos pelos transportes:

INI
[transport-wss]
type=transport
protocol=wss
bind=0.0.0.0

[transport-ws]
type=transport
protocol=ws
bind=0.0.0.0
  • transport-wss: transporte seguro para WebRTC via WSS (WebSocket Secure). Usado pela maioria dos navegadores.
  • transport-ws: transporte não seguro para ambientes de desenvolvimento (WebSocket simples).
  • bind=0.0.0.0: escuta em todas as interfaces de rede do container.

⚠️ Para WebRTC em produção, use apenas o WSS. O transporte WS sem TLS é bloqueado por navegadores em conexões HTTPS.

📄 res_odbc.conf

Este arquivo configura a conexão ODBC que o Asterisk usará para acessar dados como CDRs e registros do PJSIP (quando integrados ao banco de dados).

INI
[asterisk]
enabled=yes
dsn=Asterisk-DB
username=postgres
password=postgres
pre-connect=yes
  • enabled=yes: ativa essa conexão.
  • dsn=Asterisk-DB: nome do DSN definido no odbc.ini.
  • username e password: credenciais de acesso ao banco de dados (exemplo: PostgreSQL).
  • pre-connect=yes: mantém a conexão ativa durante o tempo de execução.

🧠 Essa seção deve estar alinhada com a configuração no cdr_adaptive_odbc.conf e no extconfig.conf, que fazem referência à conexão asterisk.

📄 rtp.conf

Este arquivo configura o intervalo de portas que o Asterisk usará para o tráfego RTP (Real-time Transport Protocol), que é fundamental para o transporte de áudio nas chamadas.

INI
[general]
rtpstart=10000
rtpend=20000
  • rtpstart=10000: porta inicial do intervalo de portas RTP.
  • rtpend=20000: porta final do intervalo de portas RTP.

🔐 Dica: Certifique-se de que o firewall do seu servidor permita o tráfego nas portas que você definir para o RTP. Para WebRTC, é importante garantir que o tráfego UDP seja liberado para esse intervalo.

📄 sorcery.conf

Este arquivo configura o Asterisk para usar sorcery, que é uma estrutura para carregar configurações dinâmicas para os módulos do Asterisk a partir de fontes externas, como um banco de dados via ODBC.

INI
[res_pjsip]
endpoint=realtime,ps_endpoints
auth=realtime,ps_auths
aor=realtime,ps_aors
  • endpoint=realtime,ps_endpoints: define que os endpoints (usuários) serão carregados em tempo real de uma tabela no banco de dados (configurado em extconfig.conf).
  • auth=realtime,ps_auths: define que as informações de autenticação também virão de uma tabela externa.
  • aor=realtime,ps_aors: associações de objetos de recursos (AOR) serão obtidas dinamicamente.

💡 O uso de “realtime” significa que o Asterisk está configurado para buscar esses dados de um banco de dados em vez de um arquivo estático, proporcionando maior flexibilidade na gestão dos usuários e configurações.

⚙️ Configurações ODBC para PostgreSQL

Na raiz do seu projeto Docker, a pasta ./etc deve conter os arquivos:

  • odbc.ini: define a conexão com o banco (DSN).
  • odbcinst.ini: registra o driver PostgreSQL ODBC no sistema.

Esses arquivos serão montados no container e utilizados pelo Asterisk.

📄 odbc.ini

Este arquivo define o DSN (Data Source Name) usado pelo Asterisk para se conectar ao banco PostgreSQL:

INI
[Asterisk-DB]
Description=PostgreSQL Asterisk DB
Driver=PostgreSQL
Servername=postgres # Deve estar conectado a sua network com esse host
Database=asterisk
Username=postgres
Password=postgres
Port=5432
  • [Asterisk-DB]: nome do DSN (referenciado em res_odbc.conf).
  • Driver=PostgreSQL: nome do driver (deve bater com o odbcinst.ini).
  • Servername=postgres: nome do host ou container do PostgreSQL (se estiver no docker-compose, o nome do serviço).
  • Database=asterisk: nome do banco de dados.
  • Username e Password: credenciais do banco.
  • Port=5432: porta padrão do PostgreSQL.

📄 odbcinst.ini

Este arquivo registra o driver ODBC do PostgreSQL no sistema:

INI
[PostgreSQL]
Description=ODBC for PostgreSQL
Driver=/usr/lib/x86_64-linux-gnu/odbc/psqlodbcw.so

O caminho do driver (Driver) pode variar entre distribuições. No Debian (como usamos no Dockerfile), estes caminhos são comuns. Caso dê erro, use find /usr -name "*psql*.so" no container para confirmar.

Com isso, você conecta o Asterisk a um banco PostgreSQL com suporte a Realtime e CDRs via ODBC.

📞 Integração WebRTC com Asterisk usando JsSIP

Este código Vue + TypeScript define um serviço de chamadas VoIP usando a biblioteca JsSIP, que implementa o protocolo SIP sobre WebSockets.

🧩 Estrutura do Serviço SIP

O arquivo define a classe SIPService, que gerencia:

  • Registro SIP no Asterisk (via WebSocket seguro wss).
  • Recebimento e realização de chamadas.
  • Emissão de eventos para uso no Vue (como incomingCall, onCall, endedCall, etc).
  • Controle de mídia (mute, unmute, encerramento).

🔐 Registro SIP

TypeScript
this.user = "4000";
this.password = "4000";
  • O número de ramal (4000) é usado para registrar o cliente no Asterisk.
  • A conexão é feita via wss://localhost:8089/ws — porta 8089 corresponde ao WebSocket TLS configurado no http.conf.

⚙️ Configuração do Asterisk

O funcionamento depende de:

  • http.conf com tlsenable=yes, bindport=8089.
  • pjsip.conf com os transportes ws e wss.
  • extensions.conf para roteamento de chamadas (Dial(PJSIP/${EXTEN})).
  • sorcery.conf e extconfig.conf configurados para usar ODBC (realtime).

📡 Realizando uma chamada

TypeScript
sipService.makeCall("4001");
  • O método verifica se o usuário está registrado e usa o getUserMedia() para capturar áudio.
  • A chamada é feita para outro ramal SIP (4001), por exemplo.

📥 Atendendo uma chamada

TypeScript
sipService.answerCall();
  • Aceita uma chamada recebida.
  • Usa também o getUserMedia() para abrir o microfone.

🎙️ Eventos disparados

A classe emite eventos que podem ser usados nos componentes Vue:

  • "incomingCall": chamada recebida.
  • "outgoingCall": chamada sendo realizada.
  • "onCall": chamada ativa.
  • "endedCall": chamada encerrada.
  • "canceledCall" e "rejectedCall": cancelamentos/falhas.

🧪 Dicas para testar

  1. Use o console para instanciar e chamar métodos do serviço.
  2. Tenha dois navegadores diferentes (ou abas privadas) com ramais distintos registrados para testes de chamada.

✅ Próximos Passos

Com o Asterisk rodando com suporte completo a WebRTC e JsSIP integrado no frontend, você já pode:

  • Realizar chamadas entre navegadores
  • Conectar dispositivos SIP tradicionais com navegadores
  • Gravar CDRs em tempo real em banco de dados

Se quiser dar o próximo passo, considere:

  • Adicionar autenticação com backend
  • Usar STUN/TURN para suporte em NAT
  • Publicar o serviço com domínio e HTTPS via reverse proxy (ex: Traefik ou Nginx)

0 Comments

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>