Si vous lisez cet article, c’est probablement parce que vous vous posez des questions sur la possibilité de connecter une application à sa base de données au travers d’un lien Internet non chiffré.

TL;DR : non vous ne devez pas faire transiter le protocole de base de données (exemple : MySQL sur le port 3306) en clair sur Internet, pour des raisons de sécurité et de performances. Utilisez à la place un système de webservices REST via HTTPS spécifiquement développé pour, ou à défaut, MySQL avec support SSL actif. Enfin, vous pouvez relocaliser les deux applications sur le même réseau pour des connexions locales et privées.

Sommaire

Description du cas de figure type

Dans le monde de l’entreprise ou en informatique de gestion, on utilise couramment des applications qui exploitent une base de données. Ces applications n’étant pas nécessairement interopérables entre elles, les faire communiquer peut être compliqué. La solution de facilité consiste donc à connecter une seconde application distante à une base de données existante. Cela ne poserait pas de soucis si les deux applications tournaient sur le même réseau local, mais à distance via un lien Internet en clair c’est une autre histoire.

Par exemple, on peut envisager une boutique en ligne (Prestashop, Magento, …) comme application A utilisant une base de données MySQL/MariaDB, et un ERP et ses connecteurs (Cegid, Sage, Odoo, …) comme application B. On peut aisément comprendre que l’entreprise utilisatrice de ces solutions a besoin de les faire communiquer ensemble, par exemple pour synchroniser les données client ou les commandes entrantes avec un système de gestion des stocks. Et pour ce faire, une connexion directe à la base de données est très tentant…

A noter que les exemples de cet article parle évoque spécifiquement la base de données MySQL/MariaDB, mais les arguments sont valables pour toute connexion à un SGBD.

Nous allons commencer par passer en revue les raisons de ne pas succomber à la solution de facilité, pour ensuite traiter les différentes options possibles.

Pourquoi ne pas faire passer le trafic MySQL sur internet

La sécurité des échanges

La première raison de ne pas faire passer le protocole de base de données en clair via Internet est sécuritaire. Une règle d’or est : on ne doit pas faire transiter des données critiques en clair sur un réseau public.

Les risques possibles sont les suivants : fuite de données sensibles ou personnelles vers des personnes malveillantes, intrusion dans le SI et action malveillante de type corruption ou effacement des données de la base, non compatibilité avec les bonnes pratiques encouragées juridiquement par la RGPD.

On peut citer la fiche n°10 de la CNIL qui vulgarise la loi « Informatique et libertés » :

[…] la transmission via Internet de données nominatives comporte, compte tenu de l’absence générale de confidentialité du réseau Internet, des risques importants de divulgation de ces données et d’intrusion dans les systèmes informatiques internes par exploitation de ces données frauduleusement acquises. […] Concernant la confidentialité d’une communication, il est possible de chiffrer directement les données ou le canal de transmission lors d’un envoi via un réseau.

Et les requêtes de base de données sont critiques, car elles peuvent contenir des informations nominatives, des mots de passe en clair même s’ils sont stockés chiffré (exemple : utilisation de la fonction MySQL PASSWORD() ), et parce qu’elles suffisent à faire de la réplication de base de données MySQL.

Pour mieux comprendre, on pourrait donner différentes analogies plus ou moins équivalentes :

  • Imaginez-vous prononcer haut et fort votre code confidentiel de carte bancaire au supermarché ? Non car tout le monde peut l’entendre et chercher à l’exploiter, même si tout le monde ne le fait pas, c’est évident.
  • Imaginez-vous faire un achat sur un eCommerce dans lequel le tunnel de paiement de la banque n’est pas sécurisé SSL ? Non, la présence du petit cadenas vert dans le navigateur a toujours été décrite comme obligatoire dans ce cas. Parce qu’il certifie que le serveur web est bien celui de la boutique (authentification de l’identité), et qu’il montre que les échanges transitent sur le réseau de manière chiffrée sans qu’une tierce personne ne puisse y accéder.
  • Utilisez-vous encore le protocole Telnet pour administrer vos serveurs ? Non, parce qu’il existe une alternative bien meilleur à tous points de vue qui s’appelle SSH, et qu’il faudrait être fou pour encore utiliser cette antiquité en 2020.

Alors, je vous repose la question : faites-vous transiter le protocole MySQL sur le port 3306 en clair sur le réseau ? Voici en tout cas la réponse issue du manuel officiel de MySQL :

Do not transmit plain (unencrypted) data over the Internet. This information is accessible to everyone who has the time and ability to intercept it and use it for their own purposes. Instead, use an encrypted protocol such as SSL or SSH. MySQL supports internal SSL connections. Another technique is to use SSH port-forwarding to create an encrypted (and compressed) tunnel for the communication.

Dans la langue de Molière, voici ce que ça donne :

Ne transmettez pas de données en clair (non chiffrées) sur Internet. Les informations en clair sont accessibles à quiconque ayant le temps et la capacité de les intercepter et de les utiliser pour leur propre intérêt. A la place, utilisez un protocole chiffré comme SSL ou SSL. MySQL supporte nativement les connexions SSL. Une alternative est de mettre en place le port-forwarding SSH pour créer un tunnel chiffré (et compressé) pour la communication.

Pour nuancer cet argument sécuritaire, je peux dire que le risque de faire transiter du trafic BDD non chiffré sur internet est moins grand que celui d’utiliser HTTP (sans chiffrement SSL), tout simplement parce que les serveurs concernés ont généralement la même adresse IP et une connexion Internet « sûre » (pas comme un wifi public par exemple).

Néanmoins, l’argument de la sécurité suffit à invalider la pratique des requêtes MySQL en clair sur Internet.

La restriction des droits utilisateurs

Quand on connecte une application B sur la base de données de l’application A, on lui affecte généralement des droits très larges en lecture et modification de l’ensemble de la base de données. C’est donc toute la gestion des droits utilisateurs qui est court-circuitée.

L’application A (exemple : la boutique) est généralement proprement conçue, et implémente une vraie gestion des droits et des privilèges selon le niveau de l’utilisateur. Mais le connecteur de l’application B, conçu uniquement dans un but d’accès aux données, n’implémente pas la même gestion des utilisateurs, et pioche donc dans la base de données sans aucune restriction.

Imaginez l’analogie suivante : vous installez dans vos locaux une porte d’entrée à accès biométrique, mais vous laissez les clés de la porte arrière à la société d’entretien sans aucun contrôle d’accès. Beaucoup d’efforts réduits à néant, n’est-ce pas ? La sécurité du système dépend de son point faible, c’est valable en sécurité physique comme en sécurité informatique.

Un risque possible serait qu’un programme malveillant se loge sur le serveur de l’application B et utilise les accès à la base de données pour effectuer des opérations malveillantes, juste parce que c’est possible. Exemple avec l’attaque « Meow » qui vise les bases de données.

Encore une fois, selon la fiche de la CNIL :

Chaque utilisateur ne devant accéder qu’aux données strictement nécessaires à l’exercice de son activité professionnelle, des profils d’habilitation doivent être définis pour déterminer les types de données accessibles à une catégorie d’utilisateur.

En soit, l’utilisation de droits utilisateurs privilégiés n’est pas recommandée pour des opérations courantes en production.

La performance

Il y a quelques années, j’avais envisagé de séparer le serveur de base de données de son serveur d’application sur des réseaux différents, pour des raisons juridiques. Ils auraient alors communiqué via Internet par un tunnel chiffré, évidemment, et même compressé.

Je me souviens de la réaction de l’ingénieur commercial du cloud provider pressenti jusqu’alors pour héberger la base de données : « si vous mettez en place ce système, cela ne fonctionnera pas, votre application sera lente et inutilisable ». J’ai testé quand même via OpenVPN sur une ligne SDSL. Bilan : l’application était inutilisable à cause de la latence de la connexion réseau entre chaque requête MySQL.

Et, entre nous, c’était prévisible.

L’argument de la performance suffit donc à invalider la pratique des requêtes MySQL (en clair ou chiffré) sur Internet. Si la performance n’est pas un critère, n’importe quelle alternative ci-dessous sera préférable.

Les alternatives pour interconnecter deux applications sur la même base de données

Relocaliser les deux applications sur le même réseau local

Le trafic MySQL en clair sur Internet est un problème. Alors faisons transiter le trafic MySQL en clair sur un réseau local ! Problem solved. En effet, dans la plupart des cas, le serveur d’application et le serveur de base de données sont sur le même réseau local privé, parfois le même serveur.

Le réseau local peut être :

  • l’interface réseau local (IP 127.0.0.1, interface lo sous Linux) ;
  • un switch virtuel intégré dans une solution de virtualisation (VMWare, Hyper-V, KVM …) ;
  • un switch physique configuré par l’hébergeur, comme par exemple OVH qui le propose avec son système vRack.

L’utilisation d’un webservice REST ou SOAP

Pour des opérations d’accès à des données par une application tierce externe, le webservice est recommandé. C’est un système pensé pour l’interopérabilité, qui implémente aisément le chiffrement (protocole HTTPS) et la compression (compression gzip du standard HTTP) et le support des droits utilisateurs (via un petit contrôleur prévu à cet effet).

A titre d’exemple, le webservice intégré à Prestashop parle très bien de lui-même :

PrestaShop enables merchants to give third-party tools access to their shop’s database through a CRUD API, otherwise called a web service.

Ce qui donne en français :

PrestaShop permet aux marchands de donner à des outils tiers l’accès à la base de données de leur boutique via une API CRUD, également appelé un webservice.

Si, par exemple, le webservice standard de PrestaShop ne donne pas satisfaction, rien n’interdit de développer un petit webservice spécifique qui réponde mieux au besoin. Les architectures orientées SOA et les webservices ont déjà fait leurs preuves au cours des 10 dernières années. Cela étant je connais des connecteurs boutique-ERP qui exploitent le webservice Prestashop avec succès pour des volumes de données importants.

J’ai moi-même opté pour ce fonctionnement sur un projet de synchronisation de stocks entre la base Oracle d’un ERP dans les locaux d’une entreprise, et un serveur web hébergé dans un datacenter. Le fonctionnement est rustique mais efficace :

  • Un script BASH lance une requête dans la base Oracle qui consiste à dumper deux colonnes d’une table directement au format CSV séparé par des virgules de type <code produit>;<quantité produit> . Aucun problème de restriction des droits puisqu’on a filtré les informations qui nous intéressent.
  • Le serveur compresse le dump CSV puis l’envoie en bloc au serveur web via HTTPS.
  • Le serveur web ouvre le fichier CSV (avec tous les contrôles de cohérence nécessaires) puis l’analyse ligne par ligne. On compare avec la BDD du site web (un simple SELECT) et en cas de valeur différente on met à jour (un simple UPDATE).

Ce système fonctionne plusieurs fois par heure et permet la synchronisation de stocks de 31 000 produits en 3 min 32 sec. Qui dit mieux ? Si le serveur Oracle disposait d’une colonne « last modified » pour la valeur de stock, on pourrait effectivement faire mieux…

Utiliser le support SSL natif de MySQL

La documentation MySQL citée plus haut préconise d’utiliser le support SSL natif qui est prévu pour sécuriser les connexions distantes via internet. Au lieu d’un simple identifiant et mot de passe, on doit en plus fournir au client MySQL des certificats de chiffrement SSL.

Les serveurs MySQL et MariaDB le supportent. Tous les langages de programmation qui implémentent l’accès à une base MySQL le supportent (exemple ici en .NET). Tous les cloud providers qui proposent de la base de données à la demande le supportent (exemple ici avec Google Cloud SQL). Je crois sincèrement que MySQL+SSL est en train de s’imposser comme un standard, un peu comme HTTPS par rapport à HTTP.

Que dit la CNIL dans sa fiche à ce sujet ? Que c’est tout bon :

Si les document transmis par voie électronique n’est pas chiffré, il sera alors indispensable de chiffrer le canal de transmission. A cet effet, l’utilisation du protocole SSL/TLS garantit l’authentification des serveurs (ainsi qu’éventuellement celle des clients) et la confidentialité des communications.

Banco, c’est une bonne solution. On ne s’affranchit pas des inconvénients liés à la latence du réseau, mais c’est déjà pas mal du tout.

Utiliser un VPN pour faire transiter le trafic de base de données MySQL

Les VPN sont formidables, ils fournissent une interface réseau virtuelle qui chiffre tout le trafic qui y passe de manière transparente. Prenez une application non chiffrée (Telnet, FTP, HTTP, …) au travers d’un VPN, et le trafic devient automatiquement chiffré. Les éditeurs de logiciels peuvent ainsi proposer le chiffrement des connexions sans modifier une seule ligne de leur logiciel. Les grands groupes peuvent ne plus faire confiance en les protocoles qu’ils utilisent car ils ajoutent une surcouche de chiffrement.

De plus il existe d’excellents VPN, comme IPSec réputé mais à la mise en œuvre complexe, SSH bien pratique mais basé sur TCP, Wireguard qui représente l’avenir mais qui n’est pas encore compatible avec grand chose, et OpenVPN qui se base sur SSL.

Seulement voilà, les VPN nécessitent une mise en œuvre qui peut être technique avec de vraies connaissances en routage IP, et un suivi dans le temps avec une maintenance. Sinon, c’est un point de défaillance supplémentaire qui ne manquera pas de défaillir.

Voilà pourquoi Telnet n’a pas été supplanté par Telnet-over-VPN mais par SSH. Et FTP non pas par FTP-over-VPN mais par FTPS (avec SSL). Et HTTP non pas par HTTP-over-VPN mais par HTTPS (avec SSL).

Alors oui, on pourrait bien configurer un VPN OpenVPN basé sur SSL pour sécuriser du trafic MySQL, c’est même validé par la citation de la CNIL ci-dessus. Mais à ce compte-là, pourquoi ne pas utiliser le support SSL proposé en standard dans MySQL et préconisé dans la documentation ? Parfois le plus simple, le plus standard est le mieux.

Mettre en place un filtrage d’accès par IP dans le pare-feu

Quand on veut ouvrir un port à l’extérieur, et qu’on n’est pas trop sûrs de la robustesse du service qui répond derrière, c’est une bonne idée de mettre en place un filtrage IP. Seules les adresses IP amies auront la possibilité de se connecter au port.

Cette mesure permet dans une certaine mesure de s’assurer de l’identité du serveur qui se connecte. Par contre, cela ne suffit pas d’un point de vue sécuritaire car les échanges demeurent non-chiffrés.

Cela n’est pas nécessaire dans le cas de l’utilisation de SSL (l’identité du serveur distant est déjà authentifiée) mais tout de même conseillé. L’excès de prudence ne nuit pas pour une telle mesure très simple à mettre en œuvre.

Conclusion

Si, après la lecture de cet article vous persistez à faire transiter le trafic de la BDD en clair sur Internet, et bien prenez vos responsabilités !