Resumo

  • ALPN transporta a oferta ordenada de identificadores opacos do cliente e permite ao servidor escolher um valor comum. A seleção vale para os dados de aplicação daquela conexão TLS, não para outro trecho nem para uma capacidade permanente do serviço.
  • Um proxy que termina TLS é servidor no lado cliente e um novo cliente no lado origem. HTTP/2 embaixo e HTTP/1.1 em cima podem ser dois resultados corretos; cada conexão precisa da própria evidência.
  • Registro IANA, configuração e callback instalado indicam possibilidade. Prova operacional exige oferta, seleção ou alerta, execução do callback, conclusão do handshake e início do protocolo, tudo ligado à conexão certa.

A tradução não era o defeito

No trecho externo, ClientHello continha duas opções; EncryptedExtensions devolvia h2; Finished autenticava a transcrição; o prefácio e SETTINGS de HTTP/2 confirmavam o uso real. Não havia motivo para negar esse resultado.

Só que a origem não era a outra ponta. A borda havia descriptografado a solicitação e aberto novo TCP/TLS com chaves, política e identidade próprias. Nesse trecho, podia selecionar http/1.1 ou não obter ALPN e aplicar fallback explícito.

Converter protocolos pode ser uma escolha saudável. O erro surgiu quando a telemetria apagou os dois IDs de conexão e o evento de terminação, copiando h2 para o cadastro da origem. Um fato de escopo preciso virou uma conclusão sobre topologia.

A negociação compara octetos exatos

A IANA atribui o valor 16 a application_layer_protocol_negotiation. Na RFC 7301, cada nome é uma sequência opaca de um a 255 octetos, com prefixo de comprimento. Elementos vazios ou truncados são inválidos.

Não cabe normalizar caixa, aparar ou fazer correspondência aproximada. HTTP/2 sobre TLS usa exatamente h2. A RFC 9113 proíbe oferecer ou selecionar h2c em ALPN sobre TLS.

A ordem mostra a preferência do cliente, mas o servidor escolhe dentro da interseção segundo sua política. h2 em primeiro lugar não prova seleção. h2 num arquivo também não prova que aquela instância e aquele contexto o executaram.

Sem interseção, a RFC 7301 exige o alerta fatal no_application_protocol. A RFC 9325 reforça o tratamento estrito para reduzir confusão entre protocolos. O servidor não pode escolher um valor que o cliente nunca ofereceu.

O resultado é firme, mas local

Depois da seleção, o protocolo é definitivo para os dados daquela conexão. Quem retorna h2 não pode interpretar o mesmo fluxo como HTTP/1.1. O prefácio de conexão e SETTINGS fornecem confirmação adicional para HTTP/2.

Assim, há uma sequência de evidência: oferta, resposta, Finished autenticado, prefácio válido e troca útil. ClientHello isolado não comprova handshake concluído. ALPN bem-sucedido sem prefácio não comprova aplicação funcionando.

O resultado também não promete o futuro. A RFC 9113 alerta que suporte anterior não é sinal forte para outra conexão, pois instâncias, configuração e rede mudam. A conexão é a unidade correta de atribuição.

O terminador mantém dois livros

Para o navegador, o proxy é servidor TLS; para a origem protegida por TLS, é cliente. Cada papel gera oferta, seleção, alerta e geração de política independentes.

As opções oficiais do Envoy mostram essa separação. O upstream pode usar explicitamente o protocolo downstream, negociar HTTP/1.1 ou HTTP/2 por ALPN de forma independente, ou cair para HTTP/1.1 quando ALPN estiver ausente. Continuidade é comportamento configurado e observado, não herança automática.

Um túnel puro é diferente: o intermediário talvez apenas encaminhe bytes e não conheça a seleção interna. O cabeçalho da RFC 7639 pode declarar protocolos pretendidos em CONNECT, mas intenção não comprova handshake dentro do túnel.

O registro defensável guarda um tuple downstream, outro upstream e um evento de terminação, tradução ou túnel que os relaciona sem fundi-los.

O caminho real dentro da biblioteca

No OpenSSL, zerar o comprimento da lista do cliente remove a extensão. Se ClientHello não propõe ALPN, o callback do servidor não é chamado. Callback instalado não significa callback executado.

O callback de servername ocorre antes e pode substituir SSL_CTX; só depois roda ALPN. A política efetiva pode pertencer ao host virtual, não ao inventário global.

SSL_get0_alpn_selected retorna memória emprestada, não terminada por NUL, junto com comprimento. Tratar o valor como string comum pode truncar ou alterar o dado.

Há uma armadilha importante em SSL_select_next_proto: sem sobreposição, a função ainda põe o primeiro item do cliente na saída e devolve OPENSSL_NPN_NO_OVERLAP. Para ALPN, essa saída deve ser ignorada. Registrar antes de verificar o retorno cria uma negociação falsa.

Ausência, vetor inválido, falta de sobreposição, NOACK, falha do callback e seleção bem-sucedida são resultados diferentes. Um booleano não preserva o limite de falha.

Reanudar não reaproveita a seleção

A RFC 7301 diz que ALPN pertence à conexão, não à sessão. Em reanuação, os valores antigos são irrelevantes e as novas mensagens governam.

Um ticket emitido quando h2 estava ativo não obriga a próxima instância a escolhê-lo. Copiar a seleção anterior para a nova linha de telemetria esconde mudança de configuração.

No TLS 1.3, os parâmetros de 0-RTT associados à PSK incluem ALPN. O servidor só pode aceitar dados iniciais quando a nova seleção coincide. Se recusar e o protocolo final mudar, a aplicação talvez precise reconstruir a mensagem.

Por isso a RFC 9846 proíbe retransmissão automática pela camada TLS, salvo quando o mesmo ALPN é selecionado. A aplicação, que conhece enquadramento e semântica, decide se refaz, reenvia ou abandona.

Protocolo não é identidade nem autorização

ALPN decide como as partes falarão. Validação do certificado e correspondência de identidade de serviço decidem com quem. A política de aplicação decide qual ação é permitida.

HTTP/3 deixa a distinção visível: h3 costuma ser selecionado no TLS sobre QUIC, mas a RFC 9114 também exige certificado aceitável para a origem da URI. Uma seleção correta não torna autoritativo um servidor com identidade inválida.

O registro IANA também só define vocabulário interoperável. Código, build e configuração explicam possibilidades; não substituem oferta, seleção e início vistos na conexão.

Testes negativos para manter o escopo

Oferecer h2,http/1.1 e fazer o servidor preferir http/1.1; a telemetria deve guardar o selecionado. Tentar devolver valor não oferecido e confirmar encerramento.

Enviar ClientHello sem ALPN e observar o callback ausente. Distinguir no_application_protocol de NOACK. Acionar OPENSSL_NPN_NO_OVERLAP sem registrar sua saída como escolha. Trocar SSL_CTX via servername e atribuir a decisão à geração correta.

Na borda, criar h2 downstream e HTTP/1.1 upstream, preservando ambas as conexões e a tradução. Reanudar após mudar política sem herdar o valor antigo. Mudar ALPN após rejeitar 0-RTT e provar que TLS não reenvia automaticamente.

Por fim, deixar ALPN passar enquanto a identidade falha; depois deixar ambos passarem enquanto a aplicação nega a ação. Três resultados separados demonstram que nenhuma camada tomou emprestada a autoridade da seguinte.

Fontes