Conexões de API com IPv6

Acompanhamento de: Conexão de API via ipv6 vs. ipv4 - suporte - Discourse Meta

Recentemente atualizei o Node.js de 18 para 20 e minha aplicação de repente parou de receber respostas da API do Discourse. Levei um tempo para descobrir que estava relacionado ao problema acima. Verifiquei isso fazendo uma conexão apenas via IPv4 como:

import {Agent} from 'node:https'
import axios from 'axios'
import {env} from 'node:process'
export const axiosDiscourse = axios.create({
  baseURL: 'https://<url-do-discourse>',
  headers: {
    'api-key': env['DISCOURSE_KEY'],
    'api-username': env['DISCOURSE_USERNAME']
  },
  httpsAgent: new Agent({
    family: 4
  })
})

a parte importante sendo a especificação do Agente HTTP - eu estava usando sem isso antes. Isso agora funciona, mas eu estava tentando migrar do Axios, para que eu possa usar outras bibliotecas baseadas em fetch como Wretch (principalmente para reduzir o tamanho do pacote usando isso no frontend também): elbywan/wretch: A tiny wrapper built around fetch with an intuitive syntax. :candy: (github.com). No entanto, não há opção para especificar IPv4 ou IPv6 com fetch. Assim, pensei que precisaria:

  1. Forçar o uso apenas de IPv4 de alguma forma e, apesar de todas as minhas tentativas até agora, isso não foi possível
  2. Verificar com o Discourse como eu poderia fazer isso funcionar no IPv6.

Estou me conectando a várias outras APIs da minha aplicação, nenhuma tem esse problema, é apenas a conexão com o Discourse que está falhando.

Este é o erro que estou recebendo, caso ajude:

Error: connect ETIMEDOUT 184.105.99.43:443
    at createConnectionError (node:net:1634:14)
    at Timeout.internalConnectMultipleTimeout (node:net:1685:38)
    at listOnTimeout (node:internal/timers:575:11)
    at processTimers (node:internal/timers:514:7) {
  errno: -110,
  code: 'ETIMEDOUT',
  syscall: 'connect',
  address: '184.105.99.43',
  port: 443
},
Error: connect ENETUNREACH 2602:fd3f:3:ff01::2b:443 - Local (:::0)
    at internalConnectMultiple (node:net:1176:40)
    at Timeout.internalConnectMultipleTimeout (node:net:1687:3)
    at listOnTimeout (node:internal/timers:575:11)
    at processTimers (node:internal/timers:514:7) {
  errno: -101,
  code: 'ENETUNREACH',
  syscall: 'connect',
  address: '2602:fd3f:3:ff01::2b',
  port: 443
}

O interessante é que, ao contrário do tópico mencionado acima, eu não recebo resposta após muito tempo. Minha solicitação falha imediatamente com este erro. A chamada da API funciona bem no navegador, curl e qualquer outra coisa que eu possa testar.

A minha forma de fazer uma solicitação à API não importa, desde que eu esteja fazendo uma solicitação da minha aplicação. Simplesmente falha e funciona apenas usando a opção de família, como mencionado acima. No tópico vinculado, vejo isso sendo mencionado:

Você precisará investigar por que as conexões IPv6 não funcionam em sua rede.

Tenho 2 preocupações com isso:

  1. Não sei como verificar especificamente isso.
  2. Não tenho certeza por que isso seria um problema apenas com o Discourse, e apenas com minha aplicação.
1 curtida

Outro ponto a observar é que isso acontece apenas dentro da minha instância do WSL. Se eu executar meu aplicativo diretamente no meu dispositivo Windows host, ele consegue se conectar normalmente.

Sei que isso provavelmente é algo muito específico da minha configuração, mas simplesmente não sei onde procurar problemas no momento. Quaisquer dicas seriam úteis!

1 curtida

Parece que a biblioteca que você está usando está tentando se conectar via IPv4 e IPv6; isso é uma boa notícia e significa que você não tem o mesmo problema que aqui!

Vamos abordá-los separadamente:

Isso significa que o seu lado enviou um TCP SYN para tentar a conexão com a instância hospedada, mas não obteve resposta. Isso geralmente significa uma das seguintes opções:

  • a solicitação não chegou ao servidor
  • o servidor (ou algo no caminho) a descartou deliberadamente em silêncio
  • a resposta não retornou à sua máquina

Como

é provável que seja um problema com a configuração de rede em sua máquina.

Isso significa que sua pilha de rede disse “Não consigo chegar lá” e está tudo bem, já que o que você está usando evidentemente volta para o IPv4.

Olhando para tudo, suspeito que:

  • O IPv4 falha da sua máquina (não está claro se isso é verdade, por favor, verifique - “consegue se conectar normalmente” pode significar que está usando IPv4 ou IPv6)
  • O IPv4 falha do seu contêiner WSL
  • O IPv6 funciona da sua máquina
  • O IPv6 falha do seu contêiner WSL

Por favor, envie uma mensagem para @team com seu endereço IPv4 externo e verificaremos se ele está sendo deliberadamente descartado - temos alguns intervalos de IP mal comportados bloqueados e isso nos permitirá descartar essa possibilidade.

Se, no entanto, tanto o IPv4 quanto o IPv6 funcionam da sua máquina, mas falham do seu contêiner WSL, isso é algo que você precisará resolver em relação à sua configuração do WSL.

Muito obrigado por retornar.\n\nEm relação aos seus suspeitos, eis o que consegui testar até agora:\n\n- Tentei desativar o IPv6 das configurações do Windows:\n\n

\n\nO que, pelo que entendi, deveria fazer com que as conexões fossem apenas via IPv4. Se sim, isso funcionou.\n\n- Tentei executar:\n\n\n curl -4 https://\u003chost\u003e/latest.json?order=created\n\n\nDo WSL e funcionou bem (obtive a resposta)\n\n- Não tenho certeza de como posso testar apenas o IPv6 porque, assim que desativo o IPv4, semelhante ao IPv6 da captura de tela acima (enquanto deixo o IPv6 ativado), meu PC basicamente ficou desconectado da internet - todas as conexões falharam, o que era esperado.\n\n- Tentei:\n\n\n curl -6 https://\u003chost\u003e/latest.json?order=created -v\n* Trying 2602:fd3f:3:ff01::2b:443...\n* Immediate connect fail for 2602:fd3f:3:ff01::2b: Network is unreachable\n* Closing connection 0\ncurl: (7) Couldn't connect to server\n\n\nDo WSL e falhou… instantaneamente.\n\nTive alguns problemas com o WSL hoje, então acabei configurando uma instalação limpa. Esta é uma instância novíssima com apenas asdf e Node.js instalados (e todos os pacotes do sistema atualizados). Não tenho certeza se isso ainda está relacionado a alguma má configuração no lado do WSL - eu deveria estar usando todas as configurações padrão no momento.\n\nEstou compartilhando meu endereço IPv4 público com o grupo mencionado.

Bem, não vejo uma maneira de enviar uma mensagem privada ainda, provavelmente porque sou um novo usuário.

Algo mais interessante… quando estava verificando meu endereço IPv4 público, o site tentou me mostrar meu endereço IPv6 também e disse, IPv6 não detectado. Então, fui verificar se eu tinha uma conexão IPv6, e encontrei esta página: Como configurar o serviço IPv6 no roteador sem fio TP-Link

Ela mostra que os roteadores devem ter uma seção dedicada para usar IPv6. Meu roteador não tem uma e eu também não recebo a opção PPPoE v6 como mostrada lá. Então, talvez, meu roteador não suporte IPv6 de forma alguma - o que pode ser o motivo pelo qual as conexões IPv6 estão falhando (e também por que basicamente perdi a conectividade com a internet quando desabilitei o IPv4 nas configurações do Windows).

EDIT: Eu tenho este roteador TL-WR841N | Roteador Wi-Fi N de 300 Mbps | TP-Link Índia e diz que suporta IPv6 :thinking:

EDIT2: Mas usar algo como: v6.testmyipv6.com me dá ERR_NAME_NOT_RESOLVED, então parece que o IPv6 realmente não está funcionando para mim.

Se esse for o problema, ainda não sei por que isso começou a acontecer de repente. Estava funcionando bem por um bom tempo.

Eu te dei uma pequena ajuda. :slight_smile: Você deve ver o botão de mensagem se clicar em @team agora. :+1:

1 curtida

Obrigado, enviado!

1 curtida

Ponto de dados adicional, mudei para o hotspot da minha rede móvel que usa IPv6. Agora posso verificar usando:

curl -6 https://<host>/latest.json?order=created -v
* Tentando 2602:fd3f:3:ff01::2b:443...
* Falha de conexão imediata para 2602:fd3f:3:ff01::2b: Rede inacessível
* Fechando conexão 0
curl: (7) Não foi possível conectar ao servidor

Ainda falha de forma semelhante. No entanto, com o IPv4 desativado nas configurações do Windows, consigo acessar a internet, diferente de antes. Então, novos dados:

  • IPv4 no Windows: Funciona
  • IPv6 no Windows: Funciona
  • IPv4 no WSL: Funciona
  • IPv6 no WSL: Falha

Se eu não especificar -4 ou -6 para o curl, ele volta para o IPv4 (o IPv6 falha imediatamente):

curl https://<host>/latest.json?order=created -v
* Tentando 184.105.99.43:443...
* Tentando 2602:fd3f:3:ff01::2b:443...
* Falha de conexão imediata para 2602:fd3f:3:ff01::2b: Rede inacessível
* Conectado a <host> (184.105.99.43) na porta 443 (#0)

Também executei:

ping -6 google.com

Tanto do Windows quanto do WSL. Funciona no Windows, falha no WSL. Acho que agora tenho informações e validação suficientes de que algo está dando errado com a conectividade IPv6 da minha instância WSL. Parece um problema: cannot reach ipv6 only address · Issue #4518 · microsoft/WSL (github.com)

Finalmente!

Com base na discussão vinculada acima, consegui adicionar

[experimental]
networkingMode=mirrored

ao .wslconfig e isso me deu conectividade IPv6 dentro da minha instância WSL. Agora posso executar com sucesso:

curl -6 https://<host>/latest.json?order=created

Ainda não funciona no meu Wi-Fi, e isso provavelmente ocorre porque este roteador antigo não suporta IPv6. Funciona bem ao usar o hotspot do meu telefone.

Muito obrigado @JammyDodger pelas dicas, você me guiou na direção certa!

OK, então algo mudou evidentemente entre a postagem original e esta, já que você estava recebendo:

Fico feliz em ver que está funcionando agora.

Sim, isso ainda me intriga. Como mencionei antes, eu conseguia enviar uma requisição curl através do WSL antes e isso funcionava. De alguma forma, estava falhando usando Axios na minha aplicação (talvez seja uma coisa do Axios ou do Node.js?).

De alguma forma, o curl -4 ainda funciona, e o Axios também funciona quando especifico o httpFamily como mostrado na minha postagem original. Mas esse não é um erro pelo qual vou perder mais sono.

Apenas para verificar, voltei para o Node.js 18 e consegui me conectar sem especificar o httpFamily, então isso definitivamente é algo que mudou no Node.js 19 ou 20. Mas por causa disso, pelo menos descobri sobre essa coisa de IPv6, caso contrário, eu ainda não teria pesquisado ou aprendido sobre isso.

Também consigo executar o código com o bun em vez do Node.js sem ter que especificar a coisa do IPv4. Entrei em contato com o Node.js: https://github.com/orgs/nodejs/discussions/50826