Skip to main content

208.2 Configurações do Apache para HTTPS


Introdução


Vamos entender de forma não muito aprofundada o que é, e como funciona o HTTPS no Apache. O HTTPS (Hyper Text Transfer Protocol Secure) é uma implementação do protocolo HTTP no qual é adicionada uma camada de segurança que utiliza o protocolo TLS/SSL.


Essa segurança adiciona uma criptografia nos dados que são trafegados entre cliente e servidor impedindo que um terceiro consiga ler os dados. Já os dados trafegados sem essa criptografia (aqui estou citando o HTTP) podem ser lidos caso sejam capturados por um terceiro.


Por praticidade sempre dizemos que é usado SSL para criptografia, mas na realidade (na maioria dos casos) é usado o TLS.


O TLS (Transport Layer Security) e seu antecessor (SSL) Secure Sockets Layer, são protocolos de segurança que fornecem uma camada de segurança nas comunicações sobre uma rede de computadores. Hoje em dia é mais usado o TLS por ser a evolução do SSL, principalmente porque o SSL já possui algumas falhas.

SSL/TLS implementa encriptação dos dados e com isso garantem a autenticidade.



Handshake com uso de SSL/TLS


Vamos entender como acontece o Handshake quando temos SSL/TLS, caso queira saber como acontece um Handshake normal do TCP/IP veja aqui.


Veja uma imagem retirada do site da IBM demonstrando o passo a passo desse handshake.

Handshake SSL/TLS

  1. O Cliente envia um "Client hello" para o servidor com as informações de criptografia.

    Dentro dessas informações estão inclusas que tipos de protocolos o cliente consegue entender para assim determinar qual protocolo e versão dos mesmos devem ser usados.

  2. O Servidor recebe e identifica os dados fornecidos pelo cliente e responde para ele um "Server hello" informando:

    • CipherSuit Como eles vão se comunicar;
    • Certificado do domínio que reside no servidor, é diferente do certificado do servidor, esse certificado é para validar o domínio e não o servidor que está respondendo. Além do certificado do domínio é enviado a chave pública do servidor.
  3. O cliente verifica o certificado do servidor e checa os parâmetros de criptografia e a criptografia que deve ser usada.

  4. Agora o cliente faz a troca de chaves com o servidor, enviando sua chave pública já encriptada com a chave pública do servidor.

    Todo esse processo é a parte de encriptação.

  5. Envia seu certificado de cliente.



Certificado Digital


O Certificado digital é um documento eletrônico (arquivo) que relaciona um indivíduo, equipamento ou entidade a uma chave pública. Esse documento é assinado por uma autoridade que é confiável a todos os indivíduos que estão participando da comunicação.


A função do Certificado Digital é comprovar a autenticidade de uma dada chave pública pertencente a um indivíduo, equipamento ou entidade.

No nosso caso a chave pública comprova a autenticidade de um domínio e pode também comprovar a autenticidade de um servidor, apesar de não ser muito comum essa utilização.


A entidade que emite o Certificado é conhecida como Autoridade Certificadora ou Certificate Authority (CA), todos os navegadores devem conhecer todas as CA que existem para esse propósito e confiar nos certificados que elas geram.



Padrão X.509


O Padrão X.509 é um padrão de certificação de chave pública, ou seja, é um certificado digital usado para autenticar a identidade de um usuário que estabelece uma conexão de rede segura. Os certificados X.509 são emitidos por autoridades certificadas, também chamadas de autoridades de certificado raiz (ou mais comumente como CA).


Os certificados X.509 contêm informações do usuário, incluindo os nomes do usuário e da autoridade, uma palavra-passe criptografada, chaves públicas assinadas pela autoridade certificada, indicações de data de validade, assinatura digital e outros detalhes da certificação. O X.509 padrões são largamente utilizados em protocolos de segurança, como o SSL (Secure Sockets Layer) e o TLS (Transport Layer Security).



Cabeçalhos do X.509


Vamos ver os principais cabeçalhos usados no X.509, somente para a versão 3.

CabeçalhoDescrição
VersionIdentifica a versão do X.509 (o normal é encontrar V3).
Serial NumberÉ um valor inteiro e único para cada certificado gerado por determinado CA.
Signature Algorithm IDIdentifica o algoritmo usado para assinar o certificado, nele contém a função de hash associada também.
Issuer NameIdentifica o nome do emissor (DN) que cria e assina o certificado.
Validity periodÉ o período de validade do Certificado (Not before = Válido a partir de | Not after = Válido até).
Subject nameNome da entidade final (DN), ou seja, é o sujeito a qual a chave privada corresponde.
Subject Public Key InfoContém a chave pública da entidade final.
Issuer Unique Identifier (optional)Assinatura do emissor do certificado.

Como curiosidade seguem alguns comandos:

# Descobrir o emissor de um certificado:
$ openssl s_client -showcerts -servername www.sysnetbr.eng.br -connect www.sysnetbr.eng.br:443 2>/dev/null | grep -i issuer
issuer=C = US, O = Let's Encrypt, CN = R3

# Descobrir quais domínios um certificado está relacionado:
$ openssl s_client -showcerts -servername www.sysnetbr.eng.br -connect www.sysnetbr.eng.br:443 2>/dev/null | openssl x509 -noout -ext subjectAltName
X509v3 Subject Alternative Name:
DNS:www.sysnetbr.eng.br


Path de Certificação


Nós com o certificado podemos fazer o processo inverso para chegar ao CA do certificado. Todo certificado é assinado por um emissor, esse emissor é conhecido pela sigla CA (Autoridade Certificadora ou Certificate Authority em Inglês).


Cada CA possui seu próprio certificado que é usado para assinar outros certificados, pensa que é um certificado usado apenas para assinar outros certificados. No entanto, esse certificado pode ter sido assinado por outro certificado (não é comum mas pode acontecer).


O primeiro certificado do primeiro emissor desse caminho é auto-assinado, ou seja, esse CA é emissor e entidade final do seu próprio certificado.


O caminho desse primeiro CA até a entidade final é conhecido como Caminho de Certificação.

# Podemo ver o caminho usando o comando abaixo:
$ openssl s_client -connect google.com.br:443
CONNECTED(00000003)
depth=2 C = US, O = Google Trust Services LLC, CN = GTS Root R1
verify return:1
depth=1 C = US, O = Google Trust Services LLC, CN = GTS CA 1C3
verify return:1
depth=0 CN = *.google.com.br
verify return:1
---
Certificate chain
0 s:CN = *.google.com.br
i:C = US, O = Google Trust Services LLC, CN = GTS CA 1C3
a:PKEY: id-ecPublicKey, 256 (bit); sigalg: RSA-SHA256
v:NotBefore: Jan 9 08:19:48 2023 GMT; NotAfter: Apr 3 08:19:47 2023 GMT
1 s:C = US, O = Google Trust Services LLC, CN = GTS CA 1C3
i:C = US, O = Google Trust Services LLC, CN = GTS Root R1
a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
v:NotBefore: Aug 13 00:00:42 2020 GMT; NotAfter: Sep 30 00:00:42 2027 GMT
2 s:C = US, O = Google Trust Services LLC, CN = GTS Root R1
i:C = BE, O = GlobalSign nv-sa, OU = Root CA, CN = GlobalSign Root CA
a:PKEY: rsaEncryption, 4096 (bit); sigalg: RSA-SHA256
v:NotBefore: Jun 19 00:00:42 2020 GMT; NotAfter: Jan 28 00:00:42 2028 GMT


Como gerar o certificado?


Para nosso ambiente com Linux/Unix, o administrador vai gerar um registro que chama CSR (Certificate Signing Request) que é basicamente um arquivo.

Aqui temos algumas informações:

Nome da empresa, E-mail do administrador, nome do administrador, nome do(s) domínio(s), nome do Servidor Web e muito mais.

Esse processo pode ser simplificado dependendo da CA, com a Let's Encrypt por exemplo é tudo mais simples.


Depois esse arquivo é enviado para um CA (como explicado mais acima), depois do CA validar as informações enviadas é gerado um Certificado Digital e com isso podemos adicionar o certificado no servidor.


Para ambiente de testes vamos criar um certificado auto-assinado, que apesar de fornecer criptografia, não é reconhecido pelos navegadores.



Gerando os Certificados


Agora vamos gerar o certificado e depois fazer a instalação dele (mapeamento do arquivo no Apache). Primeiro de tudo temos que certificar de termos o módulo do SSL para o Apache, por padrão já vem e temos que ter o openssl instalados:

$ sudo ls -l /etc/apache2/mods-available/*ssl*
-rw-r--r-- 1 root root 3110 Feb 23 2021 /etc/apache2/mods-available/ssl.conf
-rw-r--r-- 1 root root 97 Feb 23 2021 /etc/apache2/mods-available/ssl.load

# O módulo aqui no Ubuntu/Debian é referenciado dentro do '.load':
$ sudo grep '\.so' /etc/apache2/mods-available/ssl.load
LoadModule ssl_module /usr/lib/apache2/modules/mod_ssl.so

# Verificando o Openssl:
$ dpkg -l openssl
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-==============-==================-============-====================================================
ii openssl 1.1.1f-1ubuntu2.16 amd64 Secure Sockets Layer toolkit - cryptographic utility

Perceba que no CentOS 7 não tem o módulo do SSL.


Com isso em ambos os sistemas existe um arquivo chamado ssl.conf, veja a localização:

$ ls -lh /etc/apache2/mods-available/ssl.conf
-rw-r--r-- 1 root root 3.1K Feb 23 2021 /etc/apache2/mods-available/ssl.conf

Esses arquivos possuem configurações gerais para o SSL como: porta que vai ouvir, versões dos protocolos e quais protocolos (SSL/TLS).


Agora vamos gerar os certificados:

# Crie um diretório para colocar o certificado:
$ sudo mkdir /etc/apache2/ssl

## Gere Chave privada do certificado:
$ sudo openssl genrsa -des3 -out /etc/apache2/ssl/test.com.ze.key 2048

### É possível testar a senha com o comando abaixo (se der certo nenhum erro vai aparecer):
$ sudo openssl rsa -noout -in test.com.ze.key

## Gere o CSR usando a chave privada:
$ openssl req -new -key test.com.ze.key -out test.com.ze.csr -subj "/C=BR/ST=SP/L=Sao Paulo/O=Test Company/CN=test.com.ze"

### Podemos testar o CSR criado:
$ sudo openssl req -in test.com.ze.csr -text -noout

# Vamos criar um CA usando o script abaixo:
$ sudo /usr/lib/ssl/misc/CA.pl -newca
.
.
.
Certificate Details:
Serial Number:
77:df:be:42:e1:b8:b7:8a:7f:a5:d5:05:9b:89:ba:bd:c8:9e:7d:11
Validity
Not Before: Feb 7 20:54:31 2023 GMT
Not After : Feb 6 20:54:31 2026 GMT
Subject:
countryName = BR
stateOrProvinceName = Sao Paulo
organizationName = Test Company CA
commonName = test.com.ze
X509v3 extensions:
X509v3 Subject Key Identifier:
0E:F7:A9:DC:2F:F6:B8:41:B8:B8:B8:5E:5B:C5:79:CF:44:64:87:F0
X509v3 Authority Key Identifier:
keyid:0E:F7:A9:DC:2F:F6:B8:41:B8:B8:B8:5E:5B:C5:79:CF:44:64:87:F0

X509v3 Basic Constraints: critical
CA:TRUE
Certificate is to be certified until Feb 6 20:54:31 2026 GMT (1095 days)

Write out database with 1 new entries
Data Base Updated
==> 0
====
CA certificate is in ./demoCA/cacert.pem

## Se você obter erros no comando acima tente atualizar o 'openssl' e 'libssl1.1' !


# Veja o CA que foi criado:
$ ls demoCA/cacert.pem

## Agora vamos assinar o certificado usando esse CA!

# Copie o .csr com o nome 'newrew.pem':
$ sudo cp test.com.ze.csr newreq.pem

# Agora assine:
$ sudo /usr/lib/ssl/misc/CA.pl -sign
====
openssl ca -policy policy_anything -out newcert.pem -infiles newreq.pem
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for ./demoCA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number:
77:df:be:42:e1:b8:b7:8a:7f:a5:d5:05:9b:89:ba:bd:c8:9e:7d:12
Validity
Not Before: Feb 7 20:55:55 2023 GMT
Not After : Feb 7 20:55:55 2024 GMT
Subject:
countryName = BR
stateOrProvinceName = SP
localityName = Sao Paulo
organizationName = Test Company
commonName = test.com.ze
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
C2:77:35:E2:23:0D:5C:59:D5:BA:7E:16:4C:2E:FE:CA:01:64:B2:42
X509v3 Authority Key Identifier:
keyid:0E:F7:A9:DC:2F:F6:B8:41:B8:B8:B8:5E:5B:C5:79:CF:44:64:87:F0

Certificate is to be certified until Feb 7 20:55:55 2024 GMT (365 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
==> 0
====
Signed certificate is in newcert.pem

# Agora copie com nome CRT:
$ sudo cp newcert.pem /etc/apache2/ssl/test.com.ze.crt

O CSR (Certificate Signing Request) é um arquivo de texto criptografado que contém informações sobre a identidade do solicitante, incluindo nome da empresa, endereço de e-mail e endereço do site. Ele é usado para solicitar a emissão de um certificado SSL para o site.


O CRT (Certificate) é um arquivo de texto que contém informações sobre a identidade da empresa e a chave pública do site. Ele é emitido pela autoridade de certificação após a verificação da identidade da empresa. O CRT é necessário para configurar o certificado SSL no site e para estabelecer a conexão segura com os visitantes do site.


Ou seja, o CSR é usado para solicitar o certificado SSL, enquanto que o CRT é o certificado SSL em si, emitido pela autoridade de certificação. É importante ter cuidado ao gerar e enviar o CSR, pois as informações contidas nele são confidenciais e devem ser protegidas.


No CentOS 8 o CA.pl está em /usr/bin/CA.pl. Caso não veja ele, nstale o pacote openssl-perl.


É possíve gerar tanto a Chave quanto o CRT com o mesmo comando sem precisar passar pelo CSR:

$ sudo openssl req -new -x509 -days 365 \
-nodes -out /etc/apache2/ssl/zona.com.ze.crt \
-keyout /etc/apache2/ssl/zona.com.ze.key \
-subj "/C=BR/ST=SP/L=Sao Paulo/O=Test Company/CN=zona.com.ze"

Outro detalhe ao gerar o certificado usando uma CA é que você pode ver a informação CA:FALSE, isso significa que o certificado não pode ser usado para emissão de outros certificados. É muito comum vermos certificados assinados por uma CA que não tenham a autorização para emissão de outros certificados, pois esta é uma funcionalidade restrita apenas às CAs.


Se você precisar de um certificado com a permissão de emissão de outros certificados, você pode solicitar um certificado "raiz" ou "intermediário" diretamente da CA. Certificados deste tipo são geralmente usados para assinar outros certificados, e possuem a extensão CA:TRUE. Caso você queira um certificado auto-assinado pode usar o flow abaixo:

## Gere Chave privada do certificado:
$ sudo openssl genrsa -des3 -out CA.key 2048

### É possível testar a senha com o comando abaixo (se der certo nenhum erro vai aparecer):
$ sudo openssl rsa -noout -in CA.key

## Gere o CSR usando a chave privada:
$ openssl req -new -key CA.key -out cr.csr -subj "/C=BR/ST=SP/L=Sao Paulo/O=Test Company/CN=test.com.ze"

### Podemos testar o CSR criado:
$ sudo openssl req -in cr.csr -text -noout

## Assine o certificado com a própria chave privada:
$ openssl req -days 3650 -in cr.csr -key CA.key -new -x509 -out cert.crt -subj "/C=BR/ST=Bahia/L=Salvador/O=Information Ltda/CN=zona.com.ze"

### Mostra o conteúdo do certificado:
$ openssl x509 -in cert.crt -text -noout | grep -B1 -i ca:true
X509v3 Basic Constraints: critical
CA:TRUE

Agora temos um certificado auto-assinado com permissão de emissão de outros certificados. Este certificado pode ser usado como uma raiz de confiança para assinar outros certificados.

Lembrando que o comando abaixo já faz tudo isso de uma vez:

$ sudo openssl req -new -x509 -days 365 \
-nodes -out /etc/apache2/ssl/zona.com.ze.crt \
-keyout /etc/apache2/ssl/zona.com.ze.key \
-subj "/C=BR/ST=SP/L=Sao Paulo/O=Test Company/CN=zona.com.ze"

Observe que, como se trata de um certificado auto-assinado, ele não será reconhecido como confiável por um sistema sem a sua inclusão prévia na lista de autoridades de certificação confiáveis, por isso é comendado o uso em ambientes de teste ou Intranet.


Instalando os Certificados


Vamos ver como instalar o certificado no site que estamos provendo.

# Edite o arquivo abaixo:
$ sudo vim /etc/apache2/sites-enabled/vagranthome.conf

# Adicione a configuração abaixo:
<VirtualHost *:443>
ServerAdmin fulano@gmail.com
ServerName zona.com.ze

# Habilitando o SSL (mesmo que já esteja, é bom fazer assim)
SSLEngine on

# É o certificado em sí
SSLCertificateFile /etc/apache2/ssl/zona.com.ze.crt

# Chave privada:
SSLCertificateKeyFile /etc/apache2/ssl/zona.com.ze.key
</VirtualHost>
q

# Reinicie o apache:
$ sudo systemctl restart apache2

Algumas outras opções que podemos usar:

OpçãoDescrição
SSLCACertificateFileO SSLCACertificateFile também é utilizado para informar um certificado intermediário que venha a ser fornecido pelo CA. Arquivo que contém o certificado do CA ou do Intermediário do CA (.pem)
SSLCertificateKeyFileArquivo que contém a chave privada (.key)
SSLCertificateFileArquivo que contém o certificado do servidor web (.crt)

O que é um Certificado Intermediário?


A autoridade de certificação raiz ou a âncora confiável pode assinar e emitir certificados intermediários. Certificados intermediários (também conhecidos como intermediário, subordinado ou CAs emissoras) fornecem uma estrutura flexível para conferir a validade da âncora de confiança (chain of trust) a certificados de entidades intermediárias e finais adicionais na cadeia. Nesse sentido, os certificados intermediários cumprem uma função administrativa; cada intermediário pode ser usado para uma finalidade específica – como a emissão de SSL/TLS ou certificados de assinatura de código – e pode até ser usado para conferir a confiança da CA raiz para outras organizações.


Os certificados intermediários também fornecem um buffer entre o certificado da entidade final e a CA raiz, protegendo a chave raiz privada do comprometimento. Para CAs publicamente confiáveis (incluindo SSL.com), as regras publicamente definidas proíbem a emissão de certificados de entidade final diretamente da CA raiz, que deve ser mantida offline com segurança. Isso significa que qualquer cadeia de confiança de certificado confiável publicamente incluirá pelo menos um certificado intermediário.

Fonte e mais sobre “Chain of Trust”: https://www.ssl.com/faqs/what-is-a-chain-of-trust/



Certificados de Cliente


Vamos fazer com que só seja possível acessar um site caso o cliente possua um certificado específico, isso mesmo, caso o cliente possua um certificado.


Esse certificado deve ter sido assinado pelo CA que é usado para verificar a validade de certificados SSL/TLS apresentados pelos clientes que se conectam ao servidor.


Para esse teste vou deixar o compartilhamento abaixo no Apache:

<VirtualHost *:443>
ServerAdmin fulano@gmail.com
ServerName test.com.ze
DocumentRoot /var/www/html

# Habilitando o SSL (mesmo que já esteja, é bom fazer assim)
SSLEngine on

# É o certificado em sí
SSLCertificateFile /etc/apache2/ssl/test.com.ze.crt

# Chave privada:
SSLCertificateKeyFile /etc/apache2/ssl/test.com.ze.key

# Informa o CA:
SSLCACertificateFile /etc/apache2/ssl/cacert.pem

# Faz a verificação da chave do cliente:
<Directory /var/www/html/cert>
SSLVerifyClient require
</Directory>
</VirtualHost>

Lembrando que para funcionar mesmo só precisamos das opções abaixo, as outras é para funcionar o SSL/TLS:

        # Informa o CA:
SSLCACertificateFile /etc/apache2/ssl/demoCA/cacert.pem

# Faz a verificação da chave do cliente:
<Directory /var/www>
SSLVerifyClient require
</Directory>

Agora para que funcione vamos criar o certificado do cliente.

# Entre no diretório abaixo:
$ cd /etc/apache2/ssl

# Comece gerando a chave:
$ openssl genrsa -des3 -out client.key 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
...................................+++++
...............+++++
e is 65537 (0x010001)
Enter pass phrase for client.key:
Verifying - Enter pass phrase for client.key:

# Gere o CSR para o usuário:
$ openssl req -new -key client.key -out client.csr -subj "/C=BR/ST=SP/L=Sao Paulo/O=Fulano da Silva Junior/CN=Fulano da Silva Junior/emailAddress=fulano@examplo.com.br"

# Mude o nome do CSR:
$ cp client.csr newreq.pem

# Gere o certificado:
$ sudo /etc/pki/tls/misc/CA -sign
====
openssl ca -policy policy_anything -out newcert.pem -infiles newreq.pem
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for ./demoCA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number:
77:df:be:42:e1:b8:b7:8a:7f:a5:d5:05:9b:89:ba:bd:c8:9e:7d:13
Validity
Not Before: Feb 10 20:26:05 2023 GMT
Not After : Feb 10 20:26:05 2024 GMT
Subject:
countryName = BR
stateOrProvinceName = SP
localityName = Sao Paulo
organizationName = Fulano da Silva Junior
commonName = Fulano da Silva Junior
emailAddress = fulano@examplo.com.br
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
AF:01:2B:BE:3D:B3:AF:7D:BA:6C:53:70:29:7B:BB:C9:95:8F:CB:DC
X509v3 Authority Key Identifier:
keyid:0E:F7:A9:DC:2F:F6:B8:41:B8:B8:B8:5E:5B:C5:79:CF:44:64:87:F0

Certificate is to be certified until Feb 10 20:26:05 2024 GMT (365 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
==> 0
====
Signed certificate is in newcert.pem


# Renomeio o certificado:
$ mv newcert.pem fulano.crt

# Agora vamos gerar um certificado no formato P12:
$ openssl pkcs12 -export -inkey client.key -in fulano.crt -out fulano.p12
Enter pass phrase for client.key:
Enter Export Password:
Verifying - Enter Export Password:

Um certificado no formato P12 (também conhecido como PKCS#12) é um arquivo que contém uma chave privada e um certificado digital associado. Ele é usado comumente para autenticação de serviços web seguros, assinatura de e-mails e criptografia de dados.

O formato P12 é amplamente utilizado porque é compatível com vários sistemas operacionais e navegadores, além de ser fácil de usar e proteger a privacidade das informações contidas no arquivo, já que ele é protegido por uma senha.

Os certificados no formato P12 são geralmente emitidos por uma autoridade certificadora (CA), que verifica a identidade da pessoa ou empresa que solicita o certificado e confirma sua validade. Depois de ter um certificado P12 válido, você pode usá-lo para estabelecer uma conexão segura com outros serviços na internet.


Depois disso importe o certificado no navegador.


Se você estiver recebendo o erro abaixo pode ser que alguns navegadores não suportem o TLS 1.3 post-handshake authentication, existe uma solução no Firefox (testada na versão 109.0.1 (64-bit)).

You don't have permission to access this resource.Reason: Cannot perform Post-Handshake Authentication.

No Firefox acesse about:config e mude a opção security.tls.enable_post_handshake_auth para true.



Configurações de Segurança


Vamos aplicar algumas configurações de segurança no Apache, começando pela parte de SSL/TLS, essa configuração fica em locais diferentes dependendo do sistema. No Debian fica em /etc/apache2/mods-enabled/ssl.conf e no CentOS fica em /etc/httpd/conf.d/ssl.conf.


OpçãoDescrição
SSLProtocolEssa opção é usada para especificar quais protocolos de segurança SSL/TLS devem ser suportados pelo servidor web.
SSLProtocol all -SSLv3
SSLProtocol -all +TLSv1.2
Caso veja um - (sinal de menos) significa que essa versão não será suportada. E caso veja um + (sinal de mais) significa que essa versão será suportada.
SSLCipherSuiteEssa opção é usada para configurar as cifras (algoritmos de criptografia) que serão suportados pelo Servidor Web durante a negociação SSL/TLS.
SSLCipherSuite HIGH:!aNULL
Caso veja um simbolo de exclamação ! significa que essa cifra não será suportada. As cifras são separadas por : (dois pontos).
SSLHonorCipherOrderEssa opção é usada para controlar a ordem de preferência das cifras durante a negociação SSL/TLS. Dessa forma podemos especificar a ordem em que as cifras devem ser consideradas durante a negociação.
Caso essa opção tenha seu valor como On, o servidor usará a ordem de preferência das cifras especificada na opção SSLCipherSuite para selecionar a cifra a ser usada. Isso significa que a cifra especificada primeiro na lista será escolhida, a menos que ela não seja suportada pelo cliente, aí a próxima cifra na lista será considerada.
Caso seja Off, o servidor usará sua própria ordem de preferência das cifras. Neste caso, a cifra escolhida pode não ser a mesma que a especificada na opção SSLCipherSuite.
ServerTokensPor padrão essa opção pode não existir, então temos que incluir ela.
Essa opção é usada para controlar a quantidade de informação sobre o servidor que é incluída no cabeçalho de resposta HTTP.
ServerTokens Full ou OS ou Prod
A opção Full exibe todas as informações;
A opção OS exibe informações apenas do Sistema Operacional;
A opção Prod é a que exibe menos informações, ela vai retornar apenas qual Servidor Web está em uso, mas não mostra versão nem qual SO está rodando.
Essa configuração já vem aplicada em /etc/apache2/conf-available/security.conf no Debian, portanto, se mudar em outro lugar pode nao surtir efeito, então mude nesse arquivo mesmo.
ServerSignatureEssa opção é usada para controlar a exibição de informações sobre o servidor na página de erro padrão do servidor web. Quando o servidor não consegue processar uma solicitação HTTP, ele geralmente retorna uma página de erro padrão com informações sobre o erro que ocorreu. Essa página de erro padrão pode incluir informações sobre o servidor, como o nome e a versão do software de servidor.
Por segurança sempre defina como Off. Essa configuração já vem aplicada em /etc/apache2/conf-available/security.conf no Debian, portanto, se mudar em outro lugar pode nao surtir efeito, então mude nesse arquivo mesmo.
Se definido com valor email, será retornado o email configurado no ServerAdmin da página.
TraceEnableÉ uma diretiva usada para habilitar ou desabilitar o método HTTP Trace. Com ele ativado permite que um cliente envie uma solicitação ao servidor para que ele devolva a mesma solicitação (incluindo todos os cabeçalhos HTTP e corpo da mensagem) na resposta.
Este método é usado principalmente para fins de depuração e teste da configuração do servidor, pois permite que o cliente veja como o servidor está interpretando e respondendo à solicitação. No entanto, ele também pode ser usado para fins maliciosos, como a exploração de vulnerabilidades de segurança no servidor.
Essa configuração já vem aplicada em /etc/apache2/conf-available/security.conf no Debian, portanto, se mudar em outro lugar pode nao surtir efeito, então mude nesse arquivo mesmo.
SSLOpenSSLConfCmdEssa opção serve para permitir a configuração de detalhes específicos do OpenSSL através de um arquivo de configuração separado.
SSLSessionTicketsEssa opção é usada para controlar o uso de "tickets de sessão SSL", que são tokens criptografados que permitem que as informações sobre uma sessão SSL sejam armazenadas entre as solicitações do cliente. Ao habilitar essa opção, você pode aumentar a eficiência das conexões SSL, pois as informações de sessão não precisam ser renegotiadas a cada solicitação.
SSLCompressionEssa opção é usada para controlar o uso de compressão de dados na camada SSL/TLS. A compressão pode ajudar a aumentar a eficiência das conexões, mas também pode representar uma ameaça à segurança, pois pode permitir ataques de vulnerabilidade como o CRIME. Portanto, é comum desabilitar a compressão SSL para evitar esse tipo de ameaça.
SSLUseStaplingEssa opção é usada para habilitar ou desabilitar o "stapling de certificado SSL". O stapling de certificado SSL é uma técnica que permite que um servidor web forneça informações sobre o status de validação de um certificado SSL durante a negociação da conexão SSL.
Quando o stapling de certificado SSL está habilitado, o servidor web solicita periodicamente o status de validação do certificado SSL com a autoridade de certificação (CA) e inclui esse status na resposta SSL ao cliente. Isso significa que o cliente não precisa fazer uma verificação adicional com a CA para verificar o status do certificado, o que pode aumentar a eficiência e a segurança das conexões SSL.
Header always set Strict-Transport-Security "max-age=63072000"Essa é uma instrução de cabeçalho HTTP que especifica a política de segurança de transporte rígido (HSTS, sigla em inglês de "Strict Transport Security").
Essa instrução especifica que o navegador deve armazenar a política HSTS por um período de 63072000 segundos, ou cerca de 2 anos. Isso significa que, uma vez que o navegador receba essa política, ele sempre se conectará ao site apenas por meio de uma conexão criptografada, independentemente das solicitações futuras do usuário.
HSTS é uma técnica de segurança da web que força os navegadores a se conectarem a um site apenas por meio de uma conexão criptografada SSL/TLS. Quando um navegador recebe uma política HSTS, ele armazena essa informação e, em seguida, só envia solicitações para o site por meio de conexões criptografadas. Isso ajuda a proteger os usuários contra ataques de interceptação de conexão, como o ataque man-in-the-middle (MITM).

Para aplicar essas configurações podemos usar os sites cipherlist e ssl-config.mozilla. Podemos ainda usar um site do NIC.BR para testar a segurança dos nossos servidores, o nome do projeto é top.nic.br.


O OpenSSL é uma biblioteca de criptografia que fornece suporte a vários protocolos criptográficos, incluindo SSL (Secure Sockets Layer) e TLS (Transport Layer Security).


Outro ponto importante são as configuração sobre o Servidor Web que podem ser obtidas pelo navegador é com o uso da opção ServerTokens, vejamos um exemplo:

# Conseguimos ver o Servidor Web que está rodando e o Sistema Operacional:
$ curl --head http://192.168.121.209
HTTP/1.1 200 OK
Date: Mon, 13 Feb 2023 14:47:47 GMT
Server: Apache/2.4.41 (Ubuntu)
Content-Type: text/html;charset=UTF-8

# Teste com HTTPS (pode usar o '-k' ao invés de '--insecure'):
$ curl --insecure --head https://192.168.121.209
HTTP/1.1 200 OK
Date: Mon, 13 Feb 2023 14:49:55 GMT
Server: Apache/2.4.41 (Ubuntu)
Content-Type: text/html;charset=UTF-8

## Após aplicar 'ServerTokens Prod' veja como fica a saída:
$ curl --head http://192.168.121.209
HTTP/1.1 200 OK
Date: Mon, 13 Feb 2023 15:55:18 GMT
Server: Apache
Content-Type: text/html;charset=UTF-8

Um método para testar o Trace pode ser visto abaixo:

# Com Trace habilitado:
$ curl -v -X TRACE http://192.168.121.209
* Trying 192.168.121.209:80...
* Connected to 192.168.121.209 (192.168.121.209) port 80 (#0)
> TRACE / HTTP/1.1
> Host: 192.168.121.209
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Mon, 13 Feb 2023 16:13:34 GMT
< Server: Apache
< Transfer-Encoding: chunked
< Content-Type: message/http
<
TRACE / HTTP/1.1
Host: 192.168.121.209
User-Agent: curl/7.81.0
Accept: */*

* Connection #0 to host 192.168.121.209 left intact


# Com o Trace desabilitado vemos '405 Method Not Allowed'
$ curl -v -X TRACE http://192.168.121.209
* Trying 192.168.121.209:80...
* Connected to 192.168.121.209 (192.168.121.209) port 80 (#0)
> TRACE / HTTP/1.1
> Host: 192.168.121.209
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 405 Method Not Allowed
< Date: Mon, 13 Feb 2023 16:11:38 GMT
< Server: Apache
< Allow:
< Content-Length: 287
< Content-Type: text/html; charset=iso-8859-1
<
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>405 Method Not Allowed</title>
</head><body>
<h1>Method Not Allowed</h1>
<p>The requested method TRACE is not allowed for this URL.</p>
<hr>
<address>Apache Server at 192.168.121.209 Port 80</address>
</body></html>
* Connection #0 to host 192.168.121.209 left intact


Hardening do Apache


Vamos ver como fazer Hardening do Apache e melhorar as configurações do SSL/TLS. Vamos começar baixando uma chave Diffie-Hellman para uso em negociações de chaves criptográficas. Vamos baixar a chave ffdhe4096, o ffdhe na nomenclatura significa Finite Field Diffie-Hellman Ephemeral, já o número 4096 refere-se ao tamanho do campo de números utilizado na geração da chave, que é de 4096 bits. Esse tipo de chave é usado para proteger a privacidade das informações transmitidas durante uma sessão de comunicação criptografada, garantindo que a chave de sessão é compartilhada de forma segura sem ser possível a interceptação da chave.


Essa e outras chaves são disponibilizadas no [GitHub](https://github.com/internetstandards) do *Internet Standards Platform*, para mais detalhes consulte o link.

Diffie-Hellman


Diffie-Hellman é um método de troca de chaves criptográficas que permite aos participantes gerar uma chave compartilhada secreta que pode ser usada para cifrar e decifrar mensagens transmitidas. Ele foi desenvolvido por Whitfield Diffie e Martin Hellman em 1976, hoje em dia é amplamente utilizado para criar conexões seguras na internet, como VPNs, HTTPS e outros protocolos de segurança de rede.


A ideia básica por trás do Diffie-Hellman é que os participantes podem compartilhar informações públicas através de uma canal inseguro sem expor suas chaves secretas. Cada participante gera sua própria chave pública a partir de informações conhecidas por ambos e usa essas chaves públicas para gerar uma chave secreta compartilhada. Esta chave secreta é então usada para proteger as informações transmitidas entre os participantes.


O Diffie-Hellman é uma forma segura e eficiente de criar chaves secretas compartilhadas e é amplamente utilizado na criptografia moderna.



Começando o Hardening


Vamos aplicar as configurações no Apache:

# Entre no diretório abaixo:
$ cd /etc/apache2/ssl

# Baixe o arquivo:
$ wget https://raw.githubusercontent.com/internetstandards/dhe_groups/master/ffdhe4096.pem

# Agora edite o arquivo abaixo:
$ sudo vim /etc/apache2/mods-enabled/ssl.conf

################################
# Começo - Adicione ao final ###
################################
SSLCompression off
SSLSessionTickets off
SSLOpenSSLConfCmd ECDHParameters Automatic
SSLOpenSSLConfCmd Curves X25519:secp521r1:secp384r1:prime256v1
# https://raw.githubusercontent.com/internetstandards/dhe_groups/master/ffdhe4096.pem
SSLOpenSSLConfCmd DHParameters "/etc/apache2/ssl/ffdhe4096.pem"
SSLUseStapling On
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
SSLStaplingCache shmcb:${APACHE_RUN_DIR}/ssl_stapling(32768)

Header always set Strict-Transport-Security "max-age=63072000"
#############################
# Fim - Adicione ao final ###
#############################

### Agora mude as opções abaixo para outros valores ###

# Mude o valor de 'SSLCipherSuite' para:
SSLCipherSuite EECDH+AESGCM:EDH+AESGCM

# Mude o valor de 'SSLHonorCipherOrder' para (descomente se necessário):
SSLHonorCipherOrder on

# Mude o valor de 'SSLProtocol' para:
SSLProtocol -all +TLSv1.3 +TLSv1.2

## Ative o módulo 'header':
$ sudo a2enmod headers

# Reinicie o Apache:
$ systemctl restart apache2


SNI - Server Name Indicator


O Server Name Indicator (SNI) é uma extensão para o protocolo de transporte seguro (TLS) que permite que servidores Web compartilhem um único endereço IP e identifiquem qual certificado digital usar para cada site hospedado nesse endereço IP. Isso é importante porque o TLS usa o certificado digital para criptografar o tráfego entre o navegador do usuário e o servidor Web.


Sem o SNI, cada site em um único endereço IP precisaria ter um endereço IP exclusivo e, portanto, um certificado digital exclusivo. Isso tornaria a administração de sites e servidores muito mais complexa e dispendiosa.


Ao usar o SNI, os servidores Web podem compartilhar facilmente um único endereço IP, economizando recursos e tornando a administração de sites muito mais fácil. Além disso, o SNI também permite aos administradores de segurança monitorar e controlar o tráfego de rede de maneira mais eficiente.


O SNI faz isso com o uso do VirtualHost por Nomes em acesso HTTPS (Usando a opção ServerName).



Comandos importantes


Baixar o certificado do servidor:

# Ver o certificado do Site:
$ openssl s_client -showcerts -connect test.com.ze:443 </dev/null

# Baixar o certificado do site:
$ openssl s_client -showcerts -connect test.com.ze:443 </dev/null 2>&- | openssl x509 -outform PEM > test.com.ze.pem

# Ver informações completas sobre o certificado:
$ openssl s_client -connect test.com.ze:443

# Testar senha (se não der erro, a senha está correta):
$ openssl rsa -noout -in ca.key

# Mostra o conteúdo do certificado:
$ openssl x509 -in test.com.ze.pem -text -noout

# Verifica a data de validade do certificado quando temos ele em formato de arquivo:
$ openssl x509 -enddate -noout -in test.com.ze.pem
notAfter=Feb 7 20:55:55 2024 GMT

# Verifica a data de validade do certificado direto do servidor:
$ openssl s_client -servername test.com.ze -connect test.com.ze:443 </dev/null 2>&- | openssl x509 -noout -dates
notBefore=Feb 7 20:55:55 2023 GMT
notAfter=Feb 7 20:55:55 2024 GMT

# Verificar outros dominios do qual um certificado atende:
$ openssl s_client -showcerts -servername ipv6.br -connect ipv6.br:443 </dev/null 2>&- | openssl x509 -noout -ext subjectAltName
X509v3 Subject Alternative Name:
DNS:curso.ipv6.br, DNS:ds.ipv6.br, DNS:ipv6.br, DNS:ipv6.nic.br, DNS:v4.ipv6.br, DNS:v6.ipv6.br, DNS:www.ipv6.br, DNS:www.ipv6.nic.br


Fontes importantes


https://www.ibm.com/docs/en/ibm-mq/9.0?topic=tls-overview-ssltls-handshake

https://ssl-config.mozilla.org/

https://cipherlist.eu/

https://cwiki.apache.org/confluence/display/httpd/NameBasedSSLVHostsWithSNI