LPI-2 202-450 Topico 208.2
Configuração do HTTPS no Apache
Índice
- 208.2 Configuração do Apache para HTTPS - Objetivos
- 208.2 Configuração do Apache para HTTPS - Conteúdo
208.2 Configuração do Apache para HTTPS - Objetivos
Peso 3
O Candidato deve ser capaz de configurar um servidor web para HTTPS. Conhecimentos-chave:
- Arquivos de configuração e ferramentas do SSL;
- Capacidade de gerar uma chave privada de servidor e um CSR para um CA comercial;
- Capacidade de gerar um Certificado auto-assinado de um CA privado;
- Capacidade de instalar a chave e o certificado;
- Configuração de Hosts Virtuais com SNI;
- Noção das questões sobre Hosts Virtuais e o uso de SSL;
- Questões de segurança no uso de SSL.
Lista parcial dos arquivos, termos e ferramentas utilizadas:
- Arquivos de configuração do Apache2;
/etc/ssl/*
,/etc/pki/*
;openssl
, CA.pl;- SSLEngine, SSLCertificateKeyFile, SSLCertificatePath;
- SSLCACertificateFile, SSLCACertificatePath;
- SSLProtocol, SSLCipherSuite, ServerTokens, ServerSignature, TraceEnable.
208.2 Configuração do Apache para HTTPS - Conteúdo
Criptografia
Entende-se por "texto plano" qualquer tipo de dado que possa ser
"lido" no computador. Pode ser um arquivo, uma imagem, até mesmo um
texto em .txt
. Em uma interação criptografada esse arquivo em
"texto plano" é tratado por um processo de criptografia usando uma
hash conhecida como "chave de criptografia" e após isso
temos o mesmo arquivo porém cifrado.
O texto após cifrado pode ser enviado por um meio público como a Internet para alguém sem risco de que se ele possa ser "lido" caso for "capturado" por um terceiro.
Após o arquivo recebido pelo devido destinatário, esse de posse da "chave de descritografia" consegue executar o processo inverso ao da criptografia, descifrando o arquivo para poder lê-lo.
Criptografia simétrica
A criptografia simétrica é o processo onde a chave de criptografia e a chave de descriptografia são idênticas (chave compartilhada).
Figura 1: Processo de criptografia simetrica
Nesse formato toda a segurança do processo é baseado nessa "chave compartilhada" e caso algum terceiro obtiver o acesso à essa chave a segurança da operação fica comprometida.
Criptografia assimétrica
Na criptografia assimétrica ao invés de gerarmos uma chave compartilhada geramos um par de chaves. Uma é a chave pública que é usada para criptografar os dados e a outra é a chave privada que é a usada para descriptografar os dados.
Figura 2: Processo de criptografia assimétrica
Hash
O processo de hash é uma transformação de "via de mão única". Tem as seguintes características.
- A entrada pode ter tamanho variável, mas a saída terá sempre um tamanho fixo;
- Não pode ser revertida ao estado original.
Figura 3: Fluxo de caminho único da hash
Assinaturas digitais
A combinação de chaves públicas e privadas com hashes cria assinaturas digitais. Essas assinaturas digitais nos dão grande confiança de que o arquivo que recebemos realmente veio da pessoa de quem pensamos ser, e não foi modificado por acidente ou maliciosamente, desde que foi assinado.
Figura 4: Verificação de assinatura
Uma coisa a notar sobre tudo isso, é que estamos supondo aqui, que a chave pública que obtivemos realmente é a chave pública do criador que originou o documento com a assinatura que estamos tentando verificar.
Secure Socket Layer (SSL)
Assinaturas digitais são usadas em SSL, que é uma camada na pilha de protocolos, assenta acima da camada de transporte e verifica a identidade do servidor e negocia a chave de sessão assimétrica que será usada para criptografar todo o tráfego entre o navegador e o servidor.
Figura 5: Fluxo SSL
Neste diagrama, o navegador e o servidor se comunicam primeiro por meio da pilha de protocolos TCP/IP normal e essa comunicação não é criptografada (caminho inseguro).
SSL é uma camada acima da camada de transporte na extremidade do cliente e do servidor e o hand shake é realizado quando a conexão SSL é feita, verifica a identidade do servidor e negocia a chave de sessão assimétrica que nos dá um caminho seguro entre o navegador e o servidor.
SSL depende do uso de Certificados Digitais. E, basicamente, um Certificado Digital é uma coleção de informações que identificam um site, assinada por alguma autoridade de certificação de terceiros confiável. Os certificados digitais contêm:
- A identidade do emissor - Autoridade Certificadora (CA);
- O nome de domínio e a chave pública do site;
- Data de validade;
- A assinatura da CA.
Figura 6: Estrutura de um certificado
Gerando um certificado
O OpenSSL é um toolkit open-source contendo ferramentas de linha de comando (CLI) e também bibliotecas que suportam várias operações criptográficas relacionadas ao SSL.
O processo de gerar um certificado se inicia com a geração de uma
chave privada que é feita com o uso do comando openssl
.
O próprio comando openssl
pode ser usado para:
- Criar e gerenciar chaves públicas e privadas;
- A criação de certificados X509 e também solicitações de certificados (CRS);
- Cálculo de hashes;
- Criptografia e descriptografia.
O processo para obter um certificado começa com a criação de uma
chave privada com o comando openssl
na seguinte sintaxe:
openssl genrsa -des3 -out www.exemplo.com.br.key 1024
Assim criaremos uma chave privada usando criptografia Triple DES que terá o nome "www.exemplo.com.br.key". Durante o processo de criação da chave privada será solicitada a criação de uma senha. Esta senha é importante ser anotada.
Também é possível criar uma chave privada sem necessidade de senha, apesar de ser um processo menos seguro ele acaba sendo útil em alguns cenários:
openssl genrsa -out www.exemplo.com.br.key 1024
Após a criação da chave privada criaremos a Certificate Signing
Request (CSR) ou Requisição de Assinatura de Certificado. O CSR é
um pacote de informações contendo uma chave pública e
informações relativas ao site a publicar (Cidade, País, Email,
Organização, etc…) atenção ao item Common Name este deve ser
preenchido com o endereço do site (sem o http://
).
openssl req -new -key www.exemplo.com.br.key -out www.exemplo.com.br.csr
O arquivo resultante "www.exemplo.com.br.csr" deverá ser enviado para a CA.
A CA de posse do CSR utilizará a chave pública dela para calcular em conjunto com a chave pública constante no certificado e os dados fornecidos para gerar o certificado digital que será entregue ao solicitante.
Figura 7: Fluxo de geração de um certificado
O formato PKCS # 12
Trata-se de um formato binário usado para armazenar todos os
elementos da cadeia de confiança, como o certificado do servidor,
quaisquer certificados intermediários e a chave privada em um
único arquivo criptografável. Esses arquivos são criados com
extensões .pfx
e/ou .p12
. Esses arquivos são geralmente
usados para importar e exportar certificados em máquinas Windows
e MacOS.
Com o comando openssl
podemos gerar certificados no formato
PKCS#12 diretamente da CLI do Linux:
$ openssl pkcs12 -export -out certificado.pfx \ -inkey chaveprivada.key -in certificado.crt \ -certfile intermediario.crt
Sendo:
pkcs12
- o utilitário de arquivo para arquivos PKCS#12 em OpenSSL;-export -out certificado.pfx
- exportar e salvar o arquivo PKCS#12 com o nomecertificado.pfx
;-inkey chaveprivada.key
- use o arquivo de chave privadachaveprivada.key
como a chave privada a ser combinada com o certificado;-in certificado.crt
- use o arquivocertificado.crt
como o certificado com a qual a chave privada será combinada;-certfile intermediario.crt
- essa parte é opcional, serve para incluir quaisquer certificados adicionais que você queira incluir no arquivo PKCS#12.
Ao inserir o comando será solicitada uma senha de exportação para proteger o arquivo PKCS#12, isso é importante pois nesse arquivo constam o certificado e a chave privada. Essa chave será solicitada sempre que o arquivo for importado, portanto ela deve ser anotada.
Testando se a chave privada casa com o certificado ou com o CSR
Na criptografia de chave pública RSA, as chaves pública e privada de um par são matematicamente relacionadas, pois compartilham o mesmo módulo. O comprimento do módulo, expresso em bits, é o comprimento da chave.
Para confirmar se uma chave privada específica corresponde à
chave contida em uma solicitação de assinatura de certificado
e/ou um certificado, é preciso confirmar que os módulos de ambas
as chaves são idênticos. Isso pode ser feito diretamente com o
comando openssl
.
Para visualizar o hash md5 do módulo da chave privada:
openssl rsa -noout -modulus -in chaveprivada.key | openssl md5
Para visualizar o hash md5 do módulo do CSR:
openssl req -noout -modulus -in requisicao.csr | openssl md5
Para visualizar o hash md5 do módulo do certificado:
openssl x509 -noout -modulus -in mycert.crt | openssl md5
Se as hash da chave e do certificado ou do CSR corresponderem quer dizer que há compatibilidade.
Além da verificação visual lendo as hash podemos usar o comando
diff
para comparar-las:
┌─[jeremias@lab-lpi2]──[23:59]──[/tmp/certificado] └─[1004]─>$ openssl rsa -noout -modulus -in chaveprivada.key | openssl md5 > privkey-mod.txt ┌─[jeremias@lab-lpi2]──[00:00]──[/tmp/certificado] └─[1005]─>$ openssl x509 -noout -modulus -in certificado.crt | openssl md5 > cert-mod.txt ┌─[jeremias@lab-lpi2]──[00:01]──[/tmp/certificado] └─[1006]─>$ openssl req -noout -modulus -in requisicao.csr | openssl md5 > req-mod.txt ┌─[jeremias@lab-lpi2]──[00:10]──[/tmp/certificado] └─[1007]─>$ diff3 req-mod.txt cert-mod.txt privkey-mod.txt ┌─[jeremias@lab-lpi2]──[00:11]──[/tmp/certificado] └─[1008]─>$ diff req-mod.txt privkey-mod.txt ┌─[jeremias@lab-lpi2]──[00:11]──[/tmp/certificado] └─[1010]─>$ diff cert-mod.txt privkey-mod.txt
Gerando um novo CSR a partir da chave privada e de um certificado preexistente
Eventualmente pode ser necessário criar um novo arquivo de requisição de certificado, como por exemplo quando um certificado está a expirar e precisamos renová-lo. Nessas situações pode ser interessante gerar um CSR a partir de um certificado preexistente pois dessa forma não precisaremos preencher manualmente todos os dados necessários ao certificado (pois eles encontran-se dentro do certificado antigo).
$ openssl x509 \ -in certificado-antigo.crt \ -sigkey chaveprivada.key \ -x509toreq -out requisicao.csr
Como o SSL funciona na relação cliente servidor
- Tal como mostrado na seção Secure Socket Layer a comunicação se inicia pelo client solicitando a página por um meio não criptografado (porta 80).
- Recebendo então como resposta o certificado do Webserver.
- O navegador do cliente faz a validação desse certificado utilizando as informações que constam no certificado sobre a CA que o emitiu.
- Se forem válidas ele:
- Gerará um novo par de chaves pública/privada para uso próprio;
- Armazenará na "chave de seção" a chave privada que acabou de gerar;
- Armazenará a chave pública que consta no certificado do servidor como uma "chave de seção".
- Utilizando a chave pública armazenada na "chave de seção" em
conjunto com o gerador de dados aleatórios do sistema
/etc/random
o cliente inicia uma comunicação criptografada com o Webserver enviando para ele sua chave pública e a solicitação de dados da página. - Após os dados serem descriptografados usando a chave privada do servidor o webserver terá a chave pública do cliente que é armazenada na "chave de seção" e envia a solicitação do cliente para o "input data" da página.
- O webserver analisa a solicitação do cliente entregue em Input data
e agora de posse da chave pública gerada pelo cliente
armazenada em sua "chave de seção", responde a solicitação do
cliente criptografando os dados a serem enviados utilizando o
seu gerador de dados aleatórios
/dev/random/
em conjunto com a chave pública recebida pelo usuário. - Os dados são enviados criptografados para o cliente;
- Usando a chave privada que foi gerada anteriormente e que está armazenada em sua "chave de seção" o cliente consegue descriptografar os dados e enviá-los ao navegador.
- Mediante solicitação do usuário o navegador pode reiniciar o ciclo. Porém agora com "uma seção aberta" isto é, com todo esse processo de troca de chaves já executado.
Figura 8: Fluxo de comunicação HTTPS (troca de chaves)
Aplicando o SSL no Apache - Módulo mod_ssl
O módulo responsável por prover comunicação encriptografada no
Apache é o mod_ssl
hoje em dia ele já vem disponível no pacote
de instalação padrão do Apache. Antes ele era distribuído como um
pacote separado, o pacote continha:
- O próprio módulo (
mod_ssl.so
); - Os arquivos de configuração necessários.
Diretivas do apache para o SSL
O mod_ssl
tem diretivas específicas para trabalhar com o SSL:
SSLCertificateFile
- O nome do arquivo que contém o certificado digital;
SSLCertificateKeyFile
- O nome do arquivo que contém a chave privada;
SSLCypherSuite
- Especifica o algoritmo de criptografia que o navegador pode usar;
SSLEngine
(on/off)- Habilita ou desabilita o SSL
(geralmente usado dentro da seção de um
VirtualHost
). SSLEnable
- É um alias para
SSLEngine on
; SSLRequire
- Suporta controle de acesso baseado em múltiplas variáveis de servidor.
Se todos os procedimentos que executamos até aqui foram bem sucedidos (criação da chave privada, criação e envio do CSR para a CA e recebimento do certificado da CA). Teremos dois arquivos importantes em mãos. A chave privada e o certificado emitido pela CA.
Copie os arquivos para um local definitivo, como por exemplo
/etc/ssl/
.
Em um servidor rodando CentOS, após instalado o suporte ao SSL,
será criado o arquivo /etc/htpd/conf.d/ssl.conf
. Nele haverá as
configurações básicas de funcionamento do SSL.
Em uma configuração simplificada (sem usar VirtualHost
)
poderíamos procurar as diretivas que citamos acima e editá-las
colocando os caminhos para os arquivos de chave e certificado,
também executando os demais ajustes que forem necessários
(SSLEnable
e aí por diante).
Certificados auto-assinados
Além de ser um dos conhecimentos chave desse protocolo, saber criar uma CA própria para publicar certificados auto-assinados é uma necessidade que eventualmente aparece no dia a dia de um administrador de infraestrutura.
Assim o uso certificado auto-assinado irá criptografar corretamente a comunicação entre seu servidor e qualquer cliente. Porém como ele não tem a assinatura de nenhuma das Autoridades Certificadoras oficiais, um usuário "terceiro" receberá um alerta na tela do navegador informando que a autenticidade do certificado e, por consequência, de seu site não pode ser comprovada.
Porém um certificado auto-assinado pode ser útil para em ambientes como uma rede local, onde faz-se necessário publicar algo via webserver e não se quer que essa informação trafegue descriptografada mesmo na rede local. Nesse cenário é possível contornar a situação do alerta de autenticidade mostrado no navegador, copiando a chave pública da CA gerada e distribuindo ela nos computadores da rede local. Assim eles confiarão no seu site. Essa atividade pode ser automatizada utilizando GPOs de Windows, ou até mesmo criando tanto a CA quanto os certificados através do AD do local.
Criando uma CA e seus certificados no Linux
Quando o administrador precisa ter sua própria CA ele irá se
responsabilizar por todo o workflow de geração dos
certificados. Iniciando-se pela geração da chave
privada da CA. Que é executada com o comando openssl
:
openssl genrsa -des3 -out ca.key 4096
Como estamos criando uma chave para a CA é de fundamental
importância que ela tenha uma senha, portanto usamos o parâmetro
-des
que fará com que ao executar o comando seja solicitada uma
senha, depois solicitará sua confirmação. Guarde essa senha pois
ela será necessária para a emissão dos seus certificados.
Após cria-se o certificado X509 da CA, este certificado conterá as informações necessárias para a validação da CA e sua chave pública:
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt
Ao executar o comando ele solicitará a senha que criamos acima, depois solicitará dados como abreviatura de País, Estado, Cidade, nome da organização e afins. São essas informações que estarão contidas no certificado juntamente com a chave pública.
Para auditar o conteúdo do certificado gerado utiliza-se o comando:
openssl x509 -in ca.crt -text
onde ca.crt
é o nome do
certificado a inspecionar.
Agora cria-se o certificado que será instalado no servidor
propriamente dito. Assim repetiremos os passos executados
acima. Primeiramente criaremos uma chave privada, note que para
o servidor ter uma senha para a chave privada pode não ser
prático, pois ela será solicitada sempre que precisarmos
reiniciar o Apache, portanto aqui no nosso laboratório
removeremos a opção -des
:
openssl genrsa -out servidor.key
Agora geraremos o Certificate Signing Request (CSR) para que possamos requisitar à nossa CA a assinatura de um certificado. Lembre-se do que já vimos anteriormente o CSR é composto por uma chave pública concatenado com as informações do nosso site e ou serviço:
openssl req -new -key servidor.key -out servidor.csr
Se ficar duvidoso quanto a geração do CSR o conteúdo dele pode ser validado com o comando:
openssl req -in servidor.csr -text
onde servidor.csr
é o CSR
a ser validado
Agora com o CSR podemos assinar ele com nossa CA:
openssl x509 -req -days 365 -in servidor.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out servidor.crt
Durante a execução será solicitada a senha da chave da CA e por fim será emitido o certificado. Note que como executamos todos os comandos sem executar caminhos todos os arquivos que geramos até aqui estarão dentro do diretório corrente:
ls -l total 20 -rw-rw-r-- 1 usuario usuario 2183 mar 25 22:54 ca.crt -rw------- 1 usuario usuario 3311 mar 25 22:49 ca.key -rw-rw-r-- 1 usuario usuario 2045 mar 25 23:18 servidor.crt -rw-rw-r-- 1 usuario usuario 1781 mar 25 23:07 servidor.csr -rw------- 1 usuario usuario 3243 mar 25 23:07 servidor.key
Se você chegou até aqui e não tiver cinco arquivos novos no seu diretório reveja os passos.
Agora é só aplicar os certificados no seu Apache da mesma forma que faria com um certificado pago.
E como já exposto no tópico anterior, se não quiser alertas de autenticidade nos navegadores dos seus usuários instale o certificado da CA nesses navegadores.
Gerando certificados auto-assinados no Linux
Se não quiser se criar certificados para vários servidores, mas apenas emitir um certificado para um caso específico pode-se trabalhar com certificados-autoassinados que são assim chamados por não haver uma CA assinando por ele.
Portanto novamente usamos o comando openssl
que nessa sintaxe
criará tanto a chave privada quanto o certificado:
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout exemplo.key -out exemplo.crt
Agora valide o certificado criado:
openssl x509 -in exemplo.crt -text
Por fim aponte o certificado e a respectiva chave no apache conforme já executamos anteriormente. Lembrando que como nesse caso não criamos uma CA quando o navegador apresentar o alerta de autenticidade o usuário deverá apenas aceitar isso no botão devido na tela de alerta do navegador.
Problemas do SSL com VirtualHosts
O problema de usar SSL em sites hospedados em VirtualHosts
baseados em nome é que os VirtualHosts
precisam saber qual
hostname está sendo solicitado e essa solicitação não pode ser
lida até que a conexão SSL seja estabelecida.
O comportamento normal, então, é que a conexão SSL seja configurada usando a configuração no host virtual padrão para o endereço onde a conexão foi recebida.
Apesar de o Apache poder renegociar a conexão SSL, depois de ver o nome do host na solicitação (e o faz), acaba sendo tarde demais para escolher o certificado do servidor correto a ser usado para corresponder ao nome do host da solicitação durante o handshake inicial, resultando em avisos e erros do navegador sobre certificados tendo o hostname errado neles.
Apesar de hoje em dia ser possível criar um certificado que inclua vários hostnames e até mesmo certificados wildcard que abrangem um domínio todo. Em alguns casos o uso destes pode não ser possível.
Mitigando o problema com o SNI
O Server Name Indication (SNI) ou "Indicação de Nome de
Servidor", em tradução nossa, é uma extensão do protocolo SSL
conforme a RFC 4366 que permite ao cliente incluir o hostname
na primeira mensagem do handshake do SSL (connection
setup). Assim permite-se ao webserver determinar o
VirtualHost
correto para a requisição.
Com o SNI, podem haver vários VirtualHost
compartilhando o
mesmo endereço de IP e porta e cada um com seu próprio certificado.