El cifrado es una de las características de seguridad más importantes para mantener sus datos lo más seguros posible. Dependiendo de los datos que esté manejando, no siempre es obligatorio, pero al menos debería considerarlo como una mejora de seguridad en su organización de todos modos, y en realidad se recomienda para evitar el robo de datos o el acceso no autorizado.
En este blog, describiremos dos tipos básicos de cifrado y cómo configurarlo en un servidor MariaDB.
¿Qué es el cifrado de datos?
Hay dos tipos básicos de cifrado de datos:en reposo y en tránsito. Veamos qué significan.
Cifrado de datos en reposo
Los datos almacenados en un sistema se conocen como datos en reposo. El cifrado de estos datos consiste en utilizar un algoritmo para convertir texto o código en ilegible. Debe tener una clave de cifrado para decodificar los datos cifrados.
El cifrado de una base de datos completa debe realizarse con precaución, ya que puede tener un impacto grave en el rendimiento. Por lo tanto, es aconsejable cifrar solo campos o tablas individuales.
El cifrado de datos en reposo protege los datos del robo físico de los discos duros o del acceso no autorizado al almacenamiento de archivos. Este cifrado también cumple con las normas de seguridad de datos, especialmente si hay datos financieros o de salud almacenados en el sistema de archivos.
Cifrado de datos en tránsito
Los datos transferidos o que se mueven entre transacciones se conocen como datos en tránsito. Los datos que se mueven entre el servidor y el cliente mientras se navega por páginas web son un buen ejemplo de este tipo de datos.
Dado que siempre está en movimiento, debe protegerse con el cifrado adecuado para evitar cualquier robo o alteración de los datos antes de que lleguen a su destino.
La situación ideal para proteger los datos en tránsito es cifrar los datos antes de que se muevan y solo se descifran cuando llegan al destino final.
Cifrado de datos en reposo MariaDB
El cifrado de tablas y espacios de tablas se agregó en MariaDB a partir de la versión 10.1 y admite el cifrado para motores de almacenamiento XtraDB, InnoDB y Aria, y también para registros binarios.
Puede elegir diferentes formas de cifrar:
- Todas las tablas
- Mesas individuales
- Todo, excepto tablas individuales
Según la documentación, el uso de cifrado tiene una sobrecarga de aproximadamente 3-5%, por lo que es importante tener un entorno de prueba para estresarlo y ver cómo responde, para evitar problemas en producción.
Cómo configurar el cifrado de datos en reposo en MariaDB
Veamos una tabla de "ciudad" existente en una base de datos MariaDB:
$ strings city.ibd |head
infimum
supremum
infimum
supremum
3ABW
3KHM
infimum
supremum
Kabul AFGKabol
Qandahar AFGQandahar
Como puede ver, puede leer datos desde allí sin ningún problema utilizando el comando strings de Linux, por ejemplo. Ahora, veamos cómo cifrarlo.
Generar claves de cifrado usando el comando rand de openssl:
$ mkdir -p /etc/mysql/encryption
$ for i in {1..4}; do openssl rand -hex 32 >> /etc/mysql/encryption/keyfile; done;
Edite el archivo generado /etc/mysql/encryption/keyfile y agregue los ID de clave a los que se hará referencia al crear tablas cifradas. El formato debe ser el siguiente:
<encryption_key_id1>;<hex-encoded_encryption_key1>
<encryption_key_id2>;<hex-encoded_encryption_key2>
Puedes editarlo usando el comando sed linux de esta manera:
$ for i in {1..4}; do sed -i -e "$i s/^/$i;/" keyfile; done
Entonces el archivo debería ser algo como esto:
$ cat /etc/mysql/encryption/keyfile
1;f237fe72e16206c0b0f6f43c3b3f4accc242564d77f5fe17bb621de388c193af
2;0c0819a10fb366a5ea657a71759ee6a950ae8f25a5ba7400a91f59b63683edc5
3;ac9ea3a839596dbf52492d9ab6b180bf11a35f44995b2ed752c370d920a10169
4;72afc936e16a8df05cf994c7902e588de0d11ca7301f9715d00930aa7d5ff8ab
Ahora, genera una contraseña aleatoria usando el comando openssl similar que viste antes:
$ openssl rand -hex 128 > /etc/mysql/encryption/keyfile.key
Antes de continuar con el siguiente paso, es importante conocer los siguientes detalles sobre el cifrado del archivo clave:
- El único algoritmo que MariaDB admite actualmente para cifrar el archivo clave es el modo Cipher Block Chaining (CBC) del estándar de cifrado avanzado (AES).
- El tamaño de la clave de cifrado puede ser de 128 bits, 192 bits o 256 bits.
- La clave de cifrado se crea a partir del hash SHA-1 de la contraseña de cifrado.
- La contraseña de cifrado tiene una longitud máxima de 256 caracteres.
Ahora, para encriptar el archivo clave usando el comando openssl enc, ejecute el siguiente comando:
$ openssl enc -aes-256-cbc -md sha1 -pass file:/etc/mysql/encryption/keyfile.key -in /etc/mysql/encryption/keyfile -out /etc/mysql/encryption/keyfile.enc
Finalmente, debe agregar los siguientes parámetros en su archivo de configuración my.cnf (ubicado en /etc/ en el sistema operativo basado en RedHat o /etc/mysql/ en el sistema operativo basado en Debian):
[mysqld]
…
#################### DATABASE ENCRYPTION ####################
plugin_load_add = file_key_management
file_key_management_filename = /etc/mysql/encryption/keyfile.enc
file_key_management_filekey = FILE:/etc/mysql/encryption/keyfile.key
file_key_management_encryption_algorithm = aes_cbc
encrypt_binlog = 1
innodb_encrypt_tables = ON
innodb_encrypt_log = ON
innodb_encryption_threads = 4
innodb_encryption_rotate_key_age = 0
…
Y reinicie el servicio MariaDB para tomar los cambios:
$ systemctl restart mariadb
En este punto, todo está listo para usar la función de encriptación. Codifiquemos la misma tabla que mostramos anteriormente, "ciudad". Para esto, debe usar la instrucción ALTER TABLE configurando el parámetro ENCRYPTED en SÍ:
MariaDB [world]> ALTER TABLE city ENCRYPTED=YES;
Query OK, 0 rows affected (0.483 sec)
Records: 0 Duplicates: 0 Warnings: 0
Ahora, si intenta acceder a la tabla directamente desde el sistema de archivos, verá algo como esto:
$ strings city.ibd |head
PU%O
!ybN)b
9,{9WB4
T3uG:
?oiN
,35sz
8g)Q
o(o
q_A1
k=-w
Como puede ver, la tabla es ilegible. También puede especificar el ID de clave de cifrado agregando el parámetro ENCRYPTION_KEY_ID =
Las tablas nuevas se cifrarán de forma predeterminada cuando establezcamos el parámetro innodb_encrypt_tables en ON en el archivo de configuración my.cnf.
Cifrado de datos en tránsito MariaDB
MariaDB le permite cifrar los datos en tránsito entre el servidor y los clientes utilizando el protocolo de seguridad de la capa de transporte (TLS), anteriormente conocido como capa de conexión segura o SSL.
En primer lugar, debe asegurarse de que su servidor MariaDB se compiló con soporte TLS. Puede verificar esto ejecutando la siguiente instrucción SHOW GLOBAL VARIABLES:
MariaDB [(none)]> SHOW GLOBAL VARIABLES LIKE 'version_ssl_library';
+---------------------+----------------------------+
| Variable_name | Value |
+---------------------+----------------------------+
| version_ssl_library | OpenSSL 1.1.1 11 Sep 2018 |
+---------------------+----------------------------+
1 row in set (0.001 sec)
Y verifique si no está actualmente en uso usando la instrucción SHOW VARIABLES:
MariaDB [(none)]> SHOW VARIABLES LIKE '%ssl%';
+---------------------+----------------------------+
| Variable_name | Value |
+---------------------+----------------------------+
| have_openssl | YES |
| have_ssl | DISABLED |
| ssl_ca | |
| ssl_capath | |
| ssl_cert | |
| ssl_cipher | |
| ssl_crl | |
| ssl_crlpath | |
| ssl_key | |
| version_ssl_library | OpenSSL 1.1.1 11 Sep 2018 |
+---------------------+----------------------------+
10 rows in set (0.001 sec)
También puede verificar el estado SSL usando el comando status MariaDB:
MariaDB [(none)]> status
--------------
mysql Ver 15.1 Distrib 10.4.13-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2
Connection id: 22
Current database:
Current user: [email protected]
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server: MariaDB
Server version: 10.4.13-MariaDB-1:10.4.13+maria~bionic-log mariadb.org binary distribution
Protocol version: 10
Connection: Localhost via UNIX socket
Server characterset: latin1
Db characterset: latin1
Client characterset: utf8
Conn. characterset: utf8
UNIX socket: /var/lib/mysql/mysql.sock
Uptime: 4 hours 28 min 25 sec
Threads: 11 Questions: 111668 Slow queries: 0 Opens: 92 Flush tables: 1 Open tables: 85 Queries per second avg: 6.933
--------------
Cómo configurar el cifrado de datos en tránsito en MariaDB
Vamos a crear el directorio de certificados para almacenar todos los certificados:
$ mkdir -p /etc/mysql/certs
Ahora, generemos los certificados de CA que se configurarán para cifrar la conexión:
$ openssl genrsa 2048 > ca-key.pem
$ openssl req -new -x509 -nodes -days 365000 -key ca-key.pem -out ca-cert.pem
Este último comando le pedirá que complete la siguiente información:
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:
Ahora, necesita generar los certificados del servidor:
$ openssl req -newkey rsa:2048 -nodes -keyout server-key.pem -out server-req.pem
Este comando le pedirá que complete la misma información que antes más una contraseña de certificado opcional.
$ openssl rsa -in server-key.pem -out server-key.pem
$ openssl x509 -req -in server-req.pem -days 365000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem
Y finalmente, necesita generar los certificados de cliente:
$ openssl req -newkey rsa:2048 -nodes -keyout client-key.pem -out client-req.pem
Esto también le pedirá que complete la información y una contraseña de certificado opcional.
$ openssl rsa -in client-key.pem -out client-key.pem
$ openssl x509 -req -in client-req.pem -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem
Asegúrese de estar usando un nombre común diferente en cada certificado; de lo contrario, no funcionará y recibirá un mensaje como:
ERROR 2026 (HY000): SSL connection error: self signed certificate
En este momento, tendrá algo como esto:
$ ls /etc/mysql/certs/
ca-cert.pem ca-key.pem client-cert.pem client-key.pem client-req.pem server-cert.pem server-key.pem server-req.pem
Y puede validar los certificados usando el siguiente comando:
$ openssl verify -CAfile ca-cert.pem server-cert.pem client-cert.pem
server-cert.pem: OK
client-cert.pem: OK
Así que ahora vamos a configurarlo en el archivo de configuración my.cnf (ubicado en /etc/ en el sistema operativo basado en RedHat o /etc/mysql/ en el sistema operativo basado en Debian):
[mysqld]
ssl_ca=/etc/mysql/certs/ca-cert.pem
ssl_cert=/etc/mysql/certs/server-cert.pem
ssl_key=/etc/mysql/certs/server-key.pem
[client-mariadb]
ssl_ca =/etc/mysql/certs/ca-cert.pem
ssl_cert=/etc/mysql/certs/client-cert.pem
ssl_key=/etc/mysql/certs/client-key.pem
Asegúrese de agregarlo en la sección correspondiente (mysqld y client-mariadb).
Cambie el propietario del certificado y reinicie el servicio de la base de datos:
$ chown mysql.mysql /etc/mysql/certs/
$ systemctl restart mariadb
Después de esto, si echa un vistazo a la salida MOSTRAR VARIABLES, debería tener esto:
MariaDB [(none)]> SHOW VARIABLES LIKE '%ssl%';
+---------------------+----------------------------------+
| Variable_name | Value |
+---------------------+----------------------------------+
| have_openssl | YES |
| have_ssl | YES |
| ssl_ca | /etc/mysql/certs/ca-cert.pem |
| ssl_capath | |
| ssl_cert | /etc/mysql/certs/server-cert.pem |
| ssl_cipher | |
| ssl_crl | |
| ssl_crlpath | |
| ssl_key | /etc/mysql/certs/server-key.pem |
| version_ssl_library | OpenSSL 1.1.1 11 Sep 2018 |
+---------------------+----------------------------------+
10 rows in set (0.001 sec)
Ahora, vamos a crear un usuario con el parámetro REQUIRE SSL para usarlo:
MariaDB [(none)]> GRANT ALL PRIVILEGES ON *.* TO 's9s'@'%' IDENTIFIED BY 'root123' REQUIRE SSL;
Query OK, 0 rows affected (0.005 sec)
Si usa este usuario para acceder a la base de datos y verifica el comando de estado, verá el SSL en uso:
MariaDB [(none)]> status
--------------
mysql Ver 15.1 Distrib 10.4.13-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2
Connection id: 15
Current database:
Current user: [email protected]
SSL: Cipher in use is TLS_AES_256_GCM_SHA384
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server: MariaDB
Server version: 10.4.13-MariaDB-1:10.4.13+maria~bionic-log mariadb.org binary distribution
Protocol version: 10
Connection: 127.0.0.1 via TCP/IP
Server characterset: latin1
Db characterset: latin1
Client characterset: utf8
Conn. characterset: utf8
TCP port: 3306
Uptime: 16 sec
Threads: 11 Questions: 136 Slow queries: 0 Opens: 17 Flush tables: 1 Open tables: 11 Queries per second avg: 8.500
--------------
Cómo habilitar el cifrado SSL con ClusterControl
Otra forma, e incluso más fácil, de habilitar SSL en su base de datos MariaDB es mediante el uso de ClusterControl. Asumiremos que tiene instalado ClusterControl y que está administrando su base de datos MariaDB usándola, así que vaya a ClusterControl -> Seleccione su clúster MariaDB -> Seguridad -> Cifrado SSL -> Habilitar.

Y listo, tendrás tu encriptación SSL habilitada en tu base de datos MariaDB sin ninguna tarea manual.
Limitaciones de cifrado en reposo en MariaDB
Hay algunas limitaciones relacionadas con el cifrado en reposo de MariaDB que se deben tener en cuenta:
- Los metadatos (por ejemplo, archivos .frm) y los datos enviados al cliente no están encriptados.
- Solo el servidor MariaDB sabe cómo descifrar los datos, en particular
- mysqlbinlog puede leer registros binarios encriptados solo cuando se usa --read-from-remote-server.
- Percona XtraBackup no puede realizar copias de seguridad de instancias que utilizan InnoDB encriptado. Sin embargo, Mariabackup puede realizar copias de seguridad de instancias cifradas.
- El gcache de Galera basado en disco no está encriptado en la versión comunitaria de MariaDB Server, sin embargo, este archivo está encriptado en MariaDB Enterprise Server 10.4.
- El complemento de auditoría no puede crear una salida cifrada. Envíelo a syslog y configure la protección allí.
- El registro de consultas generales basado en archivos y el registro de consultas lentas no se pueden cifrar.
- El registro de Aria no está cifrado. Esto afecta solo a las tablas Aria no temporales.
- El registro de errores de MariaDB no está cifrado. El registro de errores puede contener texto de consulta y datos en algunos casos, incluidos bloqueos, fallas de aserción y casos en los que InnoDB/XtraDB escribe la salida del monitor en el registro para ayudar en la depuración. También se puede enviar a syslog si es necesario.
Conclusión
La protección de los datos en tránsito es tan importante como la protección de los datos en reposo, e incluso si no es una obligación en su organización, debe considerar aplicarla, ya que puede ayudarlo a evitar que los datos robo o acceso no autorizado.
MariaDB tiene una manera bastante fácil de implementarlo siguiendo los pasos mencionados anteriormente, pero seguro que es aún más fácil usando ClusterControl.