Skip to content

fix(bff): DNS explícito para contornar latência multi-homed do SO - #153

Merged
elson-vinicius-lopes merged 5 commits into
developfrom
fix/bff-dns-multihome-latency
Aug 23, 2026
Merged

fix(bff): DNS explícito para contornar latência multi-homed do SO#153
elson-vinicius-lopes merged 5 commits into
developfrom
fix/bff-dns-multihome-latency

Conversation

@elson-vinicius-lopes

Copy link
Copy Markdown
Contributor

O que

Adiciona um override de resolução DNS opcional (BFF_DNS_SERVERS, CSV de IPs) para o BFF, contornando a resolução de nomes lenta do Windows em hosts multi-homed (múltiplas interfaces de rede ativas simultaneamente).

Por quê

Investigação em produção (host BRNDDAPPBLD01) identificou que o login OIDC ficava lento/flaky de forma determinística: a resolução DNS padrão do SO (Smart Multi-Homed Name Resolution) levava ~11-12s consultando todas as interfaces de rede antes de aceitar a resposta correta ao resolver login.microsoftonline.com. dns.setServers() não resolve isso pois só afeta as funções c-ares (dns.resolve()), não dns.lookup() (usado por padrão pelo fetch/undici, via getaddrinfo do SO).

A mitigação registra um lookup customizado baseado em dns.Resolver (c-ares, respeita setServers) e injeta esse lookup no dispatcher global do undici via setGlobalDispatcher(). É opt-in: sem BFF_DNS_SERVERS, nada muda. IPs são validados com net.isIP (fail-closed).

Achado da revisão de segurança (@lp-security — veredito PASS)

P3 (informativo, não bloqueou): setGlobalDispatcher() é global ao processo, não restrito ao OIDC — afeta todo fetch nativo, incluindo o proxy /api → LayoutParserApi (server/src/app.ts, via @fastify/http-proxy), que herda o mesmo dispatcher. Não é uma vulnerabilidade (mesmos servidores DNS confiáveis, validados por IP), mas o comentário original só mencionava o cenário OIDC. Este PR corrige a documentação inline em server/src/dnsOverride.ts para deixar esse escopo explícito — sem mudança de comportamento/lógica.

Ressalva operacional para o deploy

LAYOUTPARSER_API_URL (upstream do proxy /api) por padrão é http://127.0.0.1:5000 (loopback, parseUpstreamUrl em server/src/config.ts), mas a validação aceita qualquer host/porta HTTP(S) sem exigir IP. Se em produção o upstream da API for configurado como hostname (não IP/loopback) e BFF_DNS_SERVERS for setado apenas com os IPs do DNS interno de autenticação, e esse hostname só for resolvível por outro DNS fora dessa lista, o proxy /api quebra — porque o override é global e passa a valer também para a resolução do upstream. Confirmar antes do deploy que os servidores DNS informados em BFF_DNS_SERVERS também resolvem o host de LAYOUTPARSER_API_URL, ou manter o upstream como loopback/IP.

Testes

  • npm run typecheck — OK (ajuste é só de comentário, sem mudança de lógica).

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com

elson-vinicius-lopes and others added 5 commits August 23, 2026 19:21
O login em produção (host BRNDDAPPBLD01) ficava lento/instável porque a
resolução DNS padrão do Windows para login.microsoftonline.com sofre o
comportamento "Smart Multi-Homed Name Resolution": o SO aguarda respostas de
todas as 5 interfaces de rede ativas (várias sem DNS configurado) antes de
aceitar a resposta correta, gerando ~11-12s de atraso fixo em toda chamada de
saída via fetch nativo do MSAL Node (auth.entra.acquire_token_failed com
durationMs ~10.6s, estourando timeout do MSAL e derrubando o login).

dns.setServers() do node:dns não resolve isso: só afeta as funções baseadas
em c-ares (dns.resolve*), não dns.lookup() usado internamente pelo conector
padrão do undici (que o fetch nativo do Node usa). A mitigação real é injetar
um lookup customizado, baseado em dns.Resolver com servidores fixos, no
dispatcher global do undici via setGlobalDispatcher — isso cobre o fetch
global usado pelo MsalOidcClient e GoogleOidcClient.

Aplicado via nova variável opcional BFF_DNS_SERVERS (CSV de IPs), sem
hardcode de infra de produção no código; sem a variável, mantém o
comportamento padrão do Node/SO, restringindo o efeito a hosts confirmadamente
afetados.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Deixa explícito no comentário que setGlobalDispatcher() afeta todo
fetch do processo, incluindo o proxy /api -> LayoutParserApi via
@fastify/http-proxy, não só as chamadas OIDC. Achado P3 da revisão
de segurança (@lp-security, veredito PASS).
Adiciona -DnsServers a Deploy-Iis.ps1: quando ausente/vazio, a linha não é
gerada no Start-Bff.ps1 (server/src/config.ts já trata isso como no-op).
Referencia vars.BFF_DNS_SERVERS no workflow, mesmo padrão de PUBLIC_HOST,
mas sem tornar obrigatório. Valor de produção configurado como variável de
repositório: 172.31.250.251,172.31.250.252 (DNS internos já validados no
host BRNDDAPPBLD01).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ERVERS

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
dnsOverride.ts estava com 0% de cobertura, derrubando os thresholds
globais do server/ (linhas/funções/statements 85%, branches 80%) e
quebrando o gate de CI do PR #153. Adiciona testes para o caso no-op
(sem servidores), aplicação do dispatcher global do undici, e a função
lookup customizada (IPv4/IPv6, fallback, all, e propagação de erro),
mockando undici e node:dns.
@elson-vinicius-lopes
elson-vinicius-lopes merged commit fb9a96d into develop Aug 23, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant