Comment rendre Mysql accessible depuis l’extérieur ? …

Le 26 décembre 2008 par John JEAN Laisser un commentaire »

Logo Mysql … Et si possible avec une gestion des accès utilisateurs cohérente. Voici une question qui revient souvent et pour laquelle certains webmasters sont un peu perdus. En effet, pour des raisons de sécurité évidente, Mysql n’autorise par défaut pas les connexions distantes. Ce billet s’adresse donc aux personnes ayant plusieurs machines / serveurs à disposition et souhaitant rendre Mysql contactable à distance sur le 3306. Le but est donc d’avoir un serveur Mysql central, sur lequel plusieurs autres serveurs pourront venir chercher les informations dont ils ont besoin. Plusieurs raisons: méthode de sécurisation (!), authentification unifiée, besoin d’un serveur robuste pour un site, etc…

Bien, donc imaginons que vous avez développé www.example.com. Vous avez aussi historiquement une dizaine de sites, example1.com, example2.com, example3.com et ainsi de suite. Vous souhaitez pouvoir gérer les accès aux répertoires /admin/ par le biais d’un login unifié par Mysql; Comprendre: déployer le même htaccess partout qui permet de checker dans une db si tel utilisateur a accès à tel site ou pas.  Au delà du fait que vous allez avoir besoin de mod_auth_mysql, il vous faut un serveur Mysql dans lequel l’ensemble des htaccess iront taper pour savoir si les utilisateurs peuvent se loger ou non. Autre exemple, example.com prend de l’ampleur, les requêtes SQL sont déjà optimisées mais elles mettent cependant le serveur sur les rotules tellement il y a de visiteurs sur le site, même chose, besoin d’un serveur Mysql à distance (je n’entend pas troller ici sur l’affinage des requêtes, l’optimisation hardware, etc ;) ).

Donc, comment permettons nous à Mysql d’écouter à distance ? C’est en réalité assez simple, mais comme ce n’est pas si évident que cela de retrouver sur google comment faire dans une seul document, je fais ce billet qui tente de condenser l’information.

La première chose à faire est d’aller modifier votre /etc/mysql/my.cnf afin de commenter la ligne suivante:

bind-address           = 127.0.0.1 devient donc
#bind-address           = 127.0.0.1

Vous devez ensuite, comme d’habitude, redémarrer mysql:

[john@coincoin:~]# /etc/init.d/mysql restart
Stopping MySQL database server: mysqld.
Starting MySQL database server: mysqld.

Vous venez d’enlever l’écoute locale du serveur Mysql. Désormais, vous pouvez créer vos utilisateurs. Et c’est ici qu’il faut être vigilant, si je reprend l’exemple d’avant (example2.com, example3.com, etc), potentiellement nous avons besoin qu’un utilisateur Mysql soit crée afin d’accéder aux informations. Mais ce n’est pas parce que 10 serveurs peuvent avoir besoin de contacter notre serveur Mysql que cet utilisateur doit avoir les droits %. Il convient de gérer précisement les autorisations de chaque utilisateur. Même si la solution de facilité souvent employée par les webmasters est de mettre en droit « % » (le % est une wildcard qui permet à l’utilisateur Mysql de se connecter depuis n’importe où), en cas de faille de type Injection Mysql, c’est la porte ouverte à n’importe qui pour collecter les informations (alors que de devoir faire relai sur le serveur qui possède la faille est beaucoup plus rébarbatif).

Donc pour résumer, ce qu’il ne faut pas faire:

CREATE USER 'example'@'%' IDENTIFIED BY '****';
GRANT USAGE ON * . * TO 'example'@'%' IDENTIFIED BY '****' WITH MAX_QUERIES_PER_HOUR 0
MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0 ;
CREATE DATABASE IF NOT EXISTS `example` ;
GRANT ALL PRIVILEGES ON `example` . * TO 'example'@'%';

Là, vous créez un utilisateur qui peut se connecter de n’importe ou. Par contre si example.com est hébergé sur 80.80.80.80, voici ce qu’il convient mieux de faire:

CREATE USER 'example'@'88.80.80.80' IDENTIFIED BY '****';
GRANT USAGE ON * . * TO 'example'@'88.80.80.80' IDENTIFIED BY '****' WITH MAX_QUERIES_PER_HOUR
0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0 ;
CREATE DATABASE IF NOT EXISTS `example` ;
GRANT ALL PRIVILEGES ON `example` . * TO 'example'@'88.80.80.80;

Dans le cas où vous hébergez un site sur le serveur Mysql directement, et que vous n’avez pas besoin de contacter à distance pour l’utilisateur Mysql, vous pouvez mettre directement localhost, autant être logique. Et si d’aventure, vous n’avez pas envie de granter les accès immédiatement:

CREATE USER 'example'@'localhost' IDENTIFIED BY '****';
GRANT USAGE ON * . * TO 'example'@'localhost' IDENTIFIED BY '****' WITH MAX_QUERIES_PER_HOUR 0
MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0 ;

Malgré tout cela, Ca ne marche pas ?!
Il n’est pas impossible que IPTABLES rejette les connexions entrantes, vous devez donc autoriser les serveurs distants à vous contacter, là encore c’est comme le % ou l’IP directement, il y a deux écoles. Soit c’est Open-bar:

/sbin/iptables -A INPUT -i eth0 -p tcp --destination-port 3306 -j ACCEPT

Soit on met l’adresse IP du serveur qui peut venir taper sur le 3306:

/sbin/iptables -A INPUT -i eth0 -s 80.80.80.80 -p tcp --destination-port 3306 -j ACCEPT

N.B:  Rendre vos bases de données accessibles depuis l’extérieur n’est pas synonyme de faiblesse de sécurité si les choses sont bien faites. Pour résumer:

  • On commente bind-adress dans /etc/mysql/my.cnf
  • On crée les utilisateurs avec les droits NECESSAIRES, pas plus. Autrement dit, on autorise depuis l’adresse IP d’où ils contactent et jamais depuis partout (%). Si l’utilisateur est local, on ne l’authentifie que depuis localhost.
  • On crée des règles iptables pour autoriser les serveurs qui ont le droit de rentrer, pas pour tout le monde (-s 80.80.80.80).

Bonnes bidouilles.

Laisser un commentaire