BLOG | NGINX

Melhorando o desempenho do NGINX com Kernel TLS e SSL_sendfile( )

NGINX-Parte-de-F5-horiz-preto-tipo-RGB
Mikhail Isachenkov Miniatura
Mikhail Isachenkov
Publicado em 11 de novembro de 2021

Transport Layer Security (TLS) é um protocolo de criptografia extremamente popular. A implementação do TLS no kernel (kTLS) melhora o desempenho ao reduzir significativamente a necessidade de operações de cópia entre o espaço do usuário e o kernel.

Combinar kTLS e sendfile() significa que os dados são criptografados diretamente no espaço do kernel, antes de serem passados para a pilha de rede para transmissão. Isso elimina a necessidade de copiar dados para o espaço do usuário para serem criptografados pelas bibliotecas TLS e depois de volta para o espaço do kernel para transmissão. O kTLS também permite o descarregamento do processamento TLS para o hardware, incluindo o descarregamento do processamento criptográfico simétrico TLS para dispositivos de rede .

Os kernels modernos do Linux e do FreeBSD suportam o descarregamento de TLS para o kernel, e agora o NGINX Open Source também! O NGINX 1.21.4 introduz suporte para kTLS ao servir arquivos estáticos e respostas em cache com SSL_sendfile() , o que pode melhorar muito o desempenho. Conforme detalhado abaixo, tanto o kernel quanto o OpenSSL devem ser construídos com kTLS para que o NGINX use SSL_sendfile() .

Neste blog, detalhamos quais sistemas operacionais e versões do OpenSSL oferecem suporte ao kTLS e mostramos como construir e configurar o kernel e o NGINX para o kTLS. Para lhe dar uma ideia da melhoria de desempenho que você pode esperar do kTLS, também compartilhamos as especificações e os resultados dos nossos testes no FreeBSD e no Ubuntu.

Observação: as implementações do kTLS são bastante novas e evoluem rapidamente. Este blog descreve o suporte ao kTLS a partir de novembro de 2021, mas fique atento aos anúncios no nginx.org e no blog NGINX<.htmla> sobre mudanças nas informações e instruções fornecidas aqui.

Requisitos gerais

  • Sistema operacional – Qualquer um dos seguintes:

    • FreeBSD 13.0+. Em novembro de 2021, o FreeBSD 13.0+ era o único sistema operacional compatível com kTLS no NGINX sem uma compilação manual do NGINX para incorporar o OpenSSL 3.0.0+. Veja Habilitando o NGINX com kTLS no FreeBSD .

    • Uma distribuição Linux construída no kernel Linux versão 4.17 ou posterior, embora recomendemos usar aquelas construídas na versão 5.2 ou posterior quando possível. (o suporte ao kTLS está realmente disponível na versão 4.13, mas o OpenSSL 3.0.0 requer o cabeçalho do kernel versão 4.17 ou posterior.)

  • OpenSSL – Versão 3.0.0 ou posterior

  • NGINX – Versão 1.21.4 ou posterior (linha principal)

    [ EditorNGINX Plus R27 e posteriores oferecem suporte a kTLS em versões qualificadas de sistemas operacionais baseados em Linux; NGINX Plus R26 e posteriores oferecem suporte a ele em versões qualificadas do FreeBSD. Para obter detalhes sobre os sistemas operacionais suportados, consulte a página de versões do NGINX Plus.]

Suporte ao sistema operacional

SOs que suportam kTLS

Em novembro de 2021, dos sistemas operacionais suportados pelo NGINX Open Source , os seguintes suportavam kTLS e as cifras indicadas. Para obter detalhes sobre o suporte à cifra, consulte Protocolo TLS e suporte à cifra .

  Cifras TLSv1.2 TLSv1.3
conjuntos de cifras
Cifra TLS_CHACHA20_POLY1305_SHA256 Versão do kernel Linux
Amazon Linux 2 * 5.10
CentOS 8 ** 4.18
FreeBSD 13.x *** N/D
RHEL 8 4.18
SLES 15 SP2 5.3
Ubuntu 20.04 LTS ❌​​ 5.4
Ubuntu 21.04 5.11
Ubuntu 21.10 5.13

  * A versão do kernel deve ser 5.10, não 4.14; veja SOs que não suportam kTLS e as Perguntas frequentes do Amazon Linux 2
** Herda seu status de suporte kTLS do RHEL 8 como sua fonte upstream
*** Veja o log de commits do FreeBSD

SOs que não suportam kTLS

Os seguintes sistemas operacionais não oferecem suporte ao kTLS, pelo motivo indicado:

  • Alpine Linux 3.11–3.14 – O kernel é construído com a opção CONFIG_TLS=n , que desabilita a construção do kTLS como um módulo ou como parte do kernel.
  • Amazon Linux 2 – A versão do kernel Linux é 4.14 para a AMI padrão do Amazon Linux 2 (consulte as Perguntas frequentes do Amazon Linux 2 ).
  • CentOS 7.4+ – A versão do kernel Linux é 3.10. Herda seu status de suporte a kTLS do RHEL 7.4+ como sua fonte upstream.
  • Debian 10 e 11 – O kernel é construído com a opção CONFIG_TLS=n (veja os logs de relatórios de bugs do Debian ).
  • RHEL 7.4+ – A versão do kernel Linux é3.10 .
  • SLES 12 SP5+ – A versão do kernel Linux é4.12 .
  • Ubuntu 18.04 LTS – A versão do kernel Linux é4.15 .

Suporte ao protocolo TLS e à cifra

Conforme detalhado acima , os sistemas operacionais que oferecem suporte ao kTLS variam em seu suporte aos protocolos e cifras TLS.

Com o TLSv1.2, o módulo kTLS suporta estas cifras:

  • AES128-GCM-SHA256
  • AES256-GCM-SHA384
  • ECDHE-RSA-AES128-GCM-SHA256
  • ECDHE-RSA-AES256-GCM-SHA384

Com o TLSv1.3, o módulo kTLS suporta estes conjuntos de cifras:

  • TLS_AES_128_GCM_SHA256
  • TLS_AES_256_GCM_SHA384
  • TLS_CHACHA20_POLY1305_SHA256 (apenas alguns sistemas operacionais, conforme especificado em SOs que suportam kTLS )

Para verificar quais cifras TLS suportadas pelo OpenSSL estão habilitadas no seu binário NGINX, execute o comando openssl-3.0.0/.openssl/bin/openssl ciphers no diretório onde você construiu o NGINX (por exemplo, seu diretório inicial).

Habilitando kTLS no NGINX

Conforme mencionado na introdução, o kTLS melhora o desempenho do NGINX porque toda a criptografia e descriptografia ocorrem no kernel. Os dados são criptografados diretamente no espaço do kernel – antes de serem passados para a pilha de rede para transmissão – eliminando a necessidade de copiar dados para o espaço do usuário para serem criptografados pelas bibliotecas TLS e, em seguida, de volta para o espaço do kernel para transmissão.

Diagrama do kernel TLS (kTLS) com NGINX

Carregando kTLS no Kernel

Nas distribuições modernas de FreeBSD e Linux, o kTLS geralmente é criado como um módulo (com a opção CONFIG_TLS=m ). Você deve carregar explicitamente o módulo kTLS no kernel antes de iniciar o NGINX.

  • No FreeBSD, execute estes comandos como usuário root :

    # kldload ktls_ocf.ko # sysctl kern.ipc.tls.enable=1
    

    Para detalhes sobre as opções de comando do FreeBSD, consulte a página de manual do ktls(4) .

  • Em distribuições Linux, execute este comando como usuário root :

    # modprobe tls
    

Habilitando NGINX com kTLS no FreeBSD

Para habilitar o suporte a kTLS no NGINX no FreeBSD, você pode usar as mesmas instruções para distribuições Linux. No entanto, recomendamos que você execute as seguintes etapas para aproveitar a compilação do NGINX com kTLS na porta security/openssl-devel na Coleção de Ports do FreeBSD . Para mais informações, incluindo uma visão geral do kTLS, consulte TLS Offload in the Kernel no site do FreeBSD.

  1. Crie o OpenSSL 3.0 com suporte a kTLS, selecionando as opções apropriadas no menu de configuração:

    # cd /usr/ports/security/openssl-devel && fazer configuração && fazer instalação
    
  2. Modifique /etc/make.conf para usar openssl-devel como a biblioteca SSL padrão:

    # echo "VERSÕES_PADRÃO+=ssl=openssl-devel" >> /etc/make.conf
    
  3. Crie o NGINX:

    # cd /usr/ports/www/nginx-devel && make install
    

Construindo NGINX com kTLS em distribuições Linux

A maioria das distribuições Linux atuais inclui uma versão do OpenSSL anterior à 3.0.0 (comumente, versão 1.1). Então você precisa construir o NGINX a partir do código-fonte com o OpenSSL 3.0.0.

As duas opções cruciais no comando configure que habilitam o suporte ao kTLS são:

  • --com-openssl=../openssl-3.0.0
  • --com-openssl-opt=habilitar-ktls

As outras opções de configuração são para os módulos incluídos nos pacotes binários oficiais do NGINX disponíveis em nginx.org . Em vez disso, você pode especificar um conjunto personalizado de módulos. Para ver as opções de compilação usadas para seu binário NGINX atual, execute nginx -V .

Para construir o NGINX com OpenSSL 3.0.0, execute os seguintes comandos:

$ wget https://nginx.org/download/nginx-1.21.4.tar.gz $ wget https://www.openssl.org/source/openssl-3.0.0.tar.gz $ tar xzf openssl-3.0.0.tar.gz $ cd nginx-1.21.4 $ ./configure \ --with-debug \ --prefix=/usr/local \ --conf-path=/usr/local/etc/nginx/nginx.conf \ --error-log-path=/var/log/nginx/error.log \ --http-log-path=/var/log/nginx/access.log \ --pid-path=/var/run/nginx.pid \ --lock-path=/var/run/nginx.lock \ --http-client-body-temp-path=/var/cache/nginx/client_temp \ --http-proxy-temp-path=/var/cache/nginx/proxy_temp \ --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \ --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \ --http-scgi-temp-path=/var/cache/nginx/scgi_temp \ --user=nginx \ --group=nginx \ --with-compat \ --with-file-aio \ --with-threads \ --with-http_addition_module \ --with-http_auth_request_module \ --with-http_dav_module \ --with-http_flv_module \ --with-http_gunzip_module \ --with-http_gzip_static_module \ --with-http_mp4_module \ --with-http_random_index_module \ --com-módulo_realip_http \ --com-módulo_link_seguro_http \ --com-módulo_slice_http \ --com-módulo_ssl_http \ --com-módulo_status_stub_http \ --com-módulo_sub_http \ --com-módulo_v2_http \ --com-mail \ --com-módulo_ssl_mail \ --com-stream \ --com-stream_realip_module \ --com-stream_ssl_module \ --com-stream_ssl_preread_module \ --com-openssl=../openssl-3.0.0 \ --com-openssl-opt=enable-ktls \ --com-cc-opt='-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' \ -com-ld-opt='-Wl,-Bfunções-simbólicas -Wl,-z,relro -Wl,-z,agora -Wl,--conforme-necessário -pie' $ make –j4 $ make install

Observação:  O binário NGINX resultante é vinculado estaticamente às bibliotecas OpenSSL 3.0.0. Se mais tarde você precisar corrigir o OpenSSL, deverá baixar e descompactar o novo arquivo de origem do OpenSSL e, em seguida, executar os comandos acima para reconstruir o binário NGINX.

Configurando o NGINX

Para habilitar o kTLS, inclua a diretiva ssl_conf_command com o parâmetro Options KTLS no contexto server{} , como nesta configuração de exemplo usada para nossos testes :

worker_processes auto;error_log /var/log/nginx/error.log debug;

events {}

http {
sendfile on;

server {
listen 443 ssl;
ssl_certificate ssl/example.crt;
ssl_certificate_key ssl/example.key;
ssl_conf_command Opções KTLS;
ssl_protocols TLSv1.3;

location / {
root /data;
}
}
}

Verificando se o kTLS está habilitado

Para verificar se o NGINX está usando kTLS, ative o modo de depuração e verifique BIO_get_ktls_send() e SSL_sendfile() no log de erros.

$ grep BIO /var/log/nginx/error.log 2021/11/10 16:02:46 [depuração] 274550#274550: *2 BIO_get_ktls_send(): 1 2021/11/10 16:02:49 [depuração] 274550#274550: *3 BIO_get_ktls_send(): 1 $ grep SSL_sendfile /var/log/nginx/error.log 2021/11/10 16:02:46 [depuração] 274550#274550: *2 SSL_sendfile: 1048576 2021/11/10 16:02:49 [depuração] 274550#274550: *3 SSL_sendfile: 1048576

Observação:  Recomendamos que você desabilite o modo de depuração depois de fazer essas verificações, especialmente em ambientes de produção. O registro de depuração acarreta uma perda de desempenho devido ao grande volume de operações de gravação; além disso, os registros de depuração podem ser enormes e esgotar rapidamente o espaço disponível na partição do disco.

Melhoria de desempenho com kTLS

Ao servir arquivos estáticos e respostas em cache sob carga pesada, SSL_sendfile() pode aumentar a taxa de transferência em até 2x em comparação ao TLS de espaço do usuário, mas o tamanho do aumento de desempenho depende significativamente de vários fatores (desempenho do disco, carga do sistema, etc.). Também é possível reduzir o uso da CPU se sua placa de rede suportar descarregamento TLS.

Testando o desempenho

Para medir o aumento de desempenho em sua configuração, use as instruções a seguir para executar um teste simples de um thread. Conforme detalhado abaixo, nossos resultados de teste indicam um aumento de desempenho de até quase 30% sem nenhum ajuste específico.

Hardware e software utilizados:

  • Instância AWS t3.medium com:
    • 4 GB de RAM
    • SSD de uso geral de 20 GB
    • CPU Intel® Xeon® Platinum 8259CL a 2,50 GHz com 2 núcleos
  • FreeBSD 13.0 e Ubuntu 21.10
  • TLSv1.3 com o conjunto de cifras TLS_AES_256_GCM_SHA384
  • NGINX 1.21.4, criado e configurado conforme especificado em Habilitando kTLS no NGINX .

Para realizar o teste:

  1. Crie um arquivo grande que caiba completamente no cache de disco:

    # truncar -s 1g /dados/1G
    
  2. Execute este comando para verificar a taxa de transferência; o comando base é repetido várias vezes para resultados mais precisos. Envie a saída para o utilitário ministat [ FreeBSD ][ Ubuntu ] para uma análise estatística básica.

     

    # para i em 'seq 1 100'; faça curl -k -s -o /dev/null -w '%{speed_download}\n' https://localhost/1G | ministat
    

Resultados dos testes de desempenho

Nos resultados a seguir dos nossos testes, apresentados como saída do ministat , cada valor é a velocidade de download em kBytes/segundo. A saída é dividida em duas linhas para maior legibilidade.

Taxa de transferência para FreeBSD 13.0 sem kTLS:

    N Mín. Máx. Mediana ...x 10 532225 573348 555616 ... 

...      Desvio Padrão Médio
... 555155.6     10239.137

Taxa de transferência para FreeBSD 13.0 com kTLS:

    N Mín. Máx. Mediana ...x 10 629379 723164 717349 ... 

...      Desvio Padrão Médio
... 708600.4     28304.766

Taxa de transferência para Ubuntu 21.10 sem kTLS:

    N Mín. Máx. Mediana ...x 10 529199 705720 662354 ... 

...      Desvio Padrão Médio
... 654321.6     48025.103

Taxa de transferência para Ubuntu 21.10 com kTLS:

    N Mín. Máx. Mediana ...x 10 619105 760208 756278 ... 

...      Desvio Padrão Médio
... 741848.3     43255.246

Em nossos testes, o kTLS melhorou mais o desempenho com o FreeBSD do que com o Ubuntu. A melhoria percentual foi a seguinte:

  Mínimo Máx. Mediana Média
FreeBSD 13.0 18% 26% 29% 28%
Ubuntu 21.10 16% 8% 14% 13%

Resumo

O NGINX 1.21.4 introduz suporte para kTLS ao servir arquivos estáticos e respostas em cache com SSL_sendfile() . Nossos testes mostram que o desempenho melhora entre 8% e 29%, dependendo do sistema operacional.

Estamos interessados em saber sobre suas experiências com kTLS e NGINX, e especialmente os resultados de seus testes em outros sistemas operacionais! Por favor, compartilhe-os na seção de comentários abaixo.


"Esta postagem do blog pode fazer referência a produtos que não estão mais disponíveis e/ou não têm mais suporte. Para obter as informações mais atualizadas sobre os produtos e soluções F5 NGINX disponíveis, explore nossa família de produtos NGINX . O NGINX agora faz parte do F5. Todos os links anteriores do NGINX.com redirecionarão para conteúdo semelhante do NGINX no F5.com."