Configuração SSL#

Para configurar um servidor HTTPS, o parâmetro ssl deve ser habilitado nos sockets de escuta no bloco server, e as localizações dos arquivos de certificado do servidor e chave privada devem ser especificadas:

server {
    listen              443 ssl;
    server_name         www.example.com;
    ssl_certificate     www.example.com.crt;
    ssl_certificate_key www.example.com.key;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
#...
}

O certificado do servidor é uma entidade pública. Ele é enviado para todo cliente que se conecta ao servidor. A chave privada é uma entidade segura e deve ser armazenada em um arquivo com acesso restrito; no entanto, deve ser legível pelo processo mestre do Angie. A chave privada pode alternativamente ser armazenada no mesmo arquivo do certificado.

ssl_certificate     www.example.com.cert;
ssl_certificate_key www.example.com.cert;

Neste caso, os direitos de acesso ao arquivo também devem ser restritos. Embora o certificado e a chave sejam armazenados em um arquivo, apenas o certificado é enviado para o cliente.

As diretivas ssl_protocols e ssl_ciphers podem ser usadas para limitar conexões para incluir apenas as versões e cifras fortes do SSL/TLS. Por padrão, o Angie usa:

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;

Portanto, configurá-las explicitamente geralmente não é necessário.

Otimização do Servidor HTTPS#

Operações SSL consomem recursos extras de CPU. Em sistemas multiprocessador, vários processos worker devem ser executados, não menos que o número de núcleos de CPU disponíveis. A operação mais intensiva em CPU é o handshake SSL. Há duas maneiras de minimizar o número dessas operações por cliente: a primeira é habilitando conexões keepalive para enviar várias requisições através de uma conexão, e a segunda é reutilizar parâmetros de 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 workers e configurado pela diretiva ssl_session_cache. Um megabyte do cache contém cerca de 4000 sessões. O timeout padrão do cache é 5 minutos. Pode ser aumentado usando a diretiva ssl_session_timeout. Aqui está uma configuração de exemplo otimizada para um sistema multi-core com um cache de sessão compartilhado de 10 megabytes:

worker_processes auto;

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

    server {
        listen              443 ssl;
        server_name         www.example.com;
        keepalive_timeout   70;

        ssl_certificate     www.example.com.crt;
        ssl_certificate_key www.example.com.key;
        ssl_protocols       TLSv1.2 TLSv1.3;
        ssl_ciphers         HIGH:!aNULL:!MD5;
    #...

Cadeias de Certificados SSL#

Alguns navegadores podem reclamar sobre um certificado assinado por uma autoridade certificadora bem conhecida, enquanto outros navegadores podem aceitar o certificado sem problemas. Isso ocorre porque a autoridade emissora assinou o certificado do servidor usando um certificado intermediário que não está presente na base de certificados de autoridades certificadoras confiáveis bem conhecidas distribuída com um navegador específico. Neste caso, a autoridade fornece um pacote de certificados encadeados que devem ser concatenados ao certificado do servidor assinado. O certificado do servidor deve aparecer antes dos certificados encadeados no arquivo combinado:

$ cat www.example.com.crt bundle.crt > www.example.com.chained.crt

O arquivo resultante deve ser usado com a diretiva ssl_certificate:

server {
    listen              443 ssl;
    server_name         www.example.com;
    ssl_certificate     www.example.com.chained.crt;
    ssl_certificate_key www.example.com.key;
#...
}

Se o certificado do servidor e o pacote foram concatenados na ordem errada, o Angie falha ao iniciar e exibe uma mensagem de erro:

SSL_CTX_use_PrivateKey_file(" ... /www.example.com.key") failed

(SSL: error:0B080074:x509 certificate routines: X509_check_private_key:key values mismatch)

Porque o Angie tentou usar a chave privada com o primeiro certificado do pacote em vez do certificado do servidor.

Navegadores geralmente armazenam certificados intermediários que recebem, assinados por autoridades confiáveis, então navegadores que são realmente usados podem já ter os certificados intermediários necessários e podem não reclamar sobre um certificado sendo enviado sem um pacote encadeado. Para garantir que o servidor envie a cadeia completa de certificados, o utilitário de linha de comando openssl pode ser usado, por exemplo:

$ openssl s_client -connect www.godaddy.com:443

Certificate chain
 0 s:/C=US/ST=Arizona/L=Scottsdale/1.3.6.1.4.1.311.60.2.1.3=US
     /1.3.6.1.4.1.311.60.2.1.2=AZ/O=GoDaddy.com, Inc
     /OU=MIS Department/CN=www.GoDaddy.com
     /serialNumber=0796928-7/2.5.4.15=V1.0, Clause 5.(b)
   i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc.
     /OU=http://certificates.godaddy.com/repository
     /CN=Go Daddy Secure Certification Authority
     /serialNumber=07969287
 1 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc.
     /OU=http://certificates.godaddy.com/repository
     /CN=Go Daddy Secure Certification Authority
     /serialNumber=07969287
   i:/C=US/O=The Go Daddy Group, Inc.
     /OU=Go Daddy Class 2 Certification Authority
 2 s:/C=US/O=The Go Daddy Group, Inc.
     /OU=Go Daddy Class 2 Certification Authority
   i:/L=ValiCert Validation Network/O=ValiCert, Inc.
     /OU=ValiCert Class 2 Policy Validation Authority
     /CN=http://www.valicert.com//emailAddress=info@valicert.com

Dica

Ao testar configurações com SNI, é importante especificar a opção -servername, pois o openssl não usa SNI por padrão.

Neste exemplo, o assunto ("s") do certificado do servidor www.GoDaddy.com #0 é assinado por um emissor ("i") que é ele próprio o assunto do certificado #1, que é assinado por um emissor que é ele próprio o assunto do certificado #2, que é assinado pelo emissor bem conhecido ValiCert, Inc. cujo certificado está armazenado na base de certificados integrada dos navegadores.

Se um pacote de certificados não foi adicionado, apenas o certificado do servidor #0 será mostrado.

Um Único Servidor HTTP/HTTPS#

É possível configurar um único servidor que manipula tanto requisições HTTP quanto HTTPS:

server {
    listen              80;
    listen              443 ssl;
    server_name         www.example.com;
    ssl_certificate     www.example.com.crt;
    ssl_certificate_key www.example.com.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.example.com;
    ssl_certificate www.example.com.crt;
#...
}

server {
    listen          443 ssl;
    server_name     www.example.org;
    ssl_certificate www.example.org.crt;
#...
}

Com esta configuração, um navegador recebe o certificado do servidor padrão, ou seja, www.example.com, independentemente do nome do servidor solicitado. Isso é causado pelo comportamento do protocolo SSL. A conexão SSL é estabelecida antes do navegador enviar uma requisição HTTP, e o Angie não conhece o nome do servidor solicitado. Portanto, ele só pode oferecer 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:

server {
    listen          192.168.1.1:443 ssl;
    server_name     www.example.com;
    ssl_certificate www.example.com.crt;
#...
}

server {
    listen          192.168.1.2:443 ssl;
    server_name     www.example.org;
    ssl_certificate www.example.org.crt;
#...
}

Um Certificado SSL com Múltiplos Nomes#

Existem outras maneiras que permitem compartilhar um único endereço IP entre vários servidores HTTPS. No entanto, todas elas têm suas desvantagens. Uma maneira é usar um certificado com vários nomes no campo de certificado SubjectAltName, por exemplo, www.example.com e www.example.org. No entanto, o comprimento do campo SubjectAltName é limitado.

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

É melhor colocar um arquivo de certificado com vários nomes e seu arquivo de chave privada no nível http da configuração 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.example.com;
#...
}

server {
    listen          443 ssl;
    server_name     www.example.org;
#...
}

Indicação de Nome do Servidor#

Uma solução mais genérica para executar vários servidores HTTPS em um único endereço IP é a extensão TLS Server Name Indication (SNI, RFC 6066), que permite que um navegador passe um nome de servidor solicitado durante o handshake SSL e, portanto, o servidor saberá qual certificado deve usar para a conexão. O SNI é atualmente suportado pela maioria dos navegadores modernos, embora possa não ser usado por alguns clientes antigos ou especiais.

Dica

Apenas nomes de domínio podem ser passados no SNI; no entanto, alguns navegadores podem erroneamente passar um endereço IP do servidor como seu nome se uma solicitação incluir um endereço IP literal. Não se deve confiar nisso.

Se o Angie foi construído com suporte SNI, então o Angie mostrará isso quando executado com a opção -V:

$ angie -V
...
TLS SNI support enabled
...

No entanto, se o Angie habilitado para SNI estiver vinculado dinamicamente a uma biblioteca OpenSSL sem suporte SNI, o Angie exibe um aviso:

Angie was built with SNI support, however, now it is linked dynamically to an OpenSSL library which has no tlsext support, therefore SNI is not available