Usuário reportou que 1502 ligando pra 1503 (dois telefones IP reais, ambos registrados) não completava a chamada. Três bugs em camadas diferentes, cada um só confirmado lendo o log/capturando pacote real — nunca por suposição: 1. Registro: os dois ramais registravam com Contact apontando pro MESMO IP público compartilhado desta rede (a VM nunca tem IP público próprio, é sempre RFC1918 atrás do NAT do escritório) — originar uma chamada tentava mandar o INVITE de volta pra esse IP público, hairpin NAT clássico, falha instantânea (503). Fix: NDLB-received-in-nat-reg- contact (Contact salvo vira o IP realmente observado no pacote). De quebra, aplicado network_mode: host no serviço freeswitch (pedido explícito do usuário) — tira o Docker NAT/bridge do meio. Quebra em cascata corrigida: fs-config vira alcançável só via 127.0.0.1:8080 (não mais nome de serviço), workers ESL (fs-events/predictive-dialer) passam a usar host.docker.internal. 2. Áudio: com o registro corrigido, a chamada completava mas sem RTP — local-network-acl="localnet.auto" só cobria a subnet da própria interface do FreeSWITCH, tratando ramais de OUTRAS subnets do mesmo escritório como "de fora" e trocando o SDP pelo IP público de novo. Fix: ACL própria (b2bcall_lan, cobre todo RFC1918) referenciada em local-network-acl. 3. Chamada morrendo sozinha em exatos 32s (Timer H do RFC 3261): mesmo com áudio ok, o 200 OK que o FreeSWITCH manda pro ramal que recebeu a chamada ainda tinha Contact com o IP público — o telefone nunca manda o ACK de volta, FreeSWITCH retransmite sozinho até desistir. Só confirmado com tcpdump (instalado nesta sessão) capturando o pacote byte a byte. Fix: ext-rtp-ip/ext-sip-ip (STUN, sempre resolvem pro IP público) removidos do profile "internal" — sem endereço "externo" configurado, o FreeSWITCH nunca mais tem como escolher errado. Confirmado resolvido pelo usuário com chamadas reais nos dois sentidos, áudio bidirecional, sobrevivendo bem além dos 32s que travavam antes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BFaBaBSQGhyXGEgtTYZGV8
68 lines
3.9 KiB
XML
68 lines
3.9 KiB
XML
<configuration name="acl.conf" description="Network Lists">
|
|
<network-lists>
|
|
<!-- ACL propria pro Event Socket: loopback (fs_cli local) + rede interna
|
|
do Docker Compose (outros containers, ex.: b2bcall-fs-events).
|
|
172.16.0.0/12 cobre o range padrao que o Docker aloca pras redes
|
|
bridge de projeto (confirmado: b2bcall_default = 172.18.0.0/16).
|
|
Nunca 0.0.0.0/0 — nao e' pra ser alcancavel de fora do host. -->
|
|
<list name="b2bcall_internal" default="deny">
|
|
<node type="allow" cidr="127.0.0.0/8"/>
|
|
<node type="allow" cidr="::1/128"/>
|
|
<node type="allow" cidr="172.16.0.0/12"/>
|
|
</list>
|
|
|
|
<!-- PHASE 68 — achado real: depois de corrigir o registro (NDLB-
|
|
received-in-nat-reg-contact, Dockerfile), a chamada completava
|
|
mas sem áudio. Causa: `local-network-acl="localnet.auto"`
|
|
(padrão vanilla) só cobre a subnet da PRÓPRIA interface do
|
|
FreeSWITCH (10.10.32.0/24, com network_mode: host) — os ramais
|
|
de verdade estão em OUTRAS subnets do mesmo escritório
|
|
(192.168.40.0/24, 192.168.44.0/24), então o FreeSWITCH os
|
|
tratava como "fora da rede local" e trocava o RTP/SIP anunciado
|
|
no SDP pelo IP público compartilhado (Ext-RTP-IP/Ext-SIP-IP,
|
|
191.240.175.55) — o mesmo hairpin NAT de antes, só que na
|
|
mídia em vez do registro. Esta VM nunca tem IP público próprio
|
|
(é sempre RFC1918 atrás do NAT do escritório), então qualquer
|
|
cliente que realmente CONSEGUE alcançar este servidor já é,
|
|
por definição, parte dessa rede privada — cobrir todo o RFC1918
|
|
aqui é seguro pra esta implantação (nunca é "de fora" de
|
|
verdade) e evita ter que listar cada subnet/VLAN do escritório
|
|
uma por uma. -->
|
|
<list name="b2bcall_lan" default="deny">
|
|
<node type="allow" cidr="10.0.0.0/8"/>
|
|
<node type="allow" cidr="172.16.0.0/12"/>
|
|
<node type="allow" cidr="192.168.0.0/16"/>
|
|
</list>
|
|
|
|
<!-- PHASE 68 (continuação) — achado real: com áudio já corrigido, o
|
|
200 OK que o FreeSWITCH manda pra um ramal como 1503 ainda tinha
|
|
`Contact: sip:1502@191.240.175.55:5060` (o IP público de novo) —
|
|
o telefone nunca manda o ACK de volta (não é dele, não sabe
|
|
voltar), o FreeSWITCH fica retransmitindo o 200 OK sozinho
|
|
(0.5s/1s/2s/4s/4s...) até desistir em exatos 32s (Timer H do
|
|
RFC 3261) e derrubar a chamada. Causa: o Contact que o
|
|
FreeSWITCH usa pra SE IDENTIFICAR numa resposta SIP é decidido
|
|
por `apply-nat-acl` (nat.auto), não por `local-network-acl` —
|
|
são duas checagens INDEPENDENTES (uma pro SDP/mídia, outra pro
|
|
cabeçalho SIP). `nat.auto` (RFC1918 exceto a própria subnet do
|
|
FreeSWITCH) continua marcando ramais de OUTRAS subnets do
|
|
escritório como "precisa de IP externo" nesta camada, mesmo já
|
|
não afetando mais o SDP. Não dá pra simplesmente trocar
|
|
`apply-nat-acl` pra `b2bcall_lan` (mesmo sentido de match de
|
|
`local-network-acl`) — isso pararia de marcar esses ramais como
|
|
NAT'd, e SEM essa marcação o `NDLB-received-in-nat-reg-contact`
|
|
(Dockerfile, o fix do REGISTRO) para de disparar, voltando o
|
|
bug original. Por isso esta é uma ACL NOVA e SEPARADA, com o
|
|
sentido INVERTIDO de `b2bcall_lan`: "NAT'd de verdade" só quem
|
|
está FORA de todo RFC1918 conhecido desta implantação — nunca
|
|
alcançável de verdade nesta VM (nunca tem IP público próprio),
|
|
mas mantém o comportamento correto se um dia existir uma
|
|
conexão genuinamente externa (trunk real via IP público). -->
|
|
<list name="b2bcall_external_nat" default="allow">
|
|
<node type="deny" cidr="10.0.0.0/8"/>
|
|
<node type="deny" cidr="172.16.0.0/12"/>
|
|
<node type="deny" cidr="192.168.0.0/16"/>
|
|
</list>
|
|
</network-lists>
|
|
</configuration>
|