O que estou pensando agora: Interfaces adaptativas em sistemas web complexos e mudanças em tempo real com LLMs

← Todos os escritos

Escritos

Investigando uma requisição HTTPS e modelo OSI

Neste artigo

Considere uma aplicação que chama uma API por HTTPS. A requisição demora alguns segundos e termina com um erro. O serviço está fora do ar? O nome não resolveu? A conexão chegou ao servidor, mas o certificado foi rejeitado?

Esses problemas acontecem em etapas diferentes. O modelo OSI ajuda a organizar a investigação, desde que não seja tratado como uma lista de sete processos que toda requisição executa.

As sete camadas

OSI é um modelo de referência para comunicação entre sistemas. As camadas separam responsabilidades:

CamadaResponsabilidade no modeloO que observar em uma investigação
7. AplicaçãoServiços de comunicação usados pelas aplicaçõesRequisição e resposta HTTP, nomes DNS
6. ApresentaçãoRepresentação e transformação dos dadosFormato e codificação dos dados
5. SessãoOrganização e controle do diálogoEstado e continuidade da comunicação
4. TransporteComunicação entre os pontos finaisConexão TCP, portas, retransmissões
3. RedeEndereçamento e encaminhamentoIP de destino, rotas, mensagens ICMP
2. EnlaceComunicação no enlace localQuadros Ethernet ou Wi-Fi, resolução de vizinhos
1. FísicaTransmissão de sinaisCabo, rádio, sinal e estado do link

Na pilha TCP/IP, essas responsabilidades são agrupadas de outra forma. A arquitetura descrita na RFC 1122 usa enlace, internet, transporte e aplicação. Não existe uma correspondência exata de uma camada para outra entre os dois modelos.

TLS, por exemplo, participa da proteção e da negociação da comunicação. Colocá-lo em uma única caixa OSI pode servir como aproximação didática, mas não descreve sozinho como ele funciona sobre o transporte. Um cookie de sessão HTTP também não representa a implementação da camada 5.

Escolher o caminho que vamos observar

Para reduzir as variações, o exemplo força HTTP/1.1 sobre TLS e TCP. HTTP/3 usa QUIC sobre UDP; nesse caso, procurar uma conexão TCP seria investigar o protocolo errado.

Execute em uma API que você administra ou está autorizado a consultar. O endereço abaixo é um placeholder, precisa ser substituído. No PowerShell, use curl.exe para chamar o executável:

curl --http1.1 --verbose --connect-timeout 5 --max-time 15 https://api.example.com/health

--connect-timeout limita a fase de conexão, incluindo resolução de nome e negociação necessária para estabelecê-la. --max-time limita a operação completa. O modo detalhado mostra a progressão da chamada.

Um diagnóstico deve registrar horário, URL, rede de origem, resultado e código de saída. Evite colocar tokens e cookies em um log que será compartilhado: o modo detalhado pode mostrar esses cabeçalhos.

1. Resolver o nome

Antes de conectar, o cliente precisa obter um endereço para api.example.com. O resultado pode vir do cache, do arquivo de hosts ou de um resolvedor DNS, dependendo da configuração do sistema.

Resolve-DnsName api.example.com

Esse comando é do PowerShell no Windows. Em outros ambientes, dig ou nslookup permitem investigar a resolução.

Verifique quais endereços foram retornados, inclusive IPv4 e IPv6. Um cliente pode falhar em um deles e funcionar no outro. Compare também o resolvedor da rede local com o usado pela aplicação.

Um nome resolvido comprova que foi obtido um endereço. Não comprova que existe um serviço escutando naquele destino.

DNS é um protocolo de aplicação. Portanto, uma falha na resolução não deve ser chamada automaticamente de “erro de camada 3” só porque ainda não temos o IP da API. O próprio DNS depende de comunicação de rede para obter a resposta quando não há um resultado local.

2. Estabelecer a conexão TCP

Com o endereço escolhido, o cliente tenta conectar à porta 443. Em uma conexão TCP nova, o estabelecimento envolve SYN, SYN/ACK e ACK.

No Windows, uma verificação isolada é:

Test-NetConnection api.example.com -Port 443 -InformationLevel Detailed

TcpTestSucceeded informa o resultado da conexão TCP feita por esse comando. Não verifica o certificado nem a resposta HTTP.

Se houver timeout, precisamos investigar rota, regras de firewall, disponibilidade do destino e caminho de retorno. O mesmo sintoma pode ter mais de uma causa. Se recebermos um reset ou “connection refused”, houve uma rejeição observável; isso ainda não identifica sozinho qual componente rejeitou.

ping usa ICMP, não TCP na porta 443. Um host pode responder ao ping e ter a porta fechada. Também pode bloquear ICMP e atender HTTPS normalmente.

3. Negociar TLS

Depois de estabelecer TCP, cliente e servidor negociam TLS. O cliente valida o certificado considerando, entre outras coisas, o nome solicitado, a cadeia de confiança e a validade temporal.

Se o curl mostra que conectou, mas termina com erro de certificado, já temos evidência de que a conexão chegou a um endpoint TLS. Agora a investigação precisa considerar o certificado apresentado e a configuração de confiança do cliente.

Um erro frequente é testar https://IP_DO_SERVIDOR/ no lugar do nome. Isso altera o nome validado e pode alterar o certificado escolhido pelo servidor. Para testar um IP específico preservando o nome da URL, use:

curl --http1.1 --verbose --resolve api.example.com:443:203.0.113.10 https://api.example.com/health

203.0.113.10 é um endereço reservado para documentação, não um destino de teste. Substitua pelo IP real autorizado.

--resolve fornece a associação nome/porta/IP para essa execução. O nome da URL continua sendo usado na validação do certificado, no SNI e no cabeçalho HTTP. Isso permite comparar o caminho normal de resolução com um destino escolhido. A documentação do curl descreve esse uso de resolução explícita.

Usar -k desativa a verificação do certificado. Uma chamada que funciona assim não demonstra que a configuração TLS está correta. Para uma autoridade interna, forneça a CA esperada com --cacert, em vez de remover a validação.

4. Observar HTTP

Com TLS estabelecido, o cliente envia a requisição HTTP. Uma resposta 401, 403, 404 ou 500 indica que algum componente HTTP respondeu.

Esse componente pode ser um proxy, gateway ou a própria aplicação. O status sozinho não prova que o código do backend foi executado. Cabeçalhos, corpo, logs e IDs de correlação ajudam a descobrir quem produziu a resposta.

Por padrão, o curl pode terminar com código de saída 0 mesmo recebendo HTTP 500. Para tratar status HTTP a partir de 400 como falha sem perder o corpo:

curl --http1.1 --fail-with-body --show-error --connect-timeout 5 --max-time 15 https://api.example.com/health

O código de saída do processo e o status HTTP são informações diferentes. Registre os dois.

Medir as etapas

Podemos pedir ao curl os tempos acumulados desde o início da operação, usando a opção write-out:

curl --http1.1 --silent --show-error --output resposta.json --write-out 'dns=%{time_namelookup} tcp=%{time_connect} tls=%{time_appconnect} primeiro_byte=%{time_starttransfer} total=%{time_total} status=%{http_code}\n' https://api.example.com/health

time_connect inclui o tempo anterior à conexão. Ele não representa apenas o tempo do TCP. Em uma chamada nova, direta, sem redirecionamento e com uma única tentativa, as diferenças entre os valores ajudam a estimar a duração de cada etapa.

time_starttransfer mede até o primeiro byte da resposta. A diferença depois de TLS inclui envio da requisição e espera pela resposta. Não é uma medida isolada do tempo de CPU do servidor.

Proxy, cache DNS, reutilização de conexões, múltiplos endereços e redirecionamentos mudam a interpretação. Por isso, compare chamadas feitas nas mesmas condições.

Captura de pacotes

Quando o log do cliente não explica a falha, uma captura feita no ponto correto ajuda a observar o que chegou à rede. No Wireshark, filtros de exibição úteis são:

dns
tcp.port == 443
tcp.analysis.retransmission
tls

Esses são filtros de exibição, aplicados depois da captura. tcp.port == 443 também pode incluir serviços que usam outro protocolo nessa porta.

Se aparecer um SYN sem resposta, a captura mostra a tentativa naquele ponto de observação. Ela não prova qual firewall ou equipamento descartou o pacote. Uma captura no servidor pode mostrar uma situação diferente da captura no cliente.

Como o tráfego HTTP está cifrado, normalmente não veremos os cabeçalhos nem o corpo da aplicação. O nome DNS também pode não aparecer: a resposta pode estar no cache ou a resolução pode usar DNS cifrado. Ausência no filtro não significa ausência da etapa.

Separar sintoma de causa

Uma forma de registrar a investigação é anotar a última etapa comprovada e a primeira que falhou:

Resultado observadoO que já foi demonstradoPróxima verificação
Nome não resolvidoO cliente não obteve um endereço utilizávelResolvedor, nome, cache e configuração local
TCP não estabeleceHouve tentativa de conexão sem sucessoDestino, porta, rota e regras de rede
Certificado rejeitadoUm endpoint TLS foi alcançadoNome, cadeia de confiança, relógio e certificado
HTTP 403Um componente HTTP negou a requisiçãoIdentidade, permissão e política do gateway ou serviço
HTTP 200 com corpo erradoHouve resposta HTTP de sucessoContrato, dados e comportamento da aplicação

O modelo OSI dá uma organização para essas perguntas. A evidência vem da requisição, dos logs e das capturas. Chamar tudo de “problema de rede” esconde as diferenças que precisamos investigar.

Referências