Para executar os exemplos será necessário:
- Terminal shell
- dotnet sdk 6.0
- docker
- openssl cli
Abrir um terminal no diretório /src e seguir os próximos passos
Apontar o endereço test.localdev.me para 127.0.0.1 na sua máquina
Rodar gerar-certificados.sh para gerar os certificados e chaves no diretório /certs:
- server.crt
- server.key
- ca.crt
- client.crt
- client.key
./gerar-certificados.sh
Rodar docker-build.sh para gerar a imagem nginx:mtls que terá configurado o certificado do servidor:
- server.crt
- server.key
E também terá a autoridade confiável para certificados do cliente:
- ca.crt
Essas configurações estão no arquivo nginx-setup-mtls.conf
./docker-build.sh
Rodar docker-run-servidor.sh para iniciar o servidor nginx expondo a porta 443
./docker-run-servidor.sh
Rodar run-cliente-curl.sh para realizar uma chamada curl informando o client.crt e client.key
./run-cliente-curl.sh
Rodar run-cliente-dotnet.sh para realizar uma chamada utilizando HttpClient e informando o client.crt e client.key
./run-cliente-dotnet.sh
-
Chamar o servidor e não informar certificado de cliente: "400 No required SSL certificate was sent"
-
Chamar o servidor e informar certificado do cliente inválido: "400 The SSL certificate error"
-
Chamar o servidor e informar certificado do cliente assinado pela autoridade configurado no servidor: "mTLS fechado com sucesso!"
- TLS x mTLS
Algumas questões interessantes:
- O certificado do servidor não tem nenhuma relação com o certificado do cliente.
- O servidor aceita comunicação com o cliente se o certificado do cliente for assinado pela autoridade de certificados de cliente configurada no servidor.
- O servidor aceita qualquer certificado de cliente assinado pela autoridade configurada.
- O certificado do cliente provavelmente será assinado por uma autoridade interna da organização para que os certificados de cliente aceitos pelo servidor estejam sob controle.
- Para realizar uma chamada dotnet utilizando HttpClient, é necessário:
var certificado = X509Certificate2.CreateFromPemFile("client.crt", "client.key");
var handler = new HttpClientHandler();
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ClientCertificates.Add(certificado);
var client = new HttpClient(handler);
var resultado = await client.GetAsync("https://test.localdev.me/index.html");
O mTLS tem o fluxo normal do TLS somado a uma validação por parte do servidor do certificado informado pelo cliente através do ca root configurado no servidor, dessa forma o cliente também consegue provar ser quem ele deve ser para o servidor.