# Arquitetura de Rede ## Estado atual (fase FreeSWITCH inicial) `freeswitch` roda na rede padrão do Docker Compose (bridge, `b2bcall_default`), igual a `postgres` e `redis`. Nenhuma porta é publicada no host — nem 8021 (ESL), nem SIP (5060/5080), nem RTP. Isso é intencional: ainda não existe nenhum tronco SIP real nem ramal externo, então não há motivo pra expor nada. `apps/api` roda hoje **direto no host** (fora do Docker), então usa `APP_DATABASE_URL`/`REDIS_URL` apontando pra `localhost` nas portas publicadas pelo Postgres/Redis. Ela não consegue (nem precisa, ainda) alcançar o FreeSWITCH. ## Decisão pendente: `network_mode` do FreeSWITCH (agente.md secao 19) Quando existir um tronco SIP real (fase Trunks), será preciso decidir entre: - **`network_mode: host`**: mais simples pra SIP/RTP (sem NAT entre o container e a rede), mas perde isolamento de rede do Docker. - **macvlan/ipvlan**: dá ao FreeSWITCH um IP próprio na rede física, sem expor outros serviços do host: mais trabalho de configurar, melhor isolamento. Não decidido ainda — só vira relevante quando houver um carrier/SBC real pra conectar (secao 17: "FreeSWITCH não deverá depender de IP SIP público" — a topologia esperada é `Internet → OpenSIPS → rede SIP privada → FreeSWITCH`, então o FreeSWITCH em si tende a ficar em rede privada mesmo, o que favorece manter bridge/macvlan em vez de host). ## Achado real (PHASE 65): VM atrás de roteador, ramal externo sem áudio Esta VM de laboratório está atrás de um roteador (NAT) — o IP da interface de rede (`ens18`) é privado (`10.10.32.x`), o roteador é quem faz NAT pro IP público real. Reportado pelo usuário: um softphone externo registrava com sucesso, mas sem áudio. Diagnóstico (contadores de pacotes do `iptables`, não suposição): 10 pacotes chegaram em `5060/udp` (SIP), **zero** pacotes chegaram em qualquer porta da faixa de RTP (`16384-16584/udp`). O REGISTER funciona porque a resposta trafega de volta pelo mesmo "buraco" NAT que o próprio pacote do cliente abriu — mas RTP usa portas completamente diferentes, como um fluxo NOVO. Sem uma regra de **port forward no roteador** pra essa faixa (apontando pro IP privado desta VM), esses pacotes nunca chegam até o Docker/FreeSWITCH. Do lado desta VM estava tudo certo: `docker-compose.yml` publica a faixa de RTP pra rede (não só loopback), `Ext-RTP-IP`/`Ext-SIP-IP` resolvem certo via STUN (`sofia status profile internal` mostra o IP público real), e a detecção de NAT do próprio FreeSWITCH (`apply-nat-acl value="nat.auto"`, `nat.auto` é uma ACL auto-gerada pelo core do FreeSWITCH — RFC1918 exceto a própria rede local do container, não precisa existir em `acl.conf.xml`) funciona corretamente (testado direto via `fs_cli -x "acl nat.auto"`). **Não tem fix de código pra isso** — é infraestrutura de rede fora do controle desta aplicação. Checklist pra quem for expor telefonia real atrás de um roteador: encaminhar UDP `5060` e toda a faixa RTP (`16384-16584`, Dockerfile do FreeSWITCH) pro IP privado da VM, sem tradução de porta. ## Quando `apps/api` virar container Hoje ela roda no host por conveniência de desenvolvimento. Quando virar o serviço Docker `b2bcall-api` (agente.md secao 14), as connection strings precisam trocar de `localhost` pros hostnames internos do compose (`postgres`, `redis`, `freeswitch`) — ver nota em docs/AUTHENTICATION.md sobre essa pegadinha.