Nesta série de blogs, forneceremos um passo a passo completo sobre como configurar um servidor MariaDB totalmente criptografado para criptografia em repouso e em trânsito, para garantir a máxima proteção dos dados de serem roubado fisicamente ou durante a transferência e comunicação com outros hosts. A ideia básica é transformar nossa implantação "simples" em uma replicação MariaDB totalmente criptografada, conforme simplificado no diagrama a seguir:
Vamos configurar vários componentes de criptografia:
- Criptografia em trânsito, que consiste em:
- Criptografia cliente-servidor
- Criptografia de replicação
- Criptografia em repouso, que consiste em:
- Criptografia de arquivos de dados
- Criptografia de log binário/relay.
Observe que esta postagem do blog abrange apenas a criptografia em trânsito. Abordaremos a criptografia em repouso na segunda parte desta série de blogs.
Este passo a passo de implantação assumiu que já temos um servidor de replicação MariaDB em execução. Se você não tiver um, poderá usar o ClusterControl para implantar uma nova replicação MariaDB em minutos, com menos de 5 cliques. Todos os servidores estão rodando no MariaDB 10.4.11 no sistema CentOS 7.
Criptografia em trânsito
Os dados podem ser expostos a riscos tanto em trânsito quanto em repouso e requerem proteção em ambos os estados. A criptografia em trânsito protege seus dados se as comunicações forem interceptadas enquanto os dados se movem entre hosts pela rede, seja do seu site e do provedor de nuvem, entre serviços ou entre clientes e o servidor.
Para MySQL/MariaDB, os dados estão em movimento quando um cliente se conecta a um servidor de banco de dados ou quando um nó escravo replica dados de um nó mestre. MariaDB suporta conexões criptografadas entre clientes e o servidor usando o protocolo TLS (Transport Layer Security). O TLS às vezes é chamado de SSL (Secure Sockets Layer), mas o MariaDB não usa o protocolo SSL para conexões criptografadas porque sua criptografia é fraca. Mais detalhes sobre isso na página de documentação do MariaDB.
Criptografia cliente-servidor
Nesta configuração, usaremos certificados autoassinados, o que significa que não usamos terceiros como Google, Comodo ou qualquer provedor de Autoridade de certificação popular para verificar nossa identidade. Em SSL/TLS, a verificação de identidade é o primeiro passo que deve ser passado antes que o servidor e o cliente troquem seus certificados e chaves.
O MySQL fornece uma ferramenta muito útil chamada mysql_ssl_rsa_setup que cuida da geração de chaves e certificados automaticamente. Infelizmente, ainda não existe essa ferramenta para o servidor MariaDB. Portanto, temos que preparar e gerar manualmente os arquivos relacionados ao SSL para nossas necessidades de TLS do MariaDB.
A seguir está uma lista dos arquivos que vamos gerar usando a ferramenta OpenSSL:
- Chave de CA - Chave privada RSA em formato PEM. Deve ser mantido em segredo.
- Certificado de CA - Certificado X.509 em formato PEM. Contém metadados de chave pública e certificado.
- CSR do servidor - Solicitação de assinatura de certificado. O Nome Comum (CN) ao preencher o formulário é importante, por exemplo CN=mariadb-server
- Chave do servidor - Chave privada RSA. Deve ser mantido em segredo.
- Certificado do servidor - Certificado X.509 assinado por chave CA. Contém metadados de chave pública e certificado.
- CSR do cliente - Solicitação de assinatura de certificado. Deve usar um nome comum (CN) diferente do CSR do servidor, por exemplo, CN=client1
- Chave do cliente - Chave privada RSA. Deve ser mantido em segredo.
- Certificado de cliente - Certificado X.509 assinado por chave CA. Contém metadados de chave pública e certificado.
Em primeiro lugar, crie um diretório para armazenar nossos certificados e chaves para criptografia em trânsito:
$ mkdir -p /etc/mysql/transit/
$ cd /etc/mysql/transit/
Só para lhe dar uma idéia porque nomeamos o diretório como mencionado é porque na próxima parte desta série de blogs, vamos criar outro diretório para criptografia em repouso em /etc/mysql/rest.
Autoridade de certificação
Gere um arquivo de chave para nossa própria Autoridade de Certificação (CA):
$ openssl genrsa 2048 > ca-key.pem
Generating RSA private key, 2048 bit long modulus
.......................+++
...............................................................................................................................................................................................................................................+++
e is 65537 (0x10001)
Gere um certificado para nossa própria Autoridade de Certificação (CA) com base no ca-key.pem gerado anteriormente com expiração de 3650 dias:
$ openssl req -new -x509 -nodes -days 3650 -key ca-key.pem -out ca.pem
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:SE
State or Province Name (full name) []:Stockholm
Locality Name (eg, city) [Default City]:Stockholm
Organization Name (eg, company) [Default Company Ltd]:Severalnines
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:CA
Email Address []:[email protected]
Agora devemos ter ca-key.pem e ca.pem sob este diretório de trabalho.
Chave e certificado para servidor
Em seguida, gere a chave privada para o servidor MariaDB:
$ openssl genrsa 2048 > server-key.pem
Generating RSA private key, 2048 bit long modulus
.............................................................................................................+++
..................................................................................................................+++
e is 65537 (0x10001)
Um certificado confiável deve ser um certificado assinado por uma Autoridade de Certificação, onde aqui, usaremos nossa própria CA porque confiamos nos hosts da rede. Antes de podermos criar um certificado assinado, precisamos gerar um certificado de solicitação chamado Certificate Signing Request (CSR).
Crie um CSR para o servidor MariaDB. Vamos chamar o certificado como server-req.pem. Este não é o certificado que vamos usar para o servidor MariaDB. O certificado final é aquele que será assinado por nossa própria chave privada da CA (conforme mostrado na próxima etapa):
$ openssl req -new -key server-key.pem -out server-req.pem
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:SE
State or Province Name (full name) []:Stockholm
Locality Name (eg, city) [Default City]:Stockholm
Organization Name (eg, company) [Default Company Ltd]:Severalnines
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:MariaDBServer
Email Address []:[email protected]
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Anote o nome comum onde especificamos "MariaDBServer". Pode ser qualquer nome, mas o valor não deve ser o mesmo do certificado do cliente. Normalmente, se os aplicativos se conectam ao servidor MariaDB via FQDN ou nome de host (skip-name-resolve=OFF), você provavelmente deseja especificar o FQDN do servidor MariaDB como o nome comum.
Podemos então gerar o certificado X.509 final (server-cert.pem) e assinar o CSR (server-req.pem) com o certificado da CA (ca.pem) e a chave privada da CA (ca -key.pem):
$ openssl x509 -req -in server-req.pem -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -days 3650 -sha256
Signature ok
subject=/C=SE/ST=Stockholm/L=Stockholm/O=Severalnines/CN=MariaDBServer/[email protected]
Getting CA Private Key
Neste ponto, isso é o que temos agora:
$ ls -1 /etc/mysql/transite
ca-key.pem
ca.pem
server-cert.pem
server-key.pem
server-req.pem
Precisamos apenas do certificado CA (ca.pem), do certificado assinado do servidor (server-cert.pem) e da chave privada do servidor (server-key.pem) para o servidor MariaDB. O CSR (server-req.pem) não é mais necessário.
Chave e Certificado para o Cliente
Em seguida, precisamos gerar arquivos de chave e certificado para o cliente MariaDB. O servidor MariaDB só aceitará conexão remota do cliente que possui esses arquivos de certificado.
Comece gerando uma chave de 2048 bits para o cliente:
$ openssl genrsa 2048 > client-key.pem
Generating RSA private key, 2048 bit long modulus
.............................................................................................................+++
..................................................................................................................+++
e is 65537 (0x10001)
Crie CSR para o cliente chamado client-req.pem:
$ openssl req -new -key client-key.pem -out client-req.pem
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:SE
State or Province Name (full name) []:Stockholm
Locality Name (eg, city) [Default City]:Stockholm
Organization Name (eg, company) [Default Company Ltd]:Severalnines
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:Client1
Email Address []:[email protected]
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Preste atenção ao nome comum onde especificamos "Client1". Especifique qualquer nome que represente o cliente. Este valor deve ser diferente do Nome Comum do servidor. Para uso avançado, você pode usar este nome comum para permitir que determinado usuário com certificado corresponda a esse valor, por exemplo:
MariaDB> GRANT SELECT ON schema1.* TO 'client1'@'192.168.0.93' IDENTIFIED BY 's' REQUIRE SUBJECT '/CN=Client2';
Podemos então gerar o certificado X.509 final (client-cert.pem) e assinar o CSR (client-req.pem) com o certificado da CA (ca.pem) e a chave privada da CA (ca -key.pem):
$ openssl x509 -req -in client-req.pem -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem -days 3650 -sha256
Signature ok
subject=/C=SE/ST=Stockholm/L=Stockholm/O=Severalnines/CN=Client1/[email protected]
Getting CA Private Key
Todos os certificados necessários para a configuração da criptografia em trânsito são gerados. Verifique se ambos os certificados estão assinados corretamente pela CA:
$ openssl verify -CAfile ca.pem server-cert.pem client-cert.pem
server-cert.pem: OK
client-cert.pem: OK
Configurando SSL para MariaDB
Crie um novo diretório em cada escravo:
(slave1)$ mkdir -p /etc/mysql/transit/
(slave2)$ mkdir -p /etc/mysql/transit/
Copie os arquivos de criptografia para todos os escravos:
$ scp -r /etc/mysql/transit/* [email protected]:/etc/mysql/transit/
$ scp -r /etc/mysql/transit/* [email protected]:/etc/mysql/transit/
Certifique-se de que o proprietário do diretório certs seja o usuário "mysql" e altere as permissões de todos os arquivos de chave para que não seja legível globalmente:
$ cd /etc/mysql/transit
$ chown -R mysql:mysql *
$ chmod 600 client-key.pem server-key.pem ca-key.pem
Aqui está o que você deve ver ao listar arquivos no diretório "transit":
$ ls -al /etc/mysql/transit
total 32
drwxr-xr-x. 2 root root 172 Dec 14 04:42 .
drwxr-xr-x. 3 root root 24 Dec 14 04:18 ..
-rw-------. 1 mysql mysql 1675 Dec 14 04:19 ca-key.pem
-rw-r--r--. 1 mysql mysql 1383 Dec 14 04:22 ca.pem
-rw-r--r--. 1 mysql mysql 1383 Dec 14 04:42 client-cert.pem
-rw-------. 1 mysql mysql 1675 Dec 14 04:42 client-key.pem
-rw-r--r--. 1 mysql mysql 1399 Dec 14 04:42 client-req.pem
-rw-r--r--. 1 mysql mysql 1391 Dec 14 04:34 server-cert.pem
-rw-------. 1 mysql mysql 1679 Dec 14 04:28 server-key.pem
-rw-r--r--. 1 mysql mysql 1415 Dec 14 04:31 server-req.pem
A seguir, habilitaremos a conexão SSL para MariaDB. Em cada host MariaDB (master e slaves) edite o arquivo de configuração e adicione as seguintes linhas na seção [mysqld]:
ssl-ca=/etc/mysql/transit/ca.pem
ssl-cert=/etc/mysql/transit/server-cert.pem
ssl-key=/etc/mysql/transit/server-key.pem
Reinicie o servidor MariaDB um nó por vez, começando nos escravos e finalmente no mestre:
(slave1)$ systemctl restart mariadb
(slave2)$ systemctl restart mariadb
(master)$ systemctl restart mariadb
Depois de reiniciado, o MariaDB agora é capaz de aceitar conexões simples conectando-se a ele sem nenhum parâmetro relacionado a SSL ou com conexões criptografadas, quando você especifica o parâmetro relacionado a SSL na string de conexão.
Para usuários do ClusterControl, você pode habilitar a criptografia cliente-servidor com apenas alguns cliques. Basta ir para ClusterControl -> Segurança -> Criptografia SSL -> Habilitar -> Criar Certificado -> Expiração do Certificado -> Habilitar SSL:
ClusterControl irá gerar as chaves necessárias, certificado X.509 e certificado CA e configure a criptografia SSL para conexões cliente-servidor para todos os nós no cluster. Para replicação MySQL/MariaDB, os arquivos SSL estarão localizados em /etc/ssl/replication/cluster_X, onde X é o ID do cluster em cada nó do banco de dados. Os mesmos certificados serão usados em todos os nós e os existentes poderão ser substituídos. Os nós devem ser reiniciados individualmente após a conclusão desse trabalho. Recomendamos que você reinicie primeiro um escravo de replicação e verifique se as configurações de SSL funcionam.
Para reiniciar cada nó, vá para ClusterControl -> Nodes -> Node Actions -> Restart Node. Reinicie um nó por vez, começando com os escravos. O último nó deve ser o nó mestre com o sinalizador de parada forçada habilitado:
Você pode saber se um nó é capaz de lidar com a criptografia cliente-servidor por olhando para o ícone de cadeado verde ao lado do nó do banco de dados na grade Visão geral:
Neste ponto, nosso cluster está pronto para aceitar conexão SSL do MySQL Comercial.
Conectando via conexão criptografada
O cliente MariaDB requer todos os arquivos SSL relacionados ao cliente que geramos dentro do servidor. Copie o certificado de cliente gerado, certificado de CA e chave de cliente para o host do cliente:
$ cd /etc/mysql/transit
$ scp client-cert.pem client-key.pem ca.pem [email protected]:~
**ClusterControl gera os arquivos SSL do cliente em /etc/ssl/replication/cluster_X/em cada nó do banco de dados, onde X é o ID do cluster.
Crie um usuário de banco de dados que exija SSL no mestre:
MariaDB> CREATE SCHEMA sbtest;
MariaDB> CREATE USER [email protected]'%' IDENTIFIED BY 'mysecr3t' REQUIRE SSL;
MariaDB> GRANT ALL PRIVILEGES ON sbtest.* to [email protected]'%';
No host do cliente, conecte-se ao servidor MariaDB com parâmetros relacionados ao SSL. Podemos verificar o status da conexão usando a instrução "STATUS":
(client)$ mysql -usbtest -p -h192.168.0.91 -P3306 --ssl-cert client-cert.pem --ssl-key client-key.pem --ssl-ca ca.pem -e 'status'
...
Current user: [email protected]
SSL: Cipher in use is DHE-RSA-AES256-GCM-SHA384
...
Preste atenção à linha SSL onde a cifra é usada para a criptografia. Isso significa que o cliente está conectado com sucesso ao servidor MariaDB via conexão criptografada.
Neste ponto, criptografamos a conexão cliente-servidor com o servidor MariaDB, conforme representado pela seta verde de duas pontas no diagrama a seguir:
Na próxima parte, vamos criptografar as conexões de replicação entre os nós.
Criptografia de replicação
Configurar conexões criptografadas para replicação é semelhante a fazer isso para conexões cliente/servidor. Podemos usar os mesmos certificados de cliente, chave e certificado de CA para permitir que o usuário de replicação acesse o servidor do mestre via canal de criptografia. Isso habilitará indiretamente a criptografia entre nós quando o thread de E/S escravo extrair eventos de replicação do mestre.
Vamos configurar isso em um escravo por vez. Para o primeiro slave, 192.168.0.92, adicione a seguinte linha na seção [client] dentro do arquivo de configuração do MariaDB:
[client]
ssl-ca=/etc/mysql/transit/ca.pem
ssl-cert=/etc/mysql/transit/client-cert.pem
ssl-key=/etc/mysql/transit/client-key.pem
Parar o thread de replicação no escravo:
(slave)MariaDB> STOP SLAVE;
No mestre, altere o usuário de replicação existente para forçá-lo a se conectar usando SSL:
(master)MariaDB> ALTER USER [email protected] REQUIRE SSL;
No escravo, teste a conectividade com o mestre, 192.168.0.91 via linha de comando mysql com --ssl sinalizador:
(slave)MariaDB> mysql -urpl_user -p -h192.168.0.91 -P 3306 --ssl -e 'status'
...
Current user: [email protected]
SSL: Cipher in use is DHE-RSA-AES256-GCM-SHA384
...
Certifique-se de que você pode se conectar ao host mestre sem erros. Em seguida, no escravo, especifique a instrução CHANGE MASTER com os parâmetros SSL conforme abaixo:
(slave)MariaDB> CHANGE MASTER TO MASTER_SSL = 1, MASTER_SSL_CA = '/etc/mysql/transit/ca.pem', MASTER_SSL_CERT = '/etc/mysql/transit/client-cert.pem', MASTER_SSL_KEY = '/etc/mysql/transit/client-key.pem';
Inicie o escravo de replicação:
(slave)MariaDB> START SLAVE;
Verifique se a replicação está funcionando corretamente com os parâmetros SSL relacionados:
MariaDB> SHOW SLAVE STATUS\G
...
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Master_SSL_Allowed: Yes
Master_SSL_CA_File: /etc/mysql/transit/ca.pem
Master_SSL_Cert: /etc/mysql/transit/client-cert.pem
Master_SSL_Key: /etc/mysql/transit/client-key.pem
...
O escravo agora está replicando do mestre com segurança por meio de criptografia TLS.
Repita todas as etapas acima no escravo restante, 192.168.0.93. A única diferença é a instrução alter user a ser executada no master onde temos que mudar para seu respectivo host:
(master)MariaDB> ALTER USER [email protected] REQUIRE SSL;
Neste ponto, concluímos a criptografia em trânsito, conforme ilustrado pelas linhas verdes do mestre para os escravos no diagrama a seguir:
Você pode verificar a conexão de criptografia observando a saída tcpdump para a interface eth1 no escravo. Veja a seguir um exemplo de replicação padrão sem criptografia:
(plain-slave)$ tcpdump -i eth1 -s 0 -l -w - 'src port 3306 or dst port 3306' | strings
tcpdump: listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
H"-'
binlog.000008Ulw
binlog.000008Ulw
sbtest
sbtest
create table t1 (id INT AUTO_INCREMENT PRIMARY KEY, data VARCHAR(255))
binlog.000008
sbtest
BEGIN3
sbtest
test data3
Ok*Z
binlog.000008*Z
^C11 packets captured
11 packets received by filter
0 packets dropped by kernel
Podemos ver claramente o texto como lido pelo escravo do mestre. Enquanto estiver em uma conexão criptografada, você deverá ver caracteres sem sentido como abaixo:
(encrypted-slave)$ tcpdump -i eth1 -s 0 -l -w - 'src port 3306 or dst port 3306' | strings
tcpdump: listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
:|f^yb#
O5~_
@#PFh
k)]O
jtk3c
@NjN9_a
!\[email protected]
NrF
?7&Y
^C6 packets captured
6 packets received by filter
0 packets dropped by kernel
Conclusão
Na próxima parte desta série de blogs, veremos como concluir nossa configuração totalmente criptografada com a criptografia em repouso MariaDB. Fique atento!