Configurando HTTPS em NGINX

Photo by Ryland Dean on Unsplash

Configurando HTTPS em NGINX

Dica de configurar HTTPS no servidor nginx.

Olá, pessoal.
Nós vamos configurar o HTTPS no servidor NGINX.

Para configurar um servidor HTTPS, o parâmetro ssl deve ser habilitado e os locais do certificado do servidor e dos arquivos de chave privada devem ser especificados:

server {
    listen              443 ssl;
    server_name         www.liberato.eti.br;
    ssl_certificate     www_liberato_eti_br.crt;
    ssl_certificate_key www_liberato_eti_br.key;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    ...
}

O certificado do servidor é uma entidade pública.
Ele é enviado para todos os clientes que se conectam ao servidor.
A chave privada é uma entidade segura e deve ser armazenada em um arquivo com acesso restrito, porém, deve ser legível pelo processo mestre do nginx.

A chave privada pode ser armazenada alternadamente no mesmo arquivo que o certificado:

    ssl_certificate     www_liberato_eti_br.cert;
    ssl_certificate_key www_liberato_eti_br.cert;

Nesse caso, os direitos de acesso ao arquivo também devem ser restritos.
Utilizando chown e chmod para definir as diretivas corretas.

Embora o certificado e a chave sejam armazenados em um arquivo, somente o certificado é enviado a um cliente.

As diretivas ssl_protocols e ssl_ciphers podem ser usadas para limitar as conexões para incluir apenas as versões fortes e cifras de SSL/TLS. Por padrão, o nginx usa:
ssl_protocols TLSv1 TLSv1.1 TLSv1.2” e
ssl_ciphers HIGH:!aNULL:!MD5”,
então, configurá-los explicitamente geralmente não é necessário. Observe que os valores padrão dessas diretivas foram alterados várias vezes.

Otimização do servidor HTTPS

As operações SSL consomem recursos extras da CPU.
Em sistemas com vários processadores, vários processos de trabalho devem ser executados, não menos que o número de núcleos de CPU disponíveis.

A operação mais intensiva da CPU é o handshake SSL.
Existem duas maneiras de minimizar o número dessas operações por cliente: a primeira é habilitar as conexões keepalive para enviar várias solicitações por meio de uma conexão e a segunda é reutilizar os parâmetros da sessão SSL para evitar handshakes SSL para conexões paralelas e subsequentes.

As sessões são armazenadas em um cache de sessão SSL compartilhado entre trabalhadores e configurado pela diretiva ssl_session_cache.

Um megabyte do cache contém cerca de 4.000 sessões.
O tempo limite padrão do cache é de 5 minutos.
Ele pode ser aumentado usando a diretiva ssl_session_timeout.

Aqui está uma configuração de amostra otimizada para um sistema multi-core com cache de sessão compartilhada de 10 megabytes:

worker_processes auto;

http {
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 10m;

    server {
        listen              443 ssl;
        server_name         www.liberato.eti.br;
        keepalive_timeout   70;

        ssl_certificate     www_liberato_eti_br.crt;
        ssl_certificate_key www_liberato_eti_br.key;
        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers         HIGH:!aNULL:!MD5;
        ...

Exemplo de um único servidor HTTP/HTTPS

É possível configurar um único servidor que lide com solicitações HTTP e HTTPS:

server {
    listen              80;
    listen              443 ssl;
    server_name         www.liberato.eti.br;
    ssl_certificate     www_liberato_eti_br.crt;
    ssl_certificate_key www_liberato_eti_br.key;
    ...
}

Servidores HTTPs baseados em nome

Um problema comum surge ao configurar dois ou mais servidores HTTPS escutando em um único endereço IP:

server {
    listen          443 ssl;
    server_name     www.liberato.eti.br;
    ssl_certificate www_liberato_eti_br.crt;
    ...
}

server {
    listen          443 ssl;
    server_name     www.liberato.local;
    ssl_certificate www_liberato_local.crt;
    ...
}

Com esta configuração, um navegador recebe o certificado do servidor padrão, ou seja, www.liberato.eti.br, independentemente do nome do servidor solicitado.
Isso é causado pelo comportamento do protocolo SSL. A conexão SSL é estabelecida antes que o navegador envie uma solicitação HTTP e o nginx não saiba o nome do servidor solicitado. Portanto, pode oferecer apenas o certificado do servidor padrão.

O método mais antigo e robusto para resolver o problema é atribuir um endereço IP separado para cada servidor HTTPS, conforme demonstro abaixo:

server {
    listen          192.168.1.1:443 ssl;
    server_name     www.liberato.eti.br;
    ssl_certificate www_liberato_eti_br.crt;
    ...
}

server {
    listen          192.168.1.2:443 ssl;
    server_name     www.liberato.local;
    ssl_certificate www_liberato_local.crt;
    ...
}

Um certificado SSL com vários nomes

Existem outras formas que permitem compartilhar um único endereço IP entre vários servidores HTTPS.
No entanto, todos eles têm suas desvantagens.
Uma maneira é usar um certificado com vários nomes no campo de certificado SubjectAltName, por exemplo, www.liberato.eti.br e www.liberato.local. No entanto, o comprimento do campo SubjectAltName é limitado.

Outra maneira é usar um certificado com um nome curinga, por exemplo, *.liberato.local. Um certificado curinga protege todos os subdomínios do domínio especificado, mas apenas em um nível. Este certificado corresponde a www.liberato.local, mas não corresponde a liberato.local e www.sub.liberato.local. Esses dois métodos também podem ser combinados. Um certificado pode conter nomes exatos e curingas no campo SubjectAltName, por exemplo, liberato.local e *.liberato.local.

É melhor colocar um arquivo de certificado com vários nomes e seu arquivo de chave privada no nível de configuração http para herdar sua única cópia de memória em todos os servidores:

ssl_certificate     common.crt;
ssl_certificate_key common.key;

server {
    listen          443 ssl;
    server_name     www.liberato.eti.br;
    ...
}

server {
    listen          443 ssl;
    server_name     www.liberato.local;
    ...
}