En esta serie de blogs, le brindaremos un recorrido completo sobre cómo configurar un servidor MariaDB completamente encriptado para encriptación en reposo y en tránsito, para garantizar la máxima protección de los datos de ser robado físicamente o mientras se transfiere y se comunica con otros hosts. La idea básica es que vamos a convertir nuestra implementación "sencilla" en una replicación de MariaDB totalmente cifrada, como se simplifica en el siguiente diagrama:
Vamos a configurar varios componentes de cifrado:
- Cifrado en tránsito, que consta de:
- Cifrado cliente-servidor
- Cifrado de replicación
- Cifrado en reposo, que consta de:
- Cifrado de archivos de datos
- Cifrado de registro binario/de retransmisión.
Tenga en cuenta que esta publicación de blog solo cubre el cifrado en tránsito. Vamos a cubrir el cifrado en reposo en la segunda parte de esta serie de blogs.
Este tutorial de implementación asumió que ya tenemos un servidor de replicación de MariaDB en ejecución. Si no tiene uno, puede usar ClusterControl para implementar una nueva replicación de MariaDB en minutos, con menos de 5 clics. Todos los servidores se ejecutan en MariaDB 10.4.11 en el sistema CentOS 7.
Cifrado en tránsito
Los datos pueden estar expuestos a riesgos tanto en tránsito como en reposo y requieren protección en ambos estados. El cifrado en tránsito protege sus datos si se interceptan las comunicaciones mientras los datos se mueven entre hosts a través de la red, ya sea desde su sitio y el proveedor de la nube, entre servicios o entre clientes y el servidor.
Para MySQL/MariaDB, los datos están en movimiento cuando un cliente se conecta a un servidor de base de datos o cuando un nodo esclavo replica datos desde un nodo maestro. MariaDB admite conexiones cifradas entre los clientes y el servidor utilizando el protocolo TLS (Seguridad de la capa de transporte). TLS a veces se denomina SSL (Secure Sockets Layer), pero MariaDB en realidad no usa el protocolo SSL para conexiones cifradas porque su cifrado es débil. Más detalles sobre esto en la página de documentación de MariaDB.
Cliente-Servidor Cifrado
En esta configuración vamos a utilizar certificados autofirmados, lo que significa que no utilizamos terceros como Google, Comodo o cualquier proveedor de autoridad certificadora popular para verificar nuestra identidad. En SSL/TLS, la verificación de identidad es el primer paso que debe realizarse antes de que el servidor y el cliente intercambien sus certificados y claves.
MySQL proporciona una herramienta muy útil llamada mysql_ssl_rsa_setup que se encarga de la generación de claves y certificados automáticamente. Desafortunadamente, todavía no existe tal herramienta para el servidor MariaDB. Por lo tanto, tenemos que preparar y generar manualmente los archivos relacionados con SSL para nuestras necesidades de MariaDB TLS.
La siguiente es una lista de los archivos que generaremos usando la herramienta OpenSSL:
- Clave CA - Clave privada RSA en formato PEM. Debe mantenerse en secreto.
- Certificado de CA - Certificado X.509 en formato PEM. Contiene clave pública y metadatos de certificados.
- Servidor CSR - Solicitud de firma de certificado. El nombre común (CN) al completar el formulario es importante, por ejemplo CN=mariadb-server
- Clave del servidor - Clave privada RSA. Debe mantenerse en secreto.
- Certificado de servidor - Certificado X.509 firmado por clave CA. Contiene clave pública y metadatos de certificados.
- RSC del cliente - Solicitud de firma de certificado. Debe usar un nombre común (CN) diferente al CSR del servidor, por ejemplo, CN=client1
- Clave de cliente - Clave privada RSA. Debe mantenerse en secreto.
- Certificado de cliente - Certificado X.509 firmado por clave CA. Contiene clave pública y metadatos de certificados.
En primer lugar, cree un directorio para almacenar nuestros certificados y claves para el cifrado en tránsito:
$ mkdir -p /etc/mysql/transit/
$ cd /etc/mysql/transit/
Solo para darle una idea de por qué nombramos el directorio como se mencionó porque en la siguiente parte de esta serie de blogs, crearemos otro directorio para el cifrado en reposo en /etc/mysql/rest.
Autoridad de certificación
Generar un archivo clave para nuestra propia Autoridad Certificadora (CA):
$ openssl genrsa 2048 > ca-key.pem
Generating RSA private key, 2048 bit long modulus
.......................+++
...............................................................................................................................................................................................................................................+++
e is 65537 (0x10001)
Generar un certificado para nuestra propia Autoridad de Certificación (CA) basado en el ca-key.pem generado antes con vencimiento de 3650 días:
$ 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]
Ahora deberíamos tener ca-key.pem y ca.pem en este directorio de trabajo.
Clave y Certificado para Servidor
A continuación, genere una clave privada para el servidor MariaDB:
$ openssl genrsa 2048 > server-key.pem
Generating RSA private key, 2048 bit long modulus
.............................................................................................................+++
..................................................................................................................+++
e is 65537 (0x10001)
Un certificado de confianza debe ser un certificado firmado por una autoridad de certificación, por lo que aquí vamos a utilizar nuestra propia CA porque confiamos en los hosts de la red. Antes de que podamos crear un certificado firmado, debemos generar un certificado de solicitud denominado Solicitud de firma de certificado (CSR).
Cree una CSR para el servidor MariaDB. Vamos a llamar al certificado como server-req.pem. Este no es el certificado que vamos a usar para el servidor MariaDB. El certificado final es el que será firmado por nuestra propia clave privada de CA (como se muestra en el siguiente paso):
$ 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 []:
Tome nota del Nombre común donde especificamos "MariaDBServer". Puede ser cualquier nombre, pero el valor no debe ser el mismo que el certificado del cliente. Por lo general, si las aplicaciones se conectan al servidor MariaDB a través de FQDN o nombre de host (skip-name-resolve=OFF), probablemente desee especificar el FQDN del servidor MariaDB como nombre común.
Podemos generar el certificado X.509 final (server-cert.pem) y firmar la CSR (server-req.pem) con el certificado de CA (ca.pem) y la clave privada de 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
En este punto, esto es lo que tenemos ahora:
$ ls -1 /etc/mysql/transite
ca-key.pem
ca.pem
server-cert.pem
server-key.pem
server-req.pem
Solo necesitamos el certificado CA (ca.pem), el certificado firmado del servidor (server-cert.pem) y la clave privada del servidor (server-key.pem) para el servidor MariaDB. El CSR (server-req.pem) ya no es necesario.
Clave y Certificado para el Cliente
A continuación, necesitamos generar archivos de claves y certificados para el cliente MariaDB. El servidor MariaDB solo aceptará la conexión remota del cliente que tiene estos archivos de certificado.
Comience generando una clave de 2048 bits para el cliente:
$ openssl genrsa 2048 > client-key.pem
Generating RSA private key, 2048 bit long modulus
.............................................................................................................+++
..................................................................................................................+++
e is 65537 (0x10001)
Cree CSR para el cliente llamado 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 atención al Nombre común donde especificamos "Cliente1". Especifique cualquier nombre que represente al cliente. Este valor debe ser diferente del nombre común del servidor. Para uso avanzado, puede usar este nombre común para permitir que ciertos usuarios con certificados coincidan con este valor, por ejemplo:
MariaDB> GRANT SELECT ON schema1.* TO 'client1'@'192.168.0.93' IDENTIFIED BY 's' REQUIRE SUBJECT '/CN=Client2';
Podemos generar el certificado X.509 final (client-cert.pem) y firmar la CSR (client-req.pem) con el certificado de CA (ca.pem) y la clave privada de 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
Se generan todos los certificados que necesitamos para la configuración del cifrado en tránsito. Verifique que ambos certificados estén correctamente firmados por la CA:
$ openssl verify -CAfile ca.pem server-cert.pem client-cert.pem
server-cert.pem: OK
client-cert.pem: OK
Configuración de SSL para MariaDB
Cree un nuevo directorio en cada esclavo:
(slave1)$ mkdir -p /etc/mysql/transit/
(slave2)$ mkdir -p /etc/mysql/transit/
Copie los archivos de cifrado a todos los esclavos:
$ scp -r /etc/mysql/transit/* [email protected]:/etc/mysql/transit/
$ scp -r /etc/mysql/transit/* [email protected]:/etc/mysql/transit/
Asegúrese del propietario del directorio de certificados para el usuario "mysql" y cambie los permisos de todos los archivos clave para que no se pueda leer globalmente:
$ cd /etc/mysql/transit
$ chown -R mysql:mysql *
$ chmod 600 client-key.pem server-key.pem ca-key.pem
Esto es lo que debería ver al listar archivos en el directorio "tránsito":
$ 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 continuación, habilitaremos la conexión SSL para MariaDB. En cada host MariaDB (maestro y esclavos), edite el archivo de configuración y agregue las siguientes líneas en la sección [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 el servidor MariaDB un nodo a la vez, comenzando desde los esclavos y finalmente en el maestro:
(slave1)$ systemctl restart mariadb
(slave2)$ systemctl restart mariadb
(master)$ systemctl restart mariadb
Después de reiniciar, MariaDB ahora es capaz de aceptar conexiones simples conectándose sin ningún parámetro relacionado con SSL o con conexiones cifradas, cuando especifica un parámetro relacionado con SSL en la cadena de conexión.
Para los usuarios de ClusterControl, puede habilitar el cifrado cliente-servidor con solo unos clics. Simplemente vaya a ClusterControl -> Seguridad -> Cifrado SSL -> Habilitar -> Crear certificado -> Caducidad del certificado -> Habilitar SSL:
ClusterControl generará las claves requeridas, el certificado X.509 y el certificado CA y configure el cifrado SSL para las conexiones cliente-servidor para todos los nodos del clúster. Para la replicación MySQL/MariaDB, los archivos SSL se ubicarán en /etc/ssl/replication/cluster_X, donde X es la ID del clúster en cada nodo de la base de datos. Se utilizarán los mismos certificados en todos los nodos y es posible que se sobrescriban los existentes. Los nodos deben reiniciarse individualmente después de que se complete este trabajo. Le recomendamos que primero reinicie un esclavo de replicación y verifique que la configuración de SSL funcione.
Para reiniciar cada nodo, vaya a ClusterControl -> Nodos -> Acciones de nodo -> Reiniciar nodo. Reinicie un nodo a la vez, comenzando con los esclavos. El último nodo debe ser el nodo maestro con el indicador de detención forzada activado:
Puede saber si un nodo puede manejar el cifrado cliente-servidor mirando el ícono de candado verde justo al lado del nodo de la base de datos en la cuadrícula de Descripción general:
En este punto, nuestro clúster ya está listo para aceptar la conexión SSL de MySQL usuarios.
Conexión a través de una conexión encriptada
El cliente MariaDB requiere todos los archivos SSL relacionados con el cliente que hemos generado dentro del servidor. Copie el certificado de cliente, el certificado de CA y la clave de cliente generados en el host del cliente:
$ cd /etc/mysql/transit
$ scp client-cert.pem client-key.pem ca.pem [email protected]:~
**ClusterControl genera los archivos SSL del cliente en /etc/ssl/replication/cluster_X/en cada nodo de la base de datos, donde X es el ID del clúster.
Cree un usuario de base de datos que requiera SSL en el maestro:
MariaDB> CREATE SCHEMA sbtest;
MariaDB> CREATE USER [email protected]'%' IDENTIFIED BY 'mysecr3t' REQUIRE SSL;
MariaDB> GRANT ALL PRIVILEGES ON sbtest.* to [email protected]'%';
Desde el host del cliente, conéctese al servidor MariaDB con parámetros relacionados con SSL. Podemos verificar el estado de la conexión usando la declaración "ESTADO":
(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 atención a la línea SSL donde se usa el cifrado para el cifrado. Esto significa que el cliente se ha conectado correctamente al servidor MariaDB a través de una conexión cifrada.
En este punto, hemos encriptado la conexión cliente-servidor al servidor MariaDB, como lo representa la flecha verde de dos puntas en el siguiente diagrama:
En la siguiente parte, cifraremos las conexiones de replicación entre nodos.
Cifrado de replicación
La configuración de conexiones cifradas para la replicación es similar a hacerlo para las conexiones cliente/servidor. Podemos usar los mismos certificados de cliente, clave y certificado de CA para permitir que el usuario de replicación acceda al servidor del maestro a través del canal de cifrado. Esto habilitará indirectamente el cifrado entre nodos cuando el subproceso de E/S esclavo extraiga eventos de replicación del maestro.
Configuremos esto en un esclavo a la vez. Para el primer esclavo, 192.168.0.92, agregue la siguiente línea en la sección [cliente] dentro del archivo de configuración de 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
Detener el subproceso de replicación en el esclavo:
(slave)MariaDB> STOP SLAVE;
En el maestro, modifique el usuario de replicación existente para obligarlo a conectarse mediante SSL:
(master)MariaDB> ALTER USER [email protected] REQUIRE SSL;
En el esclavo, pruebe la conectividad con el maestro, 192.168.0.91 a través de la línea de comando mysql con el indicador --ssl:
(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
...
Asegúrese de que puede conectarse al host maestro sin errores. Luego, en el esclavo, especifique la declaración CHANGE MASTER con los parámetros SSL como se muestra a continuación:
(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';
Iniciar el esclavo de replicación:
(slave)MariaDB> START SLAVE;
Verifique que la replicación funcione bien con los 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
...
El esclavo ahora se replica desde el maestro de forma segura a través del cifrado TLS.
Repita todos los pasos anteriores en el esclavo restante, 192.168.0.93. La única diferencia es la declaración de cambio de usuario que se ejecutará en el maestro donde tenemos que cambiar a su respectivo host:
(master)MariaDB> ALTER USER [email protected] REQUIRE SSL;
En este punto, hemos completado el cifrado en tránsito, como lo ilustran las líneas verdes del maestro al esclavo en el siguiente diagrama:
Puede verificar la conexión de cifrado mirando la salida tcpdump para la interfaz eth1 sobre el esclavo. El siguiente es un ejemplo de replicación estándar sin cifrado:
(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 el texto tal como lo lee el esclavo del maestro. Mientras esté en una conexión encriptada, debería ver caracteres incomprensibles como los siguientes:
(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
Conclusión
En la siguiente parte de esta serie de blogs, analizaremos cómo completar nuestra configuración totalmente cifrada con el cifrado en reposo de MariaDB. ¡Estén atentos!