Intégrer RADIUS à OpenVPN : greffon ou crochet de script ?
L’ancien greffon RADIUS est lié à la version du serveur pour laquelle il a été compilé. Le crochet auth-user-pass-verify le remplace, mais déplace la confiance vers votre script.
Le greffon est encore recommandé dans des fils plus anciens que les versions actuelles, et il échoue au chargement sur un serveur compilé hier. Ce n’est pas une erreur de configuration que l’on corrige avec un chemin. Le greffon et le crochet de script résolvent le même problème à des couches différentes, et passer de l’un à l’autre change ce qu’il faut installer, ce qui s’exécute avec les privilèges du serveur et ce qu’un échec de connexion vous dit réellement.
Le mythe : le greffon est la voie prise en charge
Un greffon est un objet partagé chargé dans le processus OpenVPN, il doit donc correspondre à l’interface que ce processus expose. Les versions changent, l’empaquetage change, et une bibliothèque compilée pour une interface plus ancienne refuse simplement de se charger. Rien dans la configuration du serveur ne peut combler cet écart, c’est pourquoi le conseil « installez juste radiusplugin » se termine par un serveur qui ne démarre pas.
Le crochet de script se place plutôt hors du processus. OpenVPN exécute un programme, lui remet les identifiants et lit un verdict. Ce découplage est ce qui lui permet de survivre aux mises à niveau, et c’est aussi ce qui en fait votre responsabilité d’une manière que le greffon n’a jamais eue.
Aucune des deux approches n’est plus sûre par construction. L’une exécute du code étranger dans le démon ; l’autre exécute votre code à côté, avec les identifiants en main. La bonne question est laquelle de ces deux risques vous pouvez réellement exploiter.
Ce que le greffon liait ensemble
Le greffon portait son propre fichier de configuration avec l’hôte RADIUS, le secret partagé, le nombre de tentatives et le délai, et la configuration du serveur y faisait référence par une seule ligne. Le traitement des identifiants restait dans le processus serveur, ce qui signifiait que le mot de passe ne franchissait jamais une frontière de processus que l’administrateur devait sécuriser.
Le coût était le couplage. Chaque mise à niveau d’OpenVPN risquait une interface incompatible, et chaque distribution qui reconstruisait le paquet risquait de produire une bibliothèque qui ne correspondait plus. Quand cela arrive, la panne est bruyante et immédiate, et c’est la seule miséricorde de la conception.
Si un tel greffon se charge encore sur votre version, il peut être la plus petite surface opérationnelle. Confirmez l’interface pour laquelle il a été compilé, gardez-le épinglé à la version que vous avez testée, et traitez toute mise à niveau comme un changement exigeant un test de connexion complet, non comme une mise à jour de paquet de routine.
À quoi le crochet de script fait réellement confiance
Le crochet se configure avec auth-user-pass-verify et un mécanisme de remise : variables d’environnement ou fichier temporaire. Avec la forme environnement, OpenVPN exige script-security 3, le niveau documenté qui autorise l’exposition du mot de passe aux scripts. Ce niveau est un affaiblissement délibéré de la valeur par défaut, et il doit être traité comme une autorisation assortie d’une justification.
Tout ce que le script touche hérite de cette confiance. Il doit appartenir à root, ne pas être inscriptible par le groupe ni par les autres, être référencé par un chemin absolu et être exempt de tout endroit où une valeur non fiable atteint un shell. Mettez chaque variable entre guillemets, rejetez les caractères inattendus et ne construisez jamais une commande à partir du nom d’utilisateur fourni. Un script qui s’exécute en root à chaque tentative de connexion mérite une revue précisément pour ces quatre propriétés.
ls -l /usr/local/sbin/radius-auth.sh
stat -c '%U %a' /usr/local/sbin/radius-auth.sh
La forme de remise par fichier évite le problème d’héritage de l’environnement et remet les identifiants au script via un fichier temporaire aux permissions restreintes. Si votre client le prend en charge, c’est généralement la meilleure valeur par défaut, même si elle ajoute un objet de plus à nettoyer en cas d’échec.
Les codes de sortie décident si vous échouez en ouvert
Le statut de sortie du script est le verdict : zéro accepte, non-zéro rejette. Le schéma qui pose problème est un script shell qui n’accepte que lorsque la réponse RADIUS contient un jeton d’acceptation précis et renvoie un échec pour tout le reste, car cela fusionne trois événements différents en une seule réponse. Un mauvais mot de passe, un serveur injoignable et une réponse malformée deviennent tous le même rejet.
Séparez ces cas dans le script même si le crochet ne peut renvoyer qu’accepte ou rejette. Journalisez le résultat du backend séparément, alertez sur les délais et les erreurs de transport, et rendez évident dans la supervision le moment où l’authentification échoue parce que le service est en panne et non parce que les utilisateurs se trompent de frappe.
Deux habitudes gardent le reste sain. Si RADIUS est l’autorité, il devrait être le seul endroit où un mot de passe est vérifié, car une table fantôme crée deux réponses à la même question et la seconde est une surface d’attaque que personne ne surveille. Et rappelez-vous que le crochet est rappelé à chaque nouvelle tentative, donc un script lent avec un client impatient devient un amplificateur de devinettes de mots de passe, sauf à ajouter un délai ou une politique côté RADIUS.
Ce que vous perdez quand le certificat disparaît
Beaucoup de déploiements de cette forme désactivent entièrement la vérification du certificat client, laissant un nom d’utilisateur et un mot de passe comme toute la revendication du client. Ce qui disparaît avec ce réglage, c’est l’identité fondée sur certificat. Le canal reste chiffré, mais la seule chose qui nomme le client est le verdict RADIUS. Tout ce qui, en aval, s’appuyait sur le sujet d’un certificat doit désormais s’appuyer sur le nom d’utilisateur.
Gardez la protection du canal de contrôle pour qu’un pair non authentifié ne puisse pas sonder ni inonder la poignée de main, et utilisez username-as-common-name quand la configuration par utilisateur dépend du nom commun. Les passerelles gérées résolvent souvent cela autrement, en terminant l’authentification par certificat sur une passerelle qui parle EAP-TLS à RADIUS, auquel cas aucune de ces directives serveur ne s’applique. Copiez le modèle que documente votre propre plateforme, pas celui d’un produit voisin. Les directives qui comptent diffèrent assez pour que les mélanger produise une configuration qui s’analyse puis n’authentifie personne.