Certificados de servidor e de cliente
Agora que temos a nossa IntermediateCA configurada correctamente, podemos começar a utilizá-la para emitir certificados.
Notas prévias:
- Deve-se usar metade dos bits usados na CA
- O CN do servidor deve ser o FQDN
- Um certificado servidor precisa de ter o mesmo FQDN repetido na informação SAN
- O CN dos clientes pode ser qualquer coisa, não é importante.
- Devem ser assinados com a IntermediateCA
- Normalmente têm a duração de um ano (365) e o máximo, desde Julho de 2019, é 824 dias (+1)
- Comando OpenSSL para certificado servidor:
-extensions server_cert
- Comando OpenSSL para certificado cliente:
-extensions usr_cert
- Só é possível copiar a informação SAN do CSR para o certificado se for colocada a opção
copy_extensions = copy
ou= all
na secção[ca_default]
dointermediate/openssl.conf
; caso contrário, a informação SAN tem de ser reinserida quando se usa o comandox509
para assinar o CSR, de modo a que chegue ao certificado assinado. - Vamos utilizar 4 servidores:
- offline: tem a RootCA
- server: tem o CRLDistribution da RootCA, a IntermediateCA e os seus certificados, e o OCSP Responder da IntermediateCA
- www: vai ter um servidor HTML certificado pela IntermediateCA
- cliente: vai aceder ao site que está em www
Exemplo de certificado servidor: o servidor da PKI
Começar por criar uma chave; neste caso deve-se omitir o -aes256
ou a opção -passout
para não criar uma palavra-passe.
Se existir uma palavra-passe, será necessário introduzi-la sempre que o processo do webserver seja iniciado…
|
|
Generating RSA private key, 4096 bit long modulus (2 primes) ...............................................................................................................++++ ........................................................++++ e is 65537 (0x010001)
|
|
Criar informação SAN
É especialmente útil quando o FQDN é fictício (por exemplo, não há DNS e precisamos de certificar o IP), mas tornou-se obrigatório porque agora os certificados de Web Server têm de ter o FQDN numa entrada SAN, e tê-lo só no CN já não é suficiente…
Para o fazer, temos de criar um ficheiro .CNF extra, contendo apenas essa informação (que será diferente para cada servidor)
|
|
[req]
distinguished_name = req_distinguished_name
req_extensions = req_ext
prompt = no
[req_distinguished_name]
C = PT
ST = Lisboa
L = Lisboa
O = Tiago Joao Silva
OU = TJS
CN = server.tjs.lan
[req_ext]
subjectAltName = @alt_names
[alt_names]
IP.1 = 192.168.1.70
DNS.1 = server.tjs.lan
DNS.2 = dns.tjs.lan
DNS.3 = chat.tjs.lan
DNS.4 = mail.tjs.lan
Criar o CSR
|
|
Confirmar que o CSR tem a informação SAN:
|
|
X509v3 Subject Alternative Name: IP Address:192.168.1.70, DNS:server.tjs.lan, DNS:dns.tjs.lan, DNS:chat.tjs.lan, DNS:mail.tjs.lan
Assinar o CSR
Caso não exista copy\_extensions = copy
ou = all
no inter-ca/openssl.cnf
, será preciso reinserir a informação SAN com as opções -extensions req_ext
e -extfile aaa-san.cnf
|
|
Caso exista copy\_extensions = copy
ou = all
no inter-ca/openssl.cnf
, é mais simples:
|
|
Using configuration from /root/ca/inter-ca/openssl.cnf Check that the request matches the signature Signature ok Certificate Details: Serial Number: 4100 (0x1004) Validity Not Before: Aug 22 23:54:31 2021 GMT Not After : Nov 23 23:54:31 2023 GMT Subject: countryName = PT stateOrProvinceName = Lisboa localityName = Lisboa organizationName = Tiago Joao Silva organizationalUnitName = TJS commonName = server.tjs.lan X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Cert Type: SSL Server Netscape Comment: OpenSSL Generated Server Certificate X509v3 Subject Key Identifier: 94:00:E3:58:4F:BA:20:85:F7:9C:DC:47:3C:68:A1:46:8B:78:10:AF X509v3 Authority Key Identifier: keyid:E3:75:25:D7:74:08:0B:23:F0:AF:E4:EC:D0:D4:52:CB:5A:3A:10:2E DirName:/C=PT/ST=Lisboa/L=Lisboa/O=TiagoJoaoSilva/OU=TJS/CN=ca-tjs-1/emailAddress=bofh@tjs.lan serial:10:03 X509v3 Key Usage: critical Digital Signature, Key Encipherment X509v3 Extended Key Usage: TLS Web Server Authentication Authority Information Access: OCSP - URI:http://ocsp.tjs.lan:7888 Certificate is to be certified until Nov 23 23:54:31 2023 GMT (823 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
|
|
Verificar a ChainOfTrust com o certificado CA-CHAIN
|
|
/root/ca/inter-ca/certs/server.tjs.lan.cert.pem: OK
Criar um certificado Chain/Bundle para o servidor
Concatenamos o certificado do servidor com o certificado CA-CHAIN:
|
|
Testes da CA
Configurar um webserver
Precisamos de criar um certificado novo para o webserver. O IP será 192.168.1.77
e o hostname será www
|
|
[req]
distinguished_name = req_distinguished_name
req_extensions = req_ext
prompt = no
[req_distinguished_name]
C = PT
ST = Lisboa
L = Lisboa
O = Tiago Joao Silva
OU = TJS
CN = www.tjs.lan
[req_ext]
subjectAltName = @alt_names
[alt_names]
IP.1 = 192.168.1.77
DNS.1 = www.tjs.lan
|
|
Para testar, instalamos um novo sistema Debian 11 sem GUI.
Editamos a configuração da interface desejada (enp0s3
é a interface primária no VirtualBox; no VMware é ens33
)
|
|
iface enp0s3 inet static
address 192.168.1.77/24
gateway 192.168.1.1
|
|
Editar o ficheiro /etc/hosts
; na segunda linha, mudar para:
127.0.1.1 www.tjs.lan www
Verificar:
|
|
www tjs.lan www.tjs.lan
Instalamos o servidor Nginx
|
|
Verificamos se serve a página definida por defeito
|
|
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br>/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
Trazer o certificado CHAIN do servidor para o webserver e colocá-lo num caminho que não seja afectado por updates nos certificados, como uma pasta local-certs
em /etc/ssl/
|
|
Trazer também a chave privada associada ao certificado do webserver e colocá-la em /etc/ssl/private/
|
|
Mudamos a configuração do Nginx para redirecionar automaticamente pedidos feitos à porta 80 (HTTP) para a porta 443 (HTTPS), e configuramos o certificado e a chave do webserver
|
|
A partir da linha 21:
|
|
Note-se que não se fechou a chaveta do site SSL, porque a configuração default continua por mais umas linhas e fecha mais abaixo.
|
|
--2021-08-24 21:45:45-- http://localhost/ Resolving localhost (localhost)... ::1, 127.0.0.1 Connecting to localhost (localhost)|::1|:80... connected. HTTP request sent, awaiting response... 301 Moved Permanently Location: https://www.tjs.lan/ [following] --2021-08-24 21:45:45-- https://www.tjs.lan/ Resolving www.tjs.lan (www.tjs.lan)... 127.0.1.1 Connecting to www.tjs.lan (www.tjs.lan)|127.0.1.1|:443... connected. ERROR: The certificate of ‘www.tjs.lan’ is not trusted. ERROR: The certificate of ‘www.tjs.lan’ doesn't have a known issuer.
wget
local a www.tjs.lan
não confia no certificado do servidor porque não conhece o certificado da RootCA.
Abrimos as portas 80 e 443 da firewall
|
|
Testar o webserver
Configuramos um cliente gráfico (por exemplo, um Debian 11 com MATE).
Resolução de nomes
Como não temos um servidor DNS com a zona tjs.lan nem com todos estes sistemas configurados, vamos adicionar o seguinte ao /etc/hosts
dos três sistemas (server, www e cliente)
# printf "\
#tjs.lan\n\
192.168.1.70 server.tjs.lan server\n\
192.168.1.70 ocsp.tjs.lan ocsp\n\
192.168.1.77 www.tjs.lan www \n" \
>> /etc/hosts
Instalar o certificado Root no cliente final
Importamos o certificado da RootCA para a home do utilizador actual do cliente.
Abrimos o Firefox, Preferences, Privacy and Security, View Certificates…
Ou (about:preferences#privacy)
Import…
Escolhemos o certificado da RootCA, Open
✓ Trust this CA to identify websites
✓ Trust this CA to identify email users (opcional)
OK
Clicando em View, podemos ver detalhes do certificado
Temos a Authority importada, OK
Testar o site
Abrimos http://www.tjs.lan
(pode ser necessário dizer ao Firefox que queremos mesmo ir para esse endereço), e temos uma ligação SSL protegida com o nosso certificado:
Configurar OCSP Stapling
Fonte: https://www.digitalocean.com/community/tutorials/how-to-configure-ocsp-stapling-on-apache-and-nginx
Trazemos para o webserver o certificado da RootCA
|
|
Adicionamos as linhas seguintes ao site activo no Nginx (estávamos a usar /etc/nginx/sites-available/default
), por baixo de ssl_certificate_key
:
|
|
Testar
A partir do cliente, testar o processo de OCSP Stapling com o comando seguinte, não esquecendo de indicar o certificado da CA (que deixámos na homefolder do utilizador quando o importamos para dentro do Firefox); se o apagou, é necessário trazê-lo de novo para o cliente para que possa ser usado agora:
|
|
Revogação com OSCP Responder
O Stapling costuma ter uma validade de 7 dias, em que o server guarda a resposta e já não contacta de novo o OCSP para obter a confirmação da validade do certificado, enviando directamente a resposta anterior ao cliente.
Isto significa que se revogarmos o certificado agora, só daqui a 7 dias é que o cliente recusará o certificado do webserver.
A não ser, claro, que o webserver seja reiniciado para perder a memória da resposta OCSP…
Vamos revogar o certificado do webserver:
|
|
Using configuration from /root/ca/inter-ca/openssl.cnf Revoking Certificate 1007. Data Base Updated
Reiniciamos o serviço do ocsp, para que este fique actualizado com o novo CRL
|
|
Reiniciamos o serviço do nginx em www, para perder a cache do OCSP Stapling
|
|
|
|
CONNECTED(00000003) depth=2 C = PT, ST = Lisboa, L = Lisboa, O = TiagoJoaoSilva, OU = TJS, CN = ca-tjs-1, emailAddress = bofh@tjs.lan verify return:1 depth=1 C = PT, ST = Lisboa, O = TiagoJoaoSilva, OU = TJS, CN = inter-ca-tjs-2, emailAddress = bofh@tjs.lan verify return:1 depth=0 C = PT, ST = Lisboa, L = Lisboa, O = Tiago Joao Silva, OU = TJS, CN = www.tjs.lan verify return:1 OCSP response: no response sent
Confirmar que os clientes vêem o certificado como revogado
E quando tentamos aceder a www.tjs.lan
pelo Firefox, somos informados que o certificado foi revogado:
Criar um novo certificado para substituir o revogado
Caso esteja a seguir o tutorial por ordem, é melhor emitir um certificado novo para www.tjs.lan
antes de prosseguir.
www
mudou, o seu CSR continua válido, e por isso só é necessário repetir os passos da assinatura do CSR em diante. Caso a chave privada tivesse sido comprometida, seria necessário emitir um novo certificado para www
a partir do zero.
Depois é preciso fazê-lo chegar ao local adequado em www.tjs.lan
, reiniciar o nginx, e testar de novo o acesso ao webserver no cliente:
Revogar a IntermediateCA
Para revogarmos a IntermediateCA (vamos supor que alguém deixou a chave privada da IntermediateCA num repositório público do GitHub), temos de nos deslocar à RootCA, que está offline, e seguir os passos descritos na secção correspondente:
|
|
Using configuration from /root/ca/openssl.cnf Revoking Certificate 1003. Data Base Updated
A seguir actualizamos o CRL e convertêmo-lo para DER, seguindo os passos da secção correspondente:
|
|
Podemos ver que o CRL alterado tem uma entrada nova:
|
|
Certificate Revocation List (CRL): Version 2 (0x1) Signature Algorithm: sha512WithRSAEncryption Issuer: C = PT, ST = Lisboa, L = Lisboa, O = TiagoJoaoSilva, OU = TJS, CN = ca-tjs-1, emailAddress = bofh@tjs.lan Last Update: Aug 25 20:50:52 2021 GMT Next Update: Sep 14 20:50:52 2022 GMT CRL extensions: X509v3 Authority Key Identifier: keyid:01:F2:CC:54:E0:F2:58:AC:E2:14:8E:2B:DB:6D:B6:FF:5C:25:41:A0 X509v3 CRL Number: 4098 Revoked Certificates: Serial Number: 1001 Revocation Date: Aug 13 22:11:25 2021 GMT CRL entry extensions: X509v3 CRL Reason Code: Unspecified Serial Number: 1002 Revocation Date: Aug 13 23:41:51 2021 GMT CRL entry extensions: X509v3 CRL Reason Code: Superseded Serial Number: 1003 Revocation Date: Aug 25 20:45:54 2021 GMT CRL entry extensions: X509v3 CRL Reason Code: Key Compromise
Trazer o CRL actualizado do offline para online
Usando um meio seguro que não quebre o airgapping do sistema da RootCA, levamos este ficheiro DER ao servidor que aloja a distribuição do CRL da RootCA:
|
|
Para eliminar a cache do OCSP Stapling, também é necessário reiniciar o webserver se queremos que a revogação seja imediatamente reconhecida em vez de esperarmos 7 dias:
|
|
Testar a revogação da IntermediateCA
Em browsers modernos (falha)
O site continua a ser reconhecido como seguro no Firefox, porque aparentemente os browsers não se dão ao trabalho de verificar a cadeia inteira de certificados (nem mesmo por OCSP), confiando apenas na lista interna de RootCAs e em CRLs internos distribuídos com as actualizações.
A única excepção é o velhinho Internet Explorer, paz à sua alma, que vamos testar já a seguir.
https://news.netcraft.com/archives/2013/05/13/how-certificate-revocation-doesnt-work-in-practice.html
E não consigo encontrar um comando openssl verify
que me consiga indicar que a cadeia do certificado www.tjs.lan.cert_chain.pem
está quebrada pela revogação da IntermediateCA
(https://stackoverflow.com/questions/25482199/verify-a-certificate-chain-using-openssl-verify)
O uso de PKI em browsers parece que utiliza muitos atalhos…
Em Internet Explorer
Para testar com Internet Explorer, precisamos de um cliente Windows, por isso provisionei uma VM Windows 7.
Importar o certificado da RootCA
Trazer o certificado da RootCA para o cliente Windows e salvar como ca.cert.cer
)
Win+R, certmgr.msc
Seleccionar Trusted Root Certification Authorities/Certificates
All Tasks > Import…
Escolher o certificado (Browse…)
Confirmar que queremos instalar em Trusted Root
Yes
E está instalado
Ficheiro hosts
Agora precisamos de colocar a mesma informação no ficheiro hosts
para resolver a falta de DNS.
Abrir o Notepad com permissões de administrador (clique direito em cima do Notepad, Run as administrator)
Abrir o ficheiro %SystemRoot%\System32\drivers\etc\hosts
Colar:
#tjs.lan
192.168.1.70 server.tjs.lan server
192.168.1.70 ocsp.tjs.lan ocsp
192.168.1.77 www.tjs.lan www
Salvar o ficheiro e sair do Notepad.
Abrir o site no IE
Agora podemos testar se o IE reconhece que a Inter-CA que assinou o certificado do nosso site foi revogada:
E o resultado é sim, o Internet Explorer consulta e respeita uma PKI interna a uma empresa, em vez de se limitar àquilo que já sabe sobre a PKI pública utilizada na Internet.