Comment configurer SSL / TLS pour MySQL sur Ubuntu 16.04

introduction

MySQL est le système de gestion de base de données relationnelle open source le plus populaire au monde. Les gestionnaires de paquets modernes ont réduit les difficultés liées à la mise en service de MySQL, mais il reste encore une certaine configuration à effectuer après l'installation. La sécurité est l’un des domaines les plus importants sur lesquels il faut consacrer du temps supplémentaire.

Par défaut, MySQL est configuré pour n'accepter que les connexions locales. Si vous devez autoriser les connexions à distance, il est important de le faire en toute sécurité. Dans ce guide, nous montrerons comment configurer MySQL sous Ubuntu 16.04 pour accepter les connexions distantes avec cryptage SSL / TLS.

Conditions préalables

Pour suivre ce guide, vous aurez besoin des serveurs Ubuntu 16.04two. Nous allons utiliser l’un en tant que serveur MySQL et l’autre en tant que client. Créez un utilisateur non root avec les privilègessudo sur chacun de ces serveurs. Suivez nosUbuntu 16.04 initial server setup guide pour mettre votre serveur dans l'état initial approprié.

Sur la première machine, vous devriez avoir lesMySQL server installés et configurés. Suivez nosMySQL installation guide for Ubuntu 16.04 pour installer et configurer le logiciel.

Sur la deuxième machine, installez le packageMySQL client. Vous pouvez mettre à jour l'index du packageapt et installer le logiciel nécessaire en tapant:

sudo apt-get update
sudo apt-get install mysql-client

Lorsque votre serveur et votre client sont prêts, continuez ci-dessous.

Vérifier l'état actuel de SSL / TLS

Avant de commencer, nous pouvons vérifier l'état actuel de SSL / TLS sur notre instanceMySQL server.

Connectez-vous à une session MySQL en utilisant l'utilisateur MySQL deroot. Nous utiliserons-h pour spécifier l'interface de bouclage locale IPv4 afin de forcer le client à se connecter avec TCP au lieu d'utiliser le fichier de socket local. Cela nous permettra de vérifier l’état de SSL pour les connexions TCP:

mysql -u root -p -h 127.0.0.1

Vous serez invité à entrer le mot de passe MySQLroot que vous avez sélectionné lors du processus d'installation. Ensuite, vous serez amené à une session interactive MySQL.

Affichez l'état des variables SSL / TLS en tapant:

SHOW VARIABLES LIKE '%ssl%';
Output+---------------+----------+
| Variable_name | Value    |
+---------------+----------+
| have_openssl  | DISABLED |
| have_ssl      | DISABLED |
| ssl_ca        |          |
| ssl_capath    |          |
| ssl_cert      |          |
| ssl_cipher    |          |
| ssl_crl       |          |
| ssl_crlpath   |          |
| ssl_key       |          |
+---------------+----------+
9 rows in set (0.01 sec)

Les variableshave_openssl ethave_ssl sont toutes deux marquées commeDISABLED. Cela signifie que la fonctionnalité SSL a été compilée sur le serveur, mais qu'elle n'est pas encore activée.

Vérifiez l'état de notre connexion actuelle pour confirmer:

\s
Output--------------
mysql  Ver 14.14 Distrib 5.7.17, for Linux (x86_64) using  EditLine wrapper

Connection id:      30
Current database:
Current user:       root@localhost
SSL:         Not in use
Current pager:      stdout
Using outfile:      ''
Using delimiter:    ;
Server version:     5.7.17-0ubuntu0.16.04.1 (Ubuntu)
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:         3 hours 38 min 44 sec

Threads: 1  Questions: 70  Slow queries: 0  Opens: 121  Flush tables: 1  Open tables: 40  Queries per second avg: 0.005
--------------

Comme l'indique la sortie ci-dessus, SSL n'est pas utilisé pour notre connexion, même si nous sommes connectés via TCP.

Fermez la session MySQL en cours lorsque vous avez terminé:

exit

Nous pouvons maintenant commencer à configurer MySQL pour SSL afin de sécuriser nos connexions.

Générer des certificats et des clés SSL / TLS

Pour activer les connexions SSL à MySQL, nous devons d’abord générer le certificat et les fichiers de clé appropriés. Un utilitaire appelémysql_ssl_rsa_setup est fourni avec MySQL 5.7 et supérieur pour simplifier ce processus. Ubuntu 16.04 a une version compatible de MySQL, nous pouvons donc utiliser cette commande pour générer les fichiers nécessaires.

Les fichiers seront créés dans le répertoire de données de MySQL, situé à/var/lib/mysql. Nous avons besoin du processus MySQL pour pouvoir lire les fichiers générés, nous allons donc passermysql en tant qu'utilisateur qui devrait posséder les fichiers générés:

sudo mysql_ssl_rsa_setup --uid=mysql

La génération produira une sortie qui ressemble à ceci:

OutputGenerating a 2048 bit RSA private key
...................................+++
.....+++
writing new private key to 'ca-key.pem'
-----
Generating a 2048 bit RSA private key
......+++
.................................+++
writing new private key to 'server-key.pem'
-----
Generating a 2048 bit RSA private key
......................................................+++
.................................................................................+++
writing new private key to 'client-key.pem'
-----

Vérifiez les fichiers générés en tapant:

sudo find /var/lib/mysql -name '*.pem' -ls
Output   256740      4 -rw-r--r--   1 mysql    mysql        1078 Mar 17 17:24 /var/lib/mysql/server-cert.pem
   256735      4 -rw-------   1 mysql    mysql        1675 Mar 17 17:24 /var/lib/mysqlsql/ca-key.pem
   256739      4 -rw-r--r--   1 mysql    mysql         451 Mar 17 17:24 /var/lib/mysqlsql/public_key.pem
   256741      4 -rw-------   1 mysql    mysql        1679 Mar 17 17:24 /var/lib/mysqlsql/client-key.pem
   256737      4 -rw-r--r--   1 mysql    mysql        1074 Mar 17 17:24 /var/lib/mysqlsql/ca.pem
   256743      4 -rw-r--r--   1 mysql    mysql        1078 Mar 17 17:24 /var/lib/mysqlsql/client-cert.pem
   256736      4 -rw-------   1 mysql    mysql        1675 Mar 17 17:24 /var/lib/mysqlsql/private_key.pem
   256738      4 -rw-------   1 mysql    mysql        1675 Mar 17 17:24 /var/lib/mysqlsql/server-key.pem

La dernière colonne affiche les noms de fichiers générés. Les colonnes centrales indiquant «mysql» indiquent que les fichiers générés ont la propriété d'utilisateur et de groupe correct.

Ces fichiers sont les paires clé / certificat pour l'autorité de certification (en commençant par «ca»), le processus serveur MySQL (en commençant par «serveur») et pour les clients MySQL (en commençant par «client»). De plus, les fichiersprivate_key.pem etpublic_key.pem sont utilisés par MySQL pour transférer en toute sécurité le mot de passe lorsque vous n'utilisez pas SSL.

Activer les connexions SSL sur le serveur MySQL

Les versions modernes de MySQL rechercheront les fichiers de certificat appropriés dans le répertoire de données MySQL au démarrage du serveur. De ce fait, nous n’avons pas besoin de modifier la configuration de MySQL pour activer SSL.

Nous pouvons simplement redémarrer le service MySQL à la place:

sudo systemctl restart mysql

Après le redémarrage, ouvrez une nouvelle session MySQL en utilisant la même commande que précédemment. Le client MySQL essaiera automatiquement de se connecter en utilisant SSL s'il est supporté par le serveur:

mysql -u root -p -h 127.0.0.1

Jetons un coup d’œil aux mêmes informations que nous avions demandées la dernière fois. Vérifiez les valeurs des variables liées à SSL:

SHOW VARIABLES LIKE '%ssl%';
Output+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| have_openssl  | YES             |
| have_ssl      | YES             |
| ssl_ca        | ca.pem          |
| ssl_capath    |                 |
| ssl_cert      | server-cert.pem |
| ssl_cipher    |                 |
| ssl_crl       |                 |
| ssl_crlpath   |                 |
| ssl_key       | server-key.pem  |
+---------------+-----------------+
9 rows in set (0.00 sec)

Les variableshave_openssl ethave_ssl lisent «OUI» au lieu de «DÉSACTIVÉ» cette fois. De plus, les variablesssl_ca,ssl_cert etssl_key ont été renseignées avec les noms des certificats pertinents que nous avons générés.

Ensuite, vérifiez à nouveau les détails de la connexion:

\s
Output--------------
. . .
SSL:            Cipher in use is DHE-RSA-AES256-SHA
. . .
Connection:      127.0.0.1 via TCP/IP
. . .
--------------

Cette fois, le chiffrement SSL spécifique est affiché, indiquant que SSL est utilisé pour sécuriser notre connexion.

Sortez vers le shell:

exit

Notre serveur est maintenant capable d'utiliser le cryptage, mais une configuration supplémentaire est nécessaire pour permettre l'accès à distance et imposer l'utilisation de connexions sécurisées.

Configuration des connexions sécurisées pour les clients distants

Maintenant que SSL est disponible sur le serveur, nous pouvons commencer à configurer un accès distant sécurisé. Pour ce faire, nous devons:

  • Exiger SSL pour les connexions à distance

  • Lier à une interface publique

  • Créer un utilisateur MySQL pour les connexions à distance

  • Ajustez nos règles de pare-feu pour autoriser les connexions externes

Configurer l'accès à distance avec SSL obligatoire

Actuellement, le serveur MySQL est configuré pour accepter les connexions SSL des clients. Cependant, il autorisera toujours les connexions non chiffrées si le client le demande.

Nous pouvons résoudre ce problème en activant l'optionrequire_secure_transport. Cela nécessite que toutes les connexions soient établies avec SSL ou avec un socket Unix local. Les sockets Unix n'étant accessibles que depuis le serveur lui-même, la seule option de connexion ouverte aux utilisateurs distants sera SSL.

Pour activer ce paramètre, ouvrez le fichier/etc/mysql/my.cnf dans votre éditeur de texte:

sudo nano /etc/mysql/my.cnf

À l'intérieur, il y aura deux directives!includedir utilisées pour générer des fichiers de configuration supplémentaires. Nous aurons besoin de mettre notre propre configurationbeneath ces lignes afin qu'elles remplacent tous les paramètres en conflit.

Commencez par créer une section[mysqld] pour cibler le processus serveur MySQL. Sous cet en-tête de section, définissezrequire_secure_transport surON:

/etc/mysql/my.cnf

. . .

!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/

[mysqld]
# Require clients to connect either using SSL
# or through a local socket file
require_secure_transport = ON

Cette ligne est le seul paramètre requis pour appliquer des connexions sécurisées.

Par défaut, MySQL est configuré pour n'écouter que les connexions provenant de l'ordinateur local. Pour le configurer pour écouter les connexions à distance, nous pouvons définir lebind-address sur une interface différente.

Pour permettre à MySQL d'accepter des connexions sur l'une de ses interfaces, nous pouvons définirbind-address sur «0.0.0.0»:

/etc/mysql/my.cnf

. . .

!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/

[mysqld]
# Require clients to connect either using SSL
# or through a local socket file
require_secure_transport = ON
bind-address = 0.0.0.0

Enregistrez et fermez le fichier lorsque vous avez terminé.

Ensuite, redémarrez MySQL pour appliquer les nouveaux paramètres:

sudo systemctl restart mysql

Vérifiez que MySQL écoute sur “0.0.0.0” au lieu de “127.0.0.1” en tapant:

sudo netstat -plunt
OutputActive Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:3306            0.0.0.0:*               LISTEN      4330/mysqld
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1874/sshd
tcp6       0      0 :::22                   :::*                    LISTEN      1874/sshd

“0.0.0.0” dans la sortie ci-dessus indique que MySQL est à l'écoute des connexions sur toutes les interfaces disponibles.

Ensuite, nous devons autoriser les connexions MySQL à travers notre pare-feu. Créez une exception en tapant:

sudo ufw allow mysql
OutputRule added
Rule added (v6)

Les tentatives de connexion à distance devraient maintenant pouvoir atteindre notre serveur MySQL.

Configurer un utilisateur MySQL distant

Le serveur MySQL écoute maintenant les connexions à distance, mais aucun utilisateur configuré ne peut actuellement se connecter depuis un ordinateur externe.

Connectez-vous à MySQL en tant qu'utilisateurroot pour commencer:

mysql -u root -p

À l'intérieur, vous pouvez créer un nouvel utilisateur distant à l'aide de la commandeCREATE USER. Nous allons utiliser l’adresse IP de notre machine cliente dans la partie hôte de la spécification de l’utilisateur pour limiter les connexions à cette machine.

Pour une certaine redondance au cas où l'optionrequire_secure_transport serait désactivée à l'avenir, nous spécifierons également lors de la création du compte que cet utilisateur requiert SSL en incluant la clauseREQUIRE SSL:

CREATE USER 'remote_user'@'mysql_client_IP' IDENTIFIED BY 'password' REQUIRE SSL;

Ensuite, accordez aux nouveaux utilisateurs des autorisations sur les bases de données ou les tables auxquelles ils devraient avoir accès. Pour démontrer, nous allons créer une base de donnéesexample et donner à notre nouvel utilisateur la propriété:

CREATE DATABASE example;
GRANT ALL ON example.* TO 'remote_user'@'mysql_client_IP';

Ensuite, supprimez les privilèges pour appliquer ces paramètres immédiatement:

FLUSH PRIVILEGES;

Quittez le shell lorsque vous avez terminé:

exit

Notre serveur est configuré pour permettre les connexions à notre utilisateur distant.

Test des connexions à distance

Sur la machineMySQL client, effectuez un test pour vous assurer que vous pouvez vous connecter au serveur avec succès. Utilisez l’option-u pour spécifier l’utilisateur distant et l’option-h pour spécifier l’adresse IP du serveur MySQL:

mysql -u remote_user -p -h mysql_server_IP

Après avoir spécifié le mot de passe, vous serez connecté au serveur distant.

Vérifiez que votre connexion est sécurisée:

\s
Output--------------
. . .
SSL:         Cipher in use is DHE-RSA-AES256-SHA
. . .
Connection:      mysql_server_IP via TCP/IP
. . .
--------------

Sortez vers le shell:

exit

Ensuite, essayez de vous connecter de manière non sécurisée:

mysql -u remote_user -p -h mysql_server_IP --ssl-mode=disabled

Après avoir été invité à entrer votre mot de passe, votre connexion devrait être refusée:

OutputERROR 1045 (28000): Access denied for user 'remote_user'@'mysql_server_IP' (using password: YES)

C'est ce à quoi nous travaillions. Il montre que les connexions SSL sont autorisées, tandis que les connexions non chiffrées sont refusées.

À ce stade, notre serveur MySQL a été configuré pour accepter les connexions distantes de manière sécurisée. Vous pouvez vous arrêter ici si cela répond à vos exigences en matière de sécurité, mais nous pouvons mettre en place certains éléments supplémentaires pour renforcer notre sécurité et renforcer notre confiance.

Configuration de la validation pour les connexions MySQL (facultatif)

Actuellement, notre serveur MySQL est configuré avec un certificat SSL signé par une autorité de certification générée localement. Le certificat et la paire de clés du serveur suffisent pour assurer le cryptage des connexions entrantes.

Cependant, nous n’exploitons pas actuellement la relation de confiance qu’une autorité de certification peut fournir. En distribuant le certificat de l'autorité de certification aux clients, ainsi que le certificat client et la clé, les deux parties peuvent prouver que leurs certificats ont été signés par une autorité de certification de confiance mutuelle. Cela peut aider à empêcher les connexions usurpées vers des serveurs malveillants.

Afin de mettre en œuvre cette sauvegarde supplémentaire facultative, nous devrons:

  • Transférer les fichiers SSL appropriés sur la machine cliente

  • Créer un fichier de configuration client

  • Modifier notre utilisateur distant pour exiger un certificat de confiance

Transférer les certificats clients sur l'ordinateur client

Pour commencer, nous devons récupérer les fichiers de certificat client et de l'autorité de certification MySQL sur le serveur MySQL et les placer sur le client MySQL.

Commencez par créer un répertoire sur lesMySQL client dans le répertoire personnel de l'utilisateur que vous utiliserez pour vous connecter. Appelez ceciclient-ssl:

mkdir ~/client-ssl

Puisque la clé de certificat est sensible, nous devrions verrouiller l'accès à ce répertoire afin que seul l'utilisateur actuel puisse y accéder:

chmod 700 ~/client-ssl

Maintenant, nous pouvons copier les informations de certificat dans le nouveau répertoire.

Sur la machineMySQL server, affichez le contenu du certificat CA en tapant:

sudo cat /var/lib/mysql/ca.pem
Output-----BEGIN CERTIFICATE-----

. . .

-----END CERTIFICATE-----

Copiez toute la sortie, y compris les lignesBEGIN CERTIFICATE etEND CERTIFICATE dans votre presse-papiers.

Sur lesMySQL client, créez un fichier avec le même nom dans le nouveau répertoire:

nano ~/client-ssl/ca.pem

A l'intérieur, collez le contenu du certificat copié à partir de votre presse-papiers. Enregistrez et fermez le fichier lorsque vous avez terminé.

Ensuite, affichez le certificat client sur lesMySQL server:

sudo cat /var/lib/mysql/client-cert.pem
Output-----BEGIN CERTIFICATE-----

. . .

-----END CERTIFICATE-----

Encore une fois, copiez le contenu dans votre presse-papiers. N'oubliez pas d'inclure la première et la dernière ligne.

Ouvrez un fichier du même nom sur lesMySQL client dans le répertoireclient-ssl:

nano ~/client-ssl/client-cert.pem

Collez le contenu de votre presse-papiers. Enregistrez et fermez le fichier.

Enfin, affichez le contenu du fichier de clé client sur lesMySQL server:

sudo cat /var/lib/mysql/client-key.pem
Output-----BEGIN RSA PRIVATE KEY-----

. . .

-----END RSA PRIVATE KEY-----

Copiez le contenu affiché, y compris la première et la dernière ligne, dans votre presse-papiers.

Sur lesMySQL client, ouvrez un fichier du même nom dans le répertoireclient-ssl:

nano ~/client-ssl/client-key.pem

Collez le contenu de votre presse-papiers. Enregistrez et fermez le fichier.

La machine cliente doit maintenant avoir toutes les informations d'identification requises pour accéder au serveur MySQL. Ensuite, nous devons modifier notre utilisateur distant.

Exiger un certificat d'une autorité de certification approuvée pour l'utilisateur distant

Actuellement, le client MySQL dispose des fichiers pour présenter son certificat au serveur lors de la connexion. Cependant, le serveur n'est toujours pas configuré pour exiger le certificat client d'une autorité de certification approuvée.

Pour changer cela, connectez-vous à nouveau au compte racine MySQL sur lesMySQL server:

mysql -u root -p

Ensuite, nous devons modifier les exigences pour notre utilisateur distant. Au lieu de la clauseREQUIRE SSL, nous devons appliquer la clauseREQUIRE X509. Cela implique toute la sécurité fournie par l'exigence précédente, mais impose également au client qui se connecte de présenter un certificat signé par une autorité de certification approuvée par le serveur MySQL.

Pour ajuster les exigences utilisateur, utilisez la commandeALTER USER:

ALTER USER 'remote_user'@'mysql_client_IP' REQUIRE X509;

Effacez les modifications pour vous assurer qu'elles sont appliquées immédiatement:

FLUSH PRIVILEGES;

Quittez le shell lorsque vous avez terminé:

exit

Ensuite, nous pouvons tester pour nous assurer que nous pouvons toujours nous connecter.

Test de validation du certificat lors de la connexion

Le moment est venu de vérifier si nous pouvons valider les deux parties lorsque nous nous connectons.

Sur lesMySQL client, essayez d'abord de vous connecter sans fournir les certificats clients:

mysql -u remote_user -p -h mysql_server_IP
OutputERROR 1045 (28000): Access denied for user 'remote_user'@'mysql_client_IP' (using password: YES)

Sans fournir le certificat client, le serveur refuse la connexion.

Maintenant, connectez-vous en utilisant les options--ssl-ca,--ssl-cert et--ssl-key pour pointer vers les fichiers appropriés dans le répertoire~/client-ssl:

mysql -u remote_user -p -h mysql_server_IP --ssl-ca=~/client-ssl/ca.pem --ssl-cert=~/client-ssl/client-cert.pem --ssl-key=~/client-ssl/client-key.pem

Vous devriez être connecté avec succès. Reconnectez-vous pour retrouver l'accès à votre session shell:

exit

Maintenant que nous avons confirmé l’accès au serveur, nous pouvons implémenter une petite amélioration de la convivialité.

Créer un fichier de configuration client MySQL

Pour éviter de devoir spécifier les fichiers de certificat chaque fois que vous vous connectez, nous pouvons créer un simple fichier de configuration client MySQL.

Dans votre répertoire personnel sur la machineMySQL client, créez un fichier caché appelé~/.my.cnf:

nano ~/.my.cnf

En haut du fichier, créez une section appelée[client]. En dessous, nous pouvons définir les optionsssl-ca,ssl-cert etssl-key pour qu'elles pointent vers les fichiers que nous avons copiés à partir du serveur. Ça devrait ressembler à ça:

~/.my.cnf

[client]
ssl-ca = ~/client-ssl/ca.pem
ssl-cert = ~/client-ssl/client-cert.pem
ssl-key = ~/client-ssl/client-key.pem

L'optionssl-ca indique au client de vérifier que le certificat présenté par le serveur MySQL est signé par l'autorité de certification que nous avons désignée. Cela permet au client d’avoir confiance qu’il se connecte à un serveur MySQL sécurisé.

Les optionsssl-cert etssl-key pointent vers les fichiers requis pour prouver au serveur MySQL qu'il possède également un certificat qui a été signé par la même autorité de certification. Nous en avons besoin si nous voulons que le serveur MySQL vérifie que le client a également été approuvé par l'autorité de certification.

Enregistrez et fermez le fichier lorsque vous avez terminé.

Maintenant, vous pouvez vous connecter au serveur MySQL sans ajouter les options--ssl-ca,--ssl-cert et--ssl-key sur la ligne de commande:

mysql -u remote_user -p -h mysql_server_ip

Votre client et votre serveur doivent maintenant présenter des certificats lors de la négociation de la connexion. Chaque partie est configurée pour vérifier le certificat distant par rapport au certificat de l'autorité de certification qu'il possède localement.

Conclusion

Votre serveur MySQL devrait maintenant être configuré pour exiger des connexions sécurisées pour les clients distants. En outre, si vous avez suivi les étapes pour valider les connexions à l'aide de l'autorité de certification, les deux côtés ont établi un niveau de confiance selon lequel la partie distante est légitime.

Related