12 pontos por GN⁺ 2025-08-02 | 1 comentários | Compartilhar no WhatsApp
  • O primeiro patch para integrar oficialmente o protocolo QUIC ao kernel Linux foi enviado
  • O objetivo é superar limitações do TCP, como latência, head-of-line blocking e a ossificação do protocolo causada por dispositivos intermediários
  • O QUIC é baseado em UDP, oferece suporte a multistream e criptografia ponta a ponta, e sua adoção no kernel pode ampliar o aproveitamento em mais plataformas e hardwares
  • O desempenho da implementação inicial no kernel ficou abaixo do TCP tradicional e do kernel TLS, mas há expectativa de melhora com offloading de hardware e otimizações futuras
  • Atualmente, há discussões ativas sobre suporte em Samba, SMB/NFS baseado em kernel, curl e outros, mas a incorporação ao mainline ainda deve levar tempo

Contexto do surgimento do protocolo QUIC e limitações do TCP

  • O QUIC foi criado para resolver vários problemas do TCP na internet atual
  • A latência causada pelo three-way handshake no processo de conexão do TCP, a falta de bom suporte a multistream e o fenômeno de head-of-line blocking devido à perda de pacotes prejudicam a experiência de uso da web
  • Os metadados do TCP são transmitidos sem criptografia, o que traz risco de vazamento de informações, e os middleboxes (dispositivos intermediários) filtram o tráfego com base nas informações da conexão, levando à ossificação do protocolo (ossification)
  • Mesmo tentativas de melhorar o TCP, como o Multipath TCP, não conseguem funcionar normalmente sem se disfarçar de TCP convencional

Características do QUIC e vantagens técnicas

  • O QUIC funciona sobre UDP e permite estabelecer conexões rapidamente, sem um three-way handshake separado
  • O protocolo foi projetado para transmissão multistream, de forma que a perda de pacotes não afete todo o fluxo
  • Os dados de transporte relacionados ao QUIC são sempre criptografados de ponta a ponta (com base em TLS), impedindo que dispositivos intermediários acessem as mensagens internas
  • Em qualquer ambiente de rede onde pacotes UDP possam passar, o QUIC também pode funcionar normalmente

Visão geral do patch de integração do QUIC no kernel Linux

  • O patch enviado introduz um novo tipo de protocolo chamado IPPROTO_QUIC, permitindo usar a chamada de sistema socket() existente
  • Assim como no TCP, é possível usar chamadas como bind() , connect() , listen() e accept() , mas o processamento posterior tem diferenças
  • O gerenciamento de sessão TLS e os processos de autenticação/criptografia são tratados no espaço do usuário, e após a conexão o handshake TLS precisa ser concluído em cada ponta antes que a troca de dados seja possível
  • Após a conexão inicial, é possível armazenar em cache o resultado da negociação TLS, acelerando bastante reconexões entre dois sistemas

Desafios de desempenho e perspectivas

  • A implementação de QUIC dentro do kernel ainda mostra desempenho inferior ao do kernel TLS e TCP existentes
    • Menos de um terço da vazão do in-kernel TLS; mesmo com a criptografia desativada, a vazão pode ser até 4 vezes menor que a do TCP
  • Entre os motivos apontados estão a falta de suporte a segmentation offloading, cópias extras de dados no caminho de transmissão e o processo de criptografia de cabeçalhos
  • Espera-se que o desempenho melhore com futuro suporte a offloading de hardware e com a otimização da implementação no kernel

Adoção atual e perspectivas futuras

  • Há discussões ativas sobre suporte a QUIC no kernel em vários projetos, como servidor/cliente Samba, sistemas de arquivos SMB e NFS do kernel, curl e outros
  • O patch tem cerca de 9.000 linhas e, no momento, inclui apenas código de suporte de baixo nível. A implementação completa foi prometida em patches adicionais
  • As discussões de revisão de código e incorporação estão apenas começando, então o uso prático ainda deve levar tempo
    • Considerando o precedente recente do protocolo Homa, cuja incorporação ao kernel exigiu 11 envios ao longo de 9 meses, também se espera que o QUIC entre no mainline só depois de 2026

1 comentários

 
GN⁺ 2025-08-02
Comentários do Hacker News
  • Recentemente adicionei ssl_preread_server_name à configuração do NGINX para fazer proxy_pass de requisições de certos domínios para outra instância do NGINX
    A primeira instância apenas encaminha o fluxo TLS bruto (incluindo proxy_protocol), e a segunda faz de fato a terminação do TLS
    Essa abordagem é eficaz para implementar failover — se o caminho padrão do servidor cair, atualizo o registro DNS A para o NGINX da máquina de failover, e essa instância roteia as requisições de determinados domínios por um caminho separado até o backend original
    É conveniente porque não é preciso duplicar toda a configuração de TLS
    Só que esse método não funciona com HTTP/3
    HTTP/3 é baseado em QUIC, roda sobre UDP e criptografa o SNI durante o handshake, então não dá para fazer roteamento por domínio com ssl_preread_server_name
    Fico me perguntando se existe alguma alternativa que suporte roteamento baseado em SNI no HTTP/3, ou se, caso essa funcionalidade seja necessária, ainda é preciso continuar com HTTP/1.1 ou HTTP/2 sobre TLS
    • A maioria dos clientes que suportam QUIC também suporta registros DNS HTTPS, então há a opção de adicionar um registro de menor prioridade para failover e deixar isso a cargo do cliente
      Na prática, o comportamento varia conforme a implementação do cliente (veja o status do suporte a registros HTTPS no Chromium neste issue), mas quando a conexão QUIC falha, o cliente faz fallback de forma transparente para HTTP/1.1/2 e também respeita o cabeçalho Alt-Svc
      Se for um failover planejado, você também pode simplesmente deixar de enviar o cabeçalho Alt-Svc e esperar o timeout até a instância alternativa
      Se o roteamento de QUIC for realmente necessário, felizmente a informação de SNI está sempre no primeiro pacote, então dá para rotear com inspeção de pacotes
      O udpgrm da Cloudflare pode servir de referência, e isso funciona quando não há ECH (Encrypted Client Hello)
      Se houver ECH, o roteador precisa ter a chave de descriptografia para poder tomar a decisão de roteamento, e também é possível projetar failover em cascata no próprio protocolo
      Uma implementação concreta de código pode ser vista neste exemplo do udpgrm
    • Fazer a terminação de TLS direto na borda (por exemplo, no NGINX) não é exatamente um grande ponto de risco hoje em dia no ecossistema do Let's Encrypt
      Se um invasor tiver acesso a esse servidor, também será fácil emitir novos certificados SSL, então, em vez de pensar em um sistema complexo de failover, parece mais sensato simplesmente terminar o TLS diretamente
      Pessoalmente, nunca consegui reproduzir na prática os ganhos de desempenho e confiabilidade do QUIC
      Faço testes repetidamente há anos, mas na maioria das vezes acabo desativando por questões de desempenho e afins
      O failover baseado em DNS também leva minutos para realmente se refletir, e clientes simples como navegadores muitas vezes não fazem o failover direito
      Por isso uso diretamente um handler onerror para carregar um segundo caminho
      Por exemplo, para rastreamento de anúncios uso código desse tipo, e também forneço uma API fetch encapsulada da mesma forma
      Esse método é muito mais eficiente do que qualquer outra tentativa que já fiz
    • Em um ambiente de failover, eu nem me preocuparia com failover de QUIC
      Mesmo que o navegador não consiga estabelecer a conexão QUIC (ainda que ela esteja anunciada no DNS), ele fará fallback automático para HTTP/1 ou HTTP/2 sobre TLS, então dá para usar exatamente o mesmo método de failover de sempre
    • Esse é do tipo de problema que “não é bug”
      Uma característica de design do HTTP/3 é justamente não expor informações do endpoint até a camada TLS
      Pessoalmente, considero isso uma vantagem
      O HAProxy consegue fazer proxy de TLS bruto, mas não roteamento com base no nome do host
      O Cloudflare Tunnel tem uma funcionalidade especial que permite roteamento por nome de host sem terminar o TLS, mas para usá-la o DNS também precisa apontar para a Cloudflare
      Veja a forma como isso é retratado nesta tirinha do xkcd
    • Pergunta interessante
      Fico curioso se a mesma limitação também existe em ambientes TCP+TLS quando se usa Encrypted Client Hello
      Imagino que a resposta seja praticamente a mesma
  • Lembro há muito tempo deste post relacionado sobre os pontos fracos do QUIC
    Sinto que esta discussão caminha para resolver esses problemas aos poucos
    Também existe a possibilidade de suporte em hardware nas placas de rede no futuro
    • QUIC não é muito adequado para tráfego entre máquinas
      Mas hoje em dia a maior parte do tráfego da internet vai entre dispositivos móveis e servidores, e é justamente nesse trecho que QUIC e HTTP/3 mostram seu valor
      Para os outros casos, o TCP pode continuar sendo usado
  • Fico curioso para ver como será uma API de socket para múltiplos streams
    Imagino algo que continue parecendo várias conexões, mas com cache interno
    Eu preferiria receber explicitamente um objeto de conexão e abrir streams separados a partir dele, mas por enquanto também aceito a forma atual
    Pelo que vi nesta discussão, se isso não for uma extensão, então no lado do servidor também é possível criar novos streams depois que a conexão for estabelecida
    No cliente, como na prática é um stream mas é difícil abstraí-lo como algo separado tipo uma “conexão”, parece que será necessária uma abstração de API completamente nova
    Imagino algo como receber um descritor de arquivo para cada novo stream via recvmsg
    • Como o SCTP já oferece suporte a múltiplos streams na API de sockets, vale a pena olhar a interface do SCTP como referência
  • Independentemente da implementação no kernel, seria ótimo se o OpenSSH tivesse suporte a QUIC
    Quero algo tão resistente a problemas de rede quanto o Mosh, mas mantendo todos os recursos do OpenSSH como SFTP, SOCKS, port forwarding, gerenciamento de estado, roaming etc.
    Fico me perguntando se o OpenSSH conseguiria aproveitar o suporte no kernel
    Veja o Mosh
    • O SSH teria que substituir completamente suas camadas de criptografia e multiplexação por QUIC, então seria um trabalho enorme
      Provavelmente faria mais sentido criar um protocolo de login separado baseado em QUIC
      Há várias abordagens em estágio de protótipo
    • O OpenSSH é um projeto do OpenBSD, então talvez não dê tanta importância assim a APIs específicas do Linux
  • Dizem que o gargalo do TCP é o handshake, mas pelo que eu entendia isso era resolvido com reutilização de conexão ou multiplexação
    Porém, agora estão dizendo que a implementação atual de QUIC no kernel é de 3 a 4 vezes mais lenta que no Linux, e que a diferença de desempenho deve diminuir em breve
    Se velocidade é a vantagem do QUIC, e na prática ele é mais lento, qual é então a razão para usá-lo?
    Até o autor do PR diz que parte da perda de desempenho vem do próprio design do protocolo; então fica a dúvida se ainda há problemas no TCP que poderiam ser corrigidos separadamente
    • O artigo também menciona bastante as causas de o QUIC ser lento
      Em grande parte, tudo se resume a “ainda não foi otimizado”
      Por exemplo, falta suporte a segment offload, há cópias extras de dados no caminho de transmissão, e existe overhead por causa da criptografia de cabeçalhos — tudo isso tem boa chance de ser resolvido
      O benchmarking aqui foi feito em um ambiente muito idealizado
      Na prática, ambientes móveis têm grande variabilidade de rede, e é aí que as limitações estruturais do TCP ficam mais evidentes
      Na verdade, em muitos casos já se implementam sobre TCP, como no HTTP/2, recursos semelhantes aos do QUIC
      No fim, o QUIC é uma pilha de rede abrangente que opera acima da camada 5 do modelo OSI, enquanto o TCP é mais como um motor de camada 3, então é estruturalmente difícil compará-los
      Acima de tudo, a vantagem do QUIC está em conexões e reconexões mais rápidas, além de garantir continuidade da sessão mesmo quando o IP muda
      Sua estrutura de multiplexação e streams não bloqueantes simplifica drasticamente o desenho de protocolos de nível superior
      Se essa estrutura entrar no kernel, o potencial de otimização de desempenho será enorme
      Em vez de continuar construindo soluções em várias camadas sobre as limitações do TCP, deveríamos usar com mais frequência bases mais avançadas como o QUIC no dia a dia
    • O gargalo do TCP não é só o handshake
      Quando há perda de pacotes, tudo o que vem depois fica atrasado até a recuperação completa da transmissão (HOL blocking), o que é uma limitação estrutural importante
    • Não dá para reutilizar uma “conexão que não existe”, então muita da discussão está focada em reduzir latência
      Não é simplesmente uma questão de velocidade, e sim de melhorar a latência
    • A vantagem do QUIC é a capacidade de rastreamento baseada no connection ID fornecido pelo servidor
      Veja esta explicação técnica
  • Fico confuso entre a mensagem de que mover a pilha de rede para user space melhora o desempenho e esta discussão atual propondo levá-la para o kernel
    • A maioria das pilhas QUIC roda sobre UDP dentro do kernel
      A principal limitação está nas trocas de contexto entre kernel e espaço do usuário
      Redes em user space (por exemplo, com acesso direto à NIC) eliminam a entrada no kernel
      Por outro lado, fornecer funcionalidades no espaço do kernel (como sendfile, TLS no kernel, offloading na NIC, DMA direto do disco para a NIC) também reduz trocas de contexto e cópias de dados no sistema como um todo
      As pilhas QUIC atuais não conseguem aproveitar bem nenhuma das duas vantagens
      A entrada e saída de pacotes ainda dependem de syscalls, e não se consegue evitar cópias de dados
      Dá para reduzir trocas de contexto com I/O em lote via io_uring e afins, mas isso não reduz a cópia em si
    • Exatamente
      Há dois caminhos: bypass do kernel + DMA, ou excluir o espaço do usuário, como em sendfile/kTLS
      A implementação de QUIC no kernel hoje não tem nenhuma das duas vantagens
    • No fim, ainda é preciso entregar os dados ao buffer da NIC
      Se isso puder ser feito escrevendo direto na NIC via DMA ou se tiver que passar por syscall do kernel, a diferença de desempenho é grande
      Networking em user space só faz sentido quando existe essa estrutura de transição de privilégio e DMA
    • A ideia de o user space acessar diretamente os dados de rede (provavelmente sem syscall) não tem muito significado para software comum
      É algo usado só por empresas gigantes (MOFAANG e afins)
      Em teoria, espera-se que o io_uring generalize esses benefícios, mas isso ainda não chegou de fato ao uso prático
    • A troca de contexto no acesso ao hardware é lenta demais
      É por isso que o TCP/IP continua no kernel nos principais sistemas operacionais
  • “Por que colocar cada vez mais coisas no kernel?”
    Eu achava que o papel do kernel era gerenciar memória, hardware e tarefas; protocolos acima de IP não deveriam ficar no userland?
    • Processar networking, roteamento, VPN etc. no espaço do kernel pode melhorar o desempenho em alguns casos de uso
      Por outro lado, separar essas pilhas para user space também pode trazer ganhos em alguns casos
    • Estar no kernel traz vantagens de hardening, suporte LTS e otimizações em nível de kernel e de rede
    • O principal motivo é otimizar transferências por DMA e offloading da NIC
    • Se todo o protocolo acima de IP ficar em user space, não será possível uso multiprocesso
      Como TCP/UDP no kernel arbitra o roteamento de sockets por porta, vários programas conseguem usar TCP/UDP ao mesmo tempo
      O QUIC roda sobre UDP, então o ponto da discussão continua válido
      O destaque é que apenas protocolos diretamente acima de IP não podem rodar em user space
  • Acho que o QUIC traz uma mudança enorme para muita gente
    Espero que a internet fique um pouco mais rápida no futuro
    Em ambientes de comunicação como 5G talvez a diferença nem seja tão perceptível, mas ainda assim é um avanço valioso
    Acho curioso haver uma estrutura de handshake separada por link
    Eu imaginava que o QUIC incorporasse o TLS inteiramente dentro de si, então isso foi diferente do que eu pensava
  • O principal motivo de a web como um todo estar mais lenta é que os sites ficaram pesados demais
    Ainda assim, acho que esta tecnologia pode reduzir ainda mais a latência em jogos
    • O paradoxo de Jevons também se aplica aqui
      Quando os recursos computacionais e a eficiência de rede aumentam, a demanda em si também cresce
      Em jogos ou computação científica isso não importa porque o objetivo é “resultados melhores”
      Mas na web isso muitas vezes tem efeito contrário, com mais anúncios, rastreamento e JavaScript
  • O artigo diz que, como no TCP, o QUIC estabelece conexões com bind(), connect(), listen() e accept(), mas depois a estrutura muda para uso de syscalls sendmsg() e recvmsg()
    Eu gostaria que também houvesse uma explicação de por que essa abordagem foi adotada e por que não criaram syscalls separadas específicas para QUIC