Hoje vamos explorar como implementar o mTLS (Mutual TLS), que é uma técnica de segurança para autenticação mútua entre cliente e servidor, em uma aplicação Go.
Mas antes de começar, vamos entender um pouco melhor o que é TLS (Transport Layer Security) e qual sua diferença com mTLS.
TLS vs mTLS
O TLS é usado para criptografar a comunicação entre cliente e servidor. Nele, comumente usado em conexões HTTPS, apenas o servidor se autentica perante o cliente, usando um certificado digital para garantir que o cliente está se comunicando com o servidor correto.
Já no mTLS, tanto o cliente quanto o servidor se autenticam mutuamente usando certificados. Isso significa que, além do servidor provar sua identidade ao cliente, o cliente também deve provar sua identidade ao servidor.
Assim, com o mTLS, adicionamos uma camada extra de segurança. Essa é uma prática comum em ambientes corporativos e aplicações que exigem alto nível de confiança e segurança nas comunicações.
Gerando certificado (CA)
O primeiro passo para implementar o mTLS é ter um certificado de segurança.
Os serviços mais conhecidos para se obter certificados para mTLS são:
- DigiCert: Oferece uma ampla gama de certificados SSL/TLS e é adequado para implementações de mTLS.
- GlobalSign: Além dos certificados padrão, possui opções específicas para empresas e pode ser usado para mTLS.
- Entrust Datacard: Conhecida por oferecer soluções seguras de certificados digitais, incluindo opções para mTLS.
mTLS no server
Na implementação do servidor, precisamos carregar tantos o certificado do servidor, quanto a CA para verificar o cliente.
package main
import (
"crypto/tls"
"log"
"net/http"
)
func main() {
// Carregar certificados do servidor e da CA
cer, err := tls.LoadX509KeyPair("servidor.crt", "servidor.key")
if err != nil {
log.Fatal(err)
}
// Configurar TLS
config := &tls.Config{
Certificates: []tls.Certificate{cer},
ClientAuth: tls.RequireAndVerifyClientCert,
// Certificado da CA para verificar o cliente
ClientCAs: loadCA("ca.crt"),
}
// Criar servidor com configuração TLS
server := &http.Server{
Addr: ":443",
TLSConfig: config,
}
log.Fatal(server.ListenAndServeTLS("", ""))
}
func loadCA(caFile string) *x509.CertPool {
caCert, err := ioutil.ReadFile(caFile)
if err != nil {
log.Fatal(err)
}
caPool := x509.NewCertPool()
caPool.AppendCertsFromPEM(caCert)
return caPool
}
No exemplo acima, note que não estamos utilizando a função ListenAndServeTLS do package net/http, mas sim o método ListenAndServeTLS da struct http.Server.
Outro ponto de atenção é que, nessa abordagem, caso estivéssemos utilizando o go-chi para lidar com as rotas, precisamos passá-lo diretamente à struct http.Server, mais especificamente no atributo Handler.
mTLS no client
No lado cliente da conexão, precisamos do certificado do cliente e da CA, para que o servidor consiga verificar a autenticidade do cliente.
package main
import (
"crypto/tls"
"crypto/x509"
"io/ioutil"
"log"
"net/http"
)
func main() {
// Carregar certificado do cliente e chave privada
cert, err := tls.LoadX509KeyPair("cliente.crt", "cliente.key")
if err != nil {
log.Fatal(err)
}
// Carregar CA
caCert, err := ioutil.ReadFile("ca.crt")
if err != nil {
log.Fatal(err)
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
// Configurar TLS
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{cert},
RootCAs: caCertPool,
}
tlsConfig.BuildNameToCertificate()
// Criar cliente HTTP com configuração TLS
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsConfig,
},
}
// Fazer requisição
resp, err := client.Get("<https://servidor.exemplo.com>")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
// Processar resposta...
}
Embora no exemplo eu tenha colocado tudo dentro da função main, idealmente, você pode criar um package que forneça o client já configurado. Assim, você conseguirá facilmente reutilizá-lo em qualquer parte da aplicação.
Agora que já temos a configuração do servidor e cliente, só falta testar a comunicação para garantir que a autenticação mútua está funcionando corretamente.
Conclusão
Implementar mTLS aumenta significativamente a segurança da comunicação entre seus serviços. É um processo mais complexo, mas essencial para ambientes que exigem alta segurança.
Espero que este guia ajude você a começar com mTLS em Go.
Até a próxima!
Faça parte da comunidade!
Receba os melhores conteúdos sobre Go, Kubernetes, arquitetura de software, Cloud e esteja sempre atualizado com as tendências e práticas do mercado.
Livros Recomendados
Abaixo listei alguns dos melhores livros que já li sobre GO.




