Deux clients OpenVPN sur une seule passerelle Linux : répartir la politique
Les deux tunnels peuvent monter alors que chaque client en utilise un. Décidez par source, donnez à chaque groupe sa propre table, puis autorisez et traduisez sur l’appareil choisi.
Deux démons OpenVPN peuvent tous deux signaler un tunnel établi alors que la passerelle envoie chaque client par le même. Rien dans la poignée de main ne décide quel tunnel un client utilise ; c’est le noyau qui décide, paquet par paquet, en parcourant les règles de politique puis la table que chaque règle nomme. Vu ainsi, la configuration cesse de porter sur les options d’OpenVPN et devient une matrice de routage à deux propriétaires.
C’est le noyau qui décide, pas le démon
Un paquet transféré arrive sur l’interface LAN et le code de routage évalue la liste des règles par ordre de priorité. La première règle dont le sélecteur correspond nomme une table, et les routes de cette table choisissent l’appareil de sortie. Si la table n’a aucune route correspondante, la recherche passe à la règle suivante, et c’est ce détail qui fait échouer une configuration à moitié faite discrètement plutôt que bruyamment.
Le processus du tunnel n’a pas voix au chapitre dans ce parcours. Il crée une interface et peut installer des routes, mais qu’un paquet d’un client donné entre dans cette interface dépend entièrement de la table à laquelle il a été envoyé. Deux tunnels avec des routes importées identiques se font donc concurrence, et le dernier qui écrit gagne pour tout le monde. C’est pourquoi une configuration peut sembler équilibrée dans les fichiers et envoyer malgré tout tous les clients par un seul démon.
Donnez à chaque instance son propre ensemble de ressources
Commencez par les noms, car des noms réutilisés sont la façon dont les deux instances finissent par partager un état par accident. Attribuez des périphériques de tunnel distincts, des fichiers de configuration distincts, des identifiants distincts et des unités de service distinctes. Notez le point de terminaison extérieur et l’adresse du tunnel de chaque instance dans la même table que la matrice de politique, afin qu’une modification ultérieure ait un seul endroit où regarder.
dev tun-office
route-nopull
pull-filter ignore "redirect-gateway"
dev tun-lab
route-nopull
route-nopull garde les routes poussées par un serveur hors de la table locale, ce qui est exactement ce que vous voulez quand les tables de politique sont censées être explicites. Savoir si un serveur donné pousse aussi une option redirect-gateway, et si votre version de client prend en charge la forme avec filtre, mérite une vérification dans le manuel plutôt qu’une supposition.
Écrivez la matrice : source, table, appareil
Pour chaque groupe de clients, ajoutez une règle qui sélectionne une table par adresse source, puis placez le chemin voulu dans cette table :
ip rule add from 10.8.1.0/24 lookup 100 priority 1000
ip rule add from 10.9.1.0/24 lookup 200 priority 1000
ip route add default dev tun-office table 100
ip route add default dev tun-lab table 200
La table a besoin des routes de destination que le groupe devrait avoir, plus les exceptions locales ou de gestion qui gardent la passerelle utilisable. Une table qui ne contient qu’une route par défaut est une politique de tunnel complet pour ce groupe, ce qui peut être exactement juste, mais cela devrait être une décision et non un oubli.
Le transport du tunnel lui-même n’est pas dans un groupe de clients
Les paquets chiffrés de chaque démon naissent sur la passerelle elle-même, adressés au pair extérieur. Une règle qui ne correspond qu’à un préfixe source de client laisse ces paquets tranquilles, et c’est pourquoi les règles limitées à la source sont plus sûres que les règles qui correspondent à tout. Une règle sans sélecteur peut capturer le transport du tunnel lui-même et le renvoyer par un tunnel, et la connexion échoue alors d’une manière qui ressemble à un problème de fournisseur.
Gardez la session de gestion locale et le chemin de la couche inférieure explicitement hors des tables de politique. Écrivez ces exceptions à côté de la matrice ; elles font partie de la conception, pas d’un contournement à redécouvrir pendant un incident.
Choisir un chemin ne l’autorise pas
L’autorisation de transfert est une deuxième décision prise plus loin dans le chemin. Une règle de pare-feu qui accepte les paquets sortant par le second tunnel ne fait pas choisir celui-ci par le code de routage, et une table correcte n’accorde pas l’autorisation de transférer. Les deux doivent exister, et un test qui n’en prouve qu’un vous induira en erreur sur l’autre. Quand un groupe fonctionne et l’autre non, vérifiez ces deux étapes séparément au lieu de réécrire les tables.
La traduction de source est une troisième décision, et elle devrait être limitée au groupe source et au périphérique de tunnel qui le porte réellement. Ajoutez une chaîne dédiée pour les deux instances au lieu de vider la chaîne postrouting, car des services sans rapport peuvent y posséder des entrées et un vidage les retire silencieusement.
Ce qui se passe quand un tunnel tombe
Décidez le comportement en cas de panne à l’avance. Quand une table de tunnel perd sa route, la recherche bascule vers la règle suivante, et le trafic du groupe continue par l’autre tunnel ou par le lien montant ordinaire sans aucune erreur. Si cela n’est pas acceptable, ajoutez une règle terminale avec un numéro de priorité plus bas qui renvoie un résultat inatteignable pour cette source, afin que la perte soit visible au lieu d’être absorbée.
Envoyez une requête nouvelle depuis chaque groupe source et notez quatre faits : la table sélectionnée, le périphérique de sortie, la source traduite et si la réponse est revenue par le même chemin. Puis coupez un tunnel et recommencez. Deux périphériques TUN dans une liste d’interfaces prouvent que les deux démons ont démarré ; ils ne disent rien sur celui qu’un client donné a utilisé. La seconde exécution, avec un tunnel en moins, est celle qui montre si votre règle de repli fait ce que vous vouliez.