Mysql con SSL. Reforzando la seguridad.
En esta entrada muestro configurar un servidor mysql y uno (o varios) clientes para realizar las conexiones mediante ssl.
NOTA: Aclaro que toda la información necesaria la saqué directamente de la documentación oficial de mysql.
1. Servidor mysql (compilado con soporte a yaSSL).
2. Cliente mysql (compilado con soporte a yaSSL).
3. OpenSSL.
4. Ganas de intentar.
1. Crear los cerficados y claves privadas para:
- El CA (servidor mismo en este caso),
- Servidor.
- Cliente(s).
2. Ejecutar el servidor, indicandole los parámetros indicados.
3. Verificar y corregir bug que nos impediría la conexion con ssl.
4. Añadir las restricciones de seguridad por usuario:
- Nivel 1: Solo asegura la identidad del servidor.
- Nivel 2: Obliga al cliente a validar la identidad del servidor.
- Nivel 3: Asegura que cada usuario está certificado por el CA (sin importar quien sea), además de hacer lo que hace el nivel 1.
- Nivel 4: Asegura lo mismo que 1, y añade que cada usuario debe si o sí obtener su certificado y clave privada para poder conectar con el servidor.
5. Conectar el cliente al servidor.
Paso 1: Crear los cerficados y claves privadas.
Creando certificados:
CA,
Y respondemos a todas las preguntas...
Con eso generamos la clave privada y el certificado del CA (entidad de certificación) que este caso seremos nosotros mismos. Todo esto se podría haber hecho en un solo paso como se muestra a continuación con el primer comando invocado.
-SERVER
"server-cert.pem".
-CLIENTE
Un primer cliente.
Paso 2: Ejecutar el servidor, indicandole los parámetros necesarios.
NOTA: Aclaro que toda la información necesaria la saqué directamente de la documentación oficial de mysql.
REQUERIMIENTOS:
Para hacer todo necesitaremos:1. Servidor mysql (compilado con soporte a yaSSL).
2. Cliente mysql (compilado con soporte a yaSSL).
3. OpenSSL.
4. Ganas de intentar.
MANOS A LA OBRA:
Básicamente son 3 pasos:1. Crear los cerficados y claves privadas para:
- El CA (servidor mismo en este caso),
- Servidor.
- Cliente(s).
2. Ejecutar el servidor, indicandole los parámetros indicados.
3. Verificar y corregir bug que nos impediría la conexion con ssl.
4. Añadir las restricciones de seguridad por usuario:
- Nivel 1: Solo asegura la identidad del servidor.
- Nivel 2: Obliga al cliente a validar la identidad del servidor.
- Nivel 3: Asegura que cada usuario está certificado por el CA (sin importar quien sea), además de hacer lo que hace el nivel 1.
- Nivel 4: Asegura lo mismo que 1, y añade que cada usuario debe si o sí obtener su certificado y clave privada para poder conectar con el servidor.
5. Conectar el cliente al servidor.
Paso 1: Crear los cerficados y claves privadas.
Creando certificados:
CA,
mysqladmin@gaspar:~/mysql_certs$ openssl genrsa 2048 > ca-key.pem
mysqladmin@gaspar:~/mysql_certs$ openssl req -new -x509 -nodes -days 1000 -key ca-key.pem > ca-cert.pem
Y respondemos a todas las preguntas...
Con eso generamos la clave privada y el certificado del CA (entidad de certificación) que este caso seremos nosotros mismos. Todo esto se podría haber hecho en un solo paso como se muestra a continuación con el primer comando invocado.
-SERVER
mysqladmin@gaspar:~/mysql_certs$ openssl req -newkey rsa:2048 -days 1000 -nodes -keyout server key.pem > server-req.pemEs importante entender que en el primer paso generamos la clave privada y el archivo con los datos de identidad del servidor (req), y que en el seguno paso lo que hacemos es firmar este archivo req con la clave privada del CA (y además agregamos el certificado de este), generando el certificado del servidor:
mysqladmin@gaspar:~/mysql_certs$ openssl x509 -req -in server-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > server-cert.pem
"server-cert.pem".
-CLIENTE
Un primer cliente.
mysqladmin@gaspar:~/mysql_certs$ openssl req -newkey rsa:2048 -days 1000 -nodes -keyout jaa-key.pem > jaa-req.pemUn segundo cliente.
mysqladmin@gaspar:~/mysql_certs$ openssl x509 -req -in jaa-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > jaa-cert.pem
mysqladmin@gaspar:~/mysql_certs$ openssl req -newkey rsa:2048 -days 1000 -nodes -keyout pepe-key.pem > pepe-req.pemCon esto generamos la clave privada y el certificado para dos clientes: jaa y pepe. Si necesitamos generar más simplemente volvemos a ejecutar estos dos pasos (pero obviamente cambiando los nombres de los archivos de salida!).
mysqladmin@gaspar:~/mysql_certs$ openssl x509 -req -in pepe-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > pepe-cert.pem
Paso 2: Ejecutar el servidor, indicandole los parámetros necesarios.
Este paso es sencillo, simplemente invocamos al servidor, pero debemos indicarle los parámetros necesarios para que este use su clave privada y certificado, además del certificado del CA para que pueda luego validar a los demás usuarios.
Paso 4: Añadir las restricciones de seguridad por usuario.
mysqladmin@gaspar:~/mysql_certs$ mysqld --ssl-ca=ca-cert.pem --ssl-cert=server-cert.pem --ssl-key=server-key.pemPaso 3: Verificar y corregir bug que nos impedirá la conexión con ssl.
Bueno este bug a mi me ocurre en linux, y SOLO CON EL CLIENTE MYSQL, para la siguiente version:
"ERROR 2026 (HY000): SSL connection error"
entonces hacemos:
Supongo que obteniendo las fuentes del último mysql client, y compilando el error debería desaparecer, una alternativa es compilar utilizando openssl ya que por defecto en mysql se usa yaSSL, esto por temas de compativilidad entre licencias.
Resalto que en windows no he tenido ningún problema al respecto.
jaa@dino-thunder:~$ mysql --versionel tema es que cuando intentemos conectar utilizando las opciones avanzadas de ssl no podremos conectar por un supuesto error de SSL:
mysql Ver 14.12 Distrib 5.0.38, for pc-linux-gnu (i486) using readline 5.2
"ERROR 2026 (HY000): SSL connection error"
entonces hacemos:
root@Patrulla-Delta:/home/jaa/mysql-cert/2# echo "192.168.1.1" >> /etc/hostsObviamente hay que reemplazar la direccion ip con la del servidor real.
Supongo que obteniendo las fuentes del último mysql client, y compilando el error debería desaparecer, una alternativa es compilar utilizando openssl ya que por defecto en mysql se usa yaSSL, esto por temas de compativilidad entre licencias.
Resalto que en windows no he tenido ningún problema al respecto.
MySql ofrece 4 niveles de seguridad configurables, para la mayor seguridad, debe aplicarse el nivel 4.
Antes de continuar informo algunas cosas simples:
Nivel 2 - Este nivel lo que hace es obligar al cliente a que cumpla uno de los dos requerimientos:
1. Presentar el certificado del CA (con este el cliente valida al servidor).
2. Validar con un certificado firmado por el CA (y obviamente utilizando su clave privada).
Bueno, la diferencia está en que ahora el servidor nos obliga a presentar el certificado del CA.
En el segundo caso intento ingresar presentando un certificado de CA erroneo, por lo cual también nos da una patada.
En el Tercer caso, presento un certificado firmado por el CA y logro el acceso.
Nivel 3 - Este se aplica del lado servidor. Lo que haremos será decirle al servidor que solo acepte al usuario "jaa" si presenta un certificado firmado por el CA. Pero como hacemos esto?, bueno no es tan complicado:
- En primer lugar obtenemos lo que se denomina issuer del certificado de uno de los clientes:
Es interesante notar que sea cual sea el certificado de cliente o el servidor al que apliquemos el comando siempre obtendremos el mismo contenido (siempre y cuando hallan sido firmados nuestro CA!), por ejemplo si hacemos:
ahora para conectar:
Nivel 4- Este es el nivel más seguro; en este le decimos al servidor que un cliente solo puede conectarse si presenta su propio certificado. En este caso utilizamos el "SUBJECT", el cual tiene los datos del usuario (cliente) mismo.
Primero obtenemos el subject del certificado:
Entonces vamos a mysql:
Si en este útimo caso intentamos conectar al servidor sin presentar nuestras credenciales estamos fritos, y además tampoco podemos usar el certificado y clave del usuario 'pepe'.
Con todo esto el servidor debería quedar funcionando.
Antes de continuar informo algunas cosas simples:
- ip del servidor: 192.168.1.1
- host cliente: Patrulla-Delta.local
- Todos los certificados fueron generados en el servidor pero deben copiarse al host cliente en algún lugar (en lo posible al hacer transferencias por red siempre utilizar scp!).
con esto aseguramos que ningún host intermedio robe la identidad del host servidor, es decir aseguramos la identidad del servidor, ya que este está corriendo (según lo que hicimos en 2) utilizando su certificado y clave privada, por lo tanto ahora nuestro cliente validará la firma del certificado servidor con el certificado del CA que indicamos.
$ mysql --ssl-ca=ca-cert.pem -u usuario ...
Nivel 2 - Este nivel lo que hace es obligar al cliente a que cumpla uno de los dos requerimientos:
1. Presentar el certificado del CA (con este el cliente valida al servidor).
2. Validar con un certificado firmado por el CA (y obviamente utilizando su clave privada).
Entonces para conectar
mysql> create user pepe@'%' identified by 'lalala';
mysql> GRANT ALL PRIVILEGES ON *.* TO 'jaa'@'%' REQUIRE SSL;
mysql> flush privileges;
Y uno se pregunta: pero cual es la diferencia con el nivel anterior?
$ mysql --ssl-ca=ca-cert.pem -u pepe -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 71
Server version: xxxxx
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql>
Bueno, la diferencia está en que ahora el servidor nos obliga a presentar el certificado del CA.
jaa@Patrulla-Delta:~/mysql-cert/2$ mysql -u pepe -p -h 192.168.1.1En el primer caso intento ingresar sin presentar el certificado del CA, entonces el servidor nos niega el acceso.
Enter password:
ERROR 1045 (28000): Access denied for user 'pepe'@'Patrulla-Delta.local' (using password: YES)
jaa@Patrulla-Delta:~/mysql-cert/2$ mysql --ssl-ca=jaa-cert.pem -u pepe -p -h 192.168.1.1
Enter password:
ERROR 2026 (HY000): SSL connection error
jaa@Patrulla-Delta:~/mysql-cert/2$ mysql --ssl-cert=pepe-cert.pem --ssl-key=pepe-key.pem -u pepe -p -h 192.168.1.1
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 77
Server version: xxxxx
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql>
En el segundo caso intento ingresar presentando un certificado de CA erroneo, por lo cual también nos da una patada.
En el Tercer caso, presento un certificado firmado por el CA y logro el acceso.
Nivel 3 - Este se aplica del lado servidor. Lo que haremos será decirle al servidor que solo acepte al usuario "jaa" si presenta un certificado firmado por el CA. Pero como hacemos esto?, bueno no es tan complicado:
- En primer lugar obtenemos lo que se denomina issuer del certificado de uno de los clientes:
jaa@Patrulla-Delta:~/mysql-cert/2/jaa$ openssl x509 -in client-cert.pem -noout -issuerla linea que dice issuer= /C... corresponde con la información que necesitamos. Esta es la información acerca del CA, la cual para mi caso quedó como mostré.
issuer= /C=AR/ST=Capital Federal/L=Capital Federal/O=OpenOrange/OU=Programacion/CN=OpenOrange Dpto. Cert./emailAddress=info@openorange.com.ar
Es interesante notar que sea cual sea el certificado de cliente o el servidor al que apliquemos el comando siempre obtendremos el mismo contenido (siempre y cuando hallan sido firmados nuestro CA!), por ejemplo si hacemos:
jaa@Patrulla-Delta:~/mysql-cert/2/jaa$ openssl x509 -in pepe-cert.pem -noout -issuerEntonces nuestro issuer sera:
issuer= /C=AR/ST=Capital Federal/L=Capital Federal/O=OpenOrange/OU=Programacion/CN=OpenOrange Dpto. Cert./emailAddress=info@openorange.com.ar
issuer= /C=AR/ST=Capital Federal/L=Capital Federal/O=OpenOrange/OU=Programacion/CN=OpenOrange Dpto. Cert./emailAddress=info@openorange.com.arAhora lo que hacemos es aplicar la restricción dentro del servidor mysql:
En estas dos líneas cree el usuario, y seguido a esto le asigné la restricción.
mysql> create user jaa@'%' identified by 'lalala';
mysql> GRANT ALL PRIVILEGES ON *.* TO 'jaa'@'%'
-> REQUIRE ISSUER '/C=AR/ST=Capital Federal/L=Capital Federal/O=OpenOrange/OU=Programacion/CN=OpenOrange Dpto. Cert./emailAddress=info@openorange.com.ar';
mysql> flush privileges;
ahora para conectar:
Y hacemos una prueba más, supongamos que como 'jaa' tenemos en nuestras manos la clave privada y certificado de 'pepe' (digamos que pepe confia en que no lo venderemos por ahí), entonces:
jaa@Patrulla-Delta:~/mysql-cert/2/jaa$ mysql --ssl-ca=ca-cert.pem --ssl-cert=jaa-cert.pem --ssl-key=jaa-key.pem -u jaa -h 192.168.1.1 -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 71
Server version: xxxxx
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql>
jaa@Patrulla-Delta:~/mysql-cert/2/jaa$ mysql --ssl-ca=ca-cert.pem --ssl-cert=pepe-cert.pem --ssl-key=pepe-key.pem -u jaa -h 192.168.1.1 -pvemos que podemos utilizar el certificado y clave de pepe sin ningún problema para conectarnos con nuestro usuario. Esto es debido a que todos los usuarios de clientes que generamos comparten el issuer.
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 71
Server version: xxxxx
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql>
Nivel 4- Este es el nivel más seguro; en este le decimos al servidor que un cliente solo puede conectarse si presenta su propio certificado. En este caso utilizamos el "SUBJECT", el cual tiene los datos del usuario (cliente) mismo.
Primero obtenemos el subject del certificado:
jaa@Patrulla-Delta:~/mysql-cert/2$ openssl x509 -in jaa-cert.pem -noout -subjectAl igual que para el issuer, el subject es lo que viene despues de "subject= ".
subject= /C=AR/ST=Buenos Aires/L=Brandsen/O=JAATesting/OU=Programacion/CN=Jonatan Anauati/emailAddress=janauati@openorange.com.ar
Entonces vamos a mysql:
si el usuario no existía:y ahora solo falta conectarnos:
mysql> create user jaa@'%';
Las siguientes dos son alternativas, si el usuario quedo del ejemplo anterior, en otro
caso pueden ser saltadas.
mysql> revoke all privileges on *.* from test2@'%';
mysql> update mysql.user set password=NULL where User=jaa2@'%';
Query OK, 0 rows affected (0.00 sec)
mysql> GRANT ALL PRIVILEGES ON *.* TO 'jaa'@'%'
-> REQUIRE SUBJECT '/C=AR/ST=Buenos Aires/L=Brandsen/O=JAATesting/OU=Programacion/CN=Jonatan Anauati/emailAddress=janauati@openorange.com.ar';
mysql> flush privileges;
jaa@Patrulla-Delta:~/mysql-cert/2/jaa$ mysql --ssl-ca=ca-cert.pem --ssl-cert=jaa-cert.pem --ssl-key=jaa-key.pem -u jaa -h 192.168.1.1Para este caso, al usuario le quité el password, ya que unicamente el puede conectarse ya que requiere siempre presentar su certificado y firmar (y desencriptar) con su clave privada ante el servidor.
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 71
Server version: xxxxx
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql>
Si en este útimo caso intentamos conectar al servidor sin presentar nuestras credenciales estamos fritos, y además tampoco podemos usar el certificado y clave del usuario 'pepe'.
Con todo esto el servidor debería quedar funcionando.
Etiquetas: bases de datos, certificados x509, linux, mysql, openssl, red, seguridad informática, ssl

0 comentarios:
Publicar un comentario en la entrada
Suscribirse a Enviar comentarios [Atom]
<< Página principal