Vous tapez le bon nom d’utilisateur. Le bon mot de passe. Vous le collez même depuis le gestionnaire de mots de passe, donc il est vraiment correct. Et OpenVPN répond par le message le plus froid du réseau : AUTH_FAILED.
C’est le genre d’échec qui fait perdre des heures parce qu’il est étiqueté comme un problème humain (« mauvais mot de passe ») alors qu’il s’agit souvent d’un problème système (politique, plugin, horloge, chiffrement, révocation, environnement). Traitez-le comme un incident, pas comme une histoire morale.
Ce que AUTH_FAILED signifie vraiment (et ce que ce n’est pas)
AUTH_FAILED signifie : le serveur a décidé de refuser le client pendant l’étape « authentification utilisateur » et l’a indiqué au client. C’est tout. Ce n’est pas la même chose que « votre mot de passe est mauvais ». Ce n’est même pas la preuve que le serveur a vérifié votre mot de passe.
L’authentification OpenVPN peut impliquer plusieurs couches, et différentes couches produisent des résultats clients trompeusement similaires :
- TLS identity : certificats, CA, révocation, EKU, validité liée à l’horloge, options TLS.
- User auth : fichier statique, PAM, LDAP, RADIUS, wrappers type OAuth, passerelles MFA, scripts personnalisés.
- Policy : restrictions par utilisateur, appartenance à un groupe, « pas de sessions concurrentes », règles sur l’adresse source, permissions de routage.
- Session plumbing : auth-token, renégociation, cache d’auth, overrides via
client-config-dir.
Voici la partie opérationnelle agaçante : selon la configuration, le client peut voir AUTH_FAILED même si le vrai problème était un détail TLS, un crash de plugin, un timeout du backend ou une discordance de normalisation du nom d’utilisateur.
Une seule chaîne d’erreur, de nombreux modes d’échec
OpenVPN est volontairement extensible. C’est pourquoi il survit dans des entreprises qui ont encore un mainframe et trois fournisseurs d’identité. Mais cette extensibilité signifie que la « décision » peut se produire dans un script ou un plugin en dehors du noyau d’OpenVPN. Et quand le script dit « non », le client entend « AUTH_FAILED », même si le script a dit « non parce que LDAP est down » ou « non parce que le nom d’utilisateur contient un @ et qu’on le supprime ».
Une idée paraphrasée de Werner Vogels (CTO d’Amazon) que les opérationnels répètent pour une raison : « tout échoue, tout le temps ; concevez et opérez en supposant que ça arrivera » (idée paraphrasée). AUTH_FAILED en est un parfait exemple — votre travail est de trouver quelle dépendance a failli.
Blague courte #1 : Les mots de passe sont comme le lait — tout le monde jure qu’ils sont frais jusqu’à ce qu’ils commencent à échouer en production.
Playbook de diagnostic rapide (vérifier d’abord / ensuite / après)
Voici le flux « arrêter l’hémorragie ». Il est orienté vers la réduction du temps moyen pour obtenir de la clarté, pas vers l’explication théorique. Vous pourrez faire l’archéologie plus tard.
Première étape : confirmer où l’échec se produit (TLS vs auth utilisateur)
- Augmentez la verbosité du client à 4–6. Cherchez : « TLS: Initial packet », « VERIFY OK », « Peer Connection Initiated », puis « AUTH_FAILED ».
- Si TLS ne se termine jamais, ne poursuivez pas les mots de passe. Cherchez les certificats, l’heure, les chiffrements, la chaîne CA, et l’écoute/port/firewall du serveur.
- Si TLS se termine puis AUTH_FAILED, examinez la pipeline d’authentification utilisateur : plugin, script, PAM/LDAP/RADIUS/MFA, et les vérifications de politiques côté serveur.
Deuxième étape : vérifiez les logs serveur au timestamp exact
- Trouvez la ligne de connexion pour ce client (champs communs : common-name, username, adresse réelle).
- Recherchez
AUTH_FAILED,PLUGIN_CALL,AUTH-PAM,radiusplugin,auth-user-pass-verify,client-denied. - Si vous voyez une erreur backend (échec de bind LDAP, timeout RADIUS), traitez-la comme une panne d’identité, pas comme une faute de saisie utilisateur.
Troisième étape : validez vos hypothèses sur le nom d’utilisateur, le realm et la méthode d’auth
- Le serveur attend-il
samaccountname,user@domainouDOMAIN\user? - Utilisez-vous
--auth-user-passavec un fichier de mot de passe, et contient-il des espaces de fin ? - Le MFA est-il requis ? Certaines configurations rejettent « mot de passe seul » avec AUTH_FAILED et un message de log inutile.
Quatrième étape : vérifiez la politique et l’état
- Règles de sessions concurrentes (duplicate-cn, interface management, limites de sessions).
- Cert révoqué ou nom d’utilisateur désactivé alors que les identifiants restent « corrects ».
- Overrides via client-config-dir (push par utilisateur, iroute, ou
disable).
Cinquième étape : reproduisez de manière contrôlée
- Essayez les mêmes identifiants depuis une config client connue bonne.
- Essayez un utilisateur connu bon depuis la config client qui échoue.
- Cela isole « identité » de « config client » en quelques minutes.
Faits et contexte : pourquoi l’auth OpenVPN est étonnamment complexe
Quelques faits concrets aident à expliquer pourquoi AUTH_FAILED est un attrape-tout dans le monde réel :
- OpenVPN a commencé en 2001, et ses points d’extension (scripts/plugins) ont été conçus pour de l’auth hétérogène en entreprise bien avant que le « SSO » ne devienne par défaut.
- L’authentification utilisateur/mot de passe n’est pas intrinsèque aux VPN TLS ; OpenVPN l’a ajoutée pour satisfaire les organisations qui voulaient un second facteur au-delà des certificats.
- L’intégration PAM a rendu OpenVPN « natif » sur Unix — et a aussi importé la complexité de PAM : politiques de compte, mots de passe expirés, comptes verrouillés, ordre des modules.
- Le support RADIUS est devenu une pratique courante car il centralise les décisions d’auth et le MFA, mais il introduit aussi des timeouts qui ressemblent à des mauvais mots de passe.
- Le
client-config-dird’OpenVPN est puissant : vous pouvez remplacer silencieusement des réglages par utilisateur. Ce pouvoir peut aussi casser silencieusement l’accès d’un utilisateur. - Les listes de révocation (CRL) sont difficiles à gérer opérationnellement : ce sont des fichiers, elles expirent, on les oublie. Un cert révoqué peut coexister avec des identifiants « corrects » et vous bloquer.
- La correction de l’horloge est critique pour la sécurité : les certificats et certains tokens sont limités dans le temps. Une dérive d’horloge génère des échecs d’auth qui se déguisent en problème d’identifiants.
- Le cache d’auth a évolué (auth-token, renégociation) pour réduire les invites répétées, mais une mauvaise config peut provoquer des boucles ou des échecs de « token périmé ».
- La négociation des chiffrements moderne a changé les valeurs par défaut dans OpenVPN 2.5+ (data-ciphers). Les incompatibilités peuvent mener à des déconnexions précoces que les utilisateurs interprètent comme des « problèmes d’auth ».
Triage côté client : prouver ce que vous avez envoyé
Quand quelqu’un dit « les identifiants sont corrects », il veut souvent dire « les identifiants fonctionnent ailleurs ». Ce n’est pas la même affirmation. Le client OpenVPN peut envoyer un nom d’utilisateur différent de ce que l’utilisateur pense. Ou il peut envoyer le bon nom avec un mauvais encodage. Ou le fichier de mot de passe peut contenir une nouvelle ligne, un carriage return ou un BOM.
Cherchez des preuves dans le log client (pas des impressions)
Sur le client, augmentez la verbosité et cherchez la séquence :
- Handshake TLS établi.
- Le serveur pousse des options.
- Le client invite pour nom d’utilisateur/mot de passe ou les lit depuis un fichier.
- Le serveur répond par AUTH_FAILED ou pousse un auth-token.
Si vous ne voyez pas un handshake TLS complété, ne poursuivez pas l’auth utilisateur. Si vous le voyez, le serveur est joignable et la conversation « mot de passe » a eu lieu (ou a été tentée).
Faites attention au format du nom d’utilisateur
Les déploiements OpenVPN en entreprise normalisent fréquemment les noms d’utilisateur. Certains enlèvent les realms ; certains les exigent. Certains acceptent DOMAIN\user et rejettent user@domain. Certains forcent la casse minuscule. Certains traitent « john.smith » et « John.Smith » comme des utilisateurs différents si le répertoire hérite d’un comportement legacy.
Quand vous dépannez, décidez d’une représentation canonique et testez celle-ci. Sinon vous serez « correct » de trois façons différentes et toujours faux en production.
Les fichiers d’identifiants sont piégeux
--auth-user-pass /path/to/file attend un fichier avec deux lignes : nom d’utilisateur et mot de passe. Ce fichier peut vous trahir avec :
- Des terminaisons de ligne Windows CRLF (
\r\n), créant un\rcaché dans le mot de passe. - Un espace final copié depuis un ticket.
- Un BOM UTF-8 au début de la ligne du nom d’utilisateur.
Blague courte #2 : La seule chose plus persistante qu’un mot de passe VPN expiré est un carriage return Windows qui se cache à la fin.
Triage côté serveur : prouver ce que le serveur a décidé
Les logs serveur sont la source de vérité, mais seulement si vous journalisez suffisamment et regardez au bon endroit. OpenVPN peut logger via syslog, fichier, journal systemd ou interface management. Les plugins et scripts d’auth peuvent logger ailleurs. Parfois, le seul indice est que le plugin a retourné non-zéro.
Connaissez votre mécanisme d’auth
Sur le serveur, l’auth utilisateur provient typiquement d’un des éléments suivants :
- PAM (
openvpn-plugin-auth-pam.so) : utilise la pile PAM système, peut appliquer l’expiration des mots de passe/verrouillages de compte. - Script externe (
auth-user-pass-verify) : votre script décide. S’il plante, vous obtenez AUTH_FAILED. - Plugin RADIUS : délègue au serveur RADIUS ; les timeouts et secrets partagés erronés ressemblent à des mauvais mots de passe.
- Plugin/script LDAP : fait un bind LDAP ; base DN, filtre ou paramètres TLS incorrects provoquent des rejets.
- Passerelle MFA : les flux de type Duo modifient souvent le champ mot de passe (ajoutent un code push) ou utilisent challenge/response RADIUS.
Différencier « auth rejetée » vs « auth cassée »
Une pipeline d’auth peut rejeter parce que l’utilisateur est mauvais. Elle peut aussi rejeter parce que la pipeline est cassée. Opérationnellement, ce sont des niveaux de gravité différents :
- Utilisateur mauvais : un utilisateur, échec constant, backend sain.
- Pipeline cassée : beaucoup d’utilisateurs, timeouts, erreurs de plugin, rafales de logs, pics CPU, échecs de resolver.
Soyez impitoyable sur cette distinction. Si cinq personnes échouent en même temps juste après un déploiement, ce ne sont pas cinq personnes qui ont soudainement oublié comment taper.
Tâches pratiques : commandes, sorties, décisions
Voici des vérifications pratiques que vous pouvez exécuter. Chacune inclut un extrait de sortie réaliste et la décision que vous en tirez. Utilisez-les comme un runbook, pas comme un buffet.
Task 1: Confirm the client actually reaches the server and completes TLS
cr0x@server:~$ sudo openvpn --config client.ovpn --verb 5
...
TCP/UDP: Preserving recently used remote address: [AF_INET]203.0.113.10:1194
TLS: Initial packet from [AF_INET]203.0.113.10:1194, sid=2c0e1f9d 1a2b3c4d
VERIFY OK: depth=1, CN=corp-vpn-ca
VERIFY OK: depth=0, CN=vpn-gateway-1
Control Channel: TLSv1.3, cipher TLS_AES_256_GCM_SHA384, peer certificate: 256 bit RSA
[corp-vpn] Peer Connection Initiated with [AF_INET]203.0.113.10:1194
AUTH: Received control message: AUTH_FAILED
SIGTERM[soft,auth-failure] received, process exiting
Sens : TLS a fonctionné ; l’échec se situe dans l’auth/politique utilisateur. Décision : Arrêtez de déboguer les certificats et passez aux logs/plugins d’auth serveur.
Task 2: Check server journal for auth-related lines at the failure time
cr0x@server:~$ sudo journalctl -u openvpn-server@corp -S "2025-12-27 09:10:00" -U "2025-12-27 09:15:00"
Dec 27 09:12:31 vpn1 openvpn[1842]: 198.51.100.44:51233 TLS: Username/Password authentication deferred for username 'j.smith'
Dec 27 09:12:31 vpn1 openvpn[1842]: 198.51.100.44:51233 PLUGIN_CALL: POST /usr/lib/openvpn/openvpn-plugin-auth-pam.so/PLUGIN_AUTH_USER_PASS_VERIFY status=1
Dec 27 09:12:31 vpn1 openvpn[1842]: 198.51.100.44:51233 AUTH_FAILED: user 'j.smith'
Sens : Le plugin PAM a rejeté. Décision : Valider la config PAM, l’état du compte, et si PAM retourne « expiré/verrouillé » vs « mauvais mot de passe ».
Task 3: Verify which auth mechanism the server is using
cr0x@server:~$ sudo grep -E '^(plugin|auth-user-pass-verify|client-cert-not-required|verify-client-cert|management)' /etc/openvpn/server/corp.conf
plugin /usr/lib/openvpn/openvpn-plugin-auth-pam.so login
verify-client-cert require
management 127.0.0.1 7505
Sens : Le plugin PAM est en jeu ; le certificat client est requis aussi. Décision : Déboguez PAM et vérifiez aussi la validité/révocation des certificats si les symptômes ne correspondent pas à l’auth utilisateur.
Task 4: Test PAM auth directly on the server (isolating OpenVPN)
cr0x@server:~$ sudo pamtester login j.smith authenticate
Password:
pamtester: Authentication failure
Sens : PAM rejette lui-même ; OpenVPN n’est que le messager. Décision : Vérifiez la connectivité de l’annuaire, l’ordre des modules PAM, l’expiration du mot de passe, le verrouillage de compte et la santé NSS/SSSD.
Task 5: Inspect PAM stack used by the plugin
cr0x@server:~$ sudo sed -n '1,200p' /etc/pam.d/login
auth required pam_securetty.so
auth requisite pam_nologin.so
auth include common-auth
account include common-account
session include common-session
Sens : Le plugin utilise le service « login », qui peut être plus strict que prévu (nologin, securetty). Décision : Envisagez un fichier de service PAM dédié (par ex. /etc/pam.d/openvpn) pour éviter des restrictions non liées.
Task 6: Check SSSD / directory health (common silent culprit)
cr0x@server:~$ sudo systemctl status sssd --no-pager
● sssd.service - System Security Services Daemon
Loaded: loaded (/lib/systemd/system/sssd.service; enabled)
Active: active (running) since Fri 2025-12-27 08:40:18 UTC; 32min ago
...
Sens : SSSD est up, mais cela ne garantit pas qu’il atteint LDAP. Décision : Interrogez un utilisateur et vérifiez les logs pour des timeouts.
Task 7: Verify user lookup and group membership (policy may block)
cr0x@server:~$ id j.smith
uid=110245(j.smith) gid=10000(domain users) groups=10000(domain users),12010(vpn-users)
Sens : L’utilisateur existe et est dans vpn-users. Décision : Si l’auth échoue encore, ce n’est pas « utilisateur absent » ; c’est l’état du compte/le mot de passe ou un flux MFA/politique en amont.
Task 8: Check account status (locked/expired) when using local or LDAP-backed auth
cr0x@server:~$ sudo passwd -S j.smith
j.smith L 2025-11-02 0 99999 7 -1
Sens : « L » indique compte verrouillé (pour comptes locaux ; l’interprétation varie pour les annuaires). Décision : Déverrouillez/réinitialisez via le système d’identité approprié ; arrêtez de dire à l’utilisateur « réessayez ».
Task 9: Validate client credential file for hidden characters
cr0x@server:~$ sed -n '1,2p' -n auth.txt | cat -A
j.smith$
MyS3cretP@ssw0rd^M$
Sens : La ligne de mot de passe se termine par ^M (CR). C’est un mot de passe différent. Décision : Convertissez le fichier en terminaisons Unix et retentez.
Task 10: Fix CRLF in the credential file and retest
cr0x@server:~$ sed -i 's/\r$//' auth.txt
cr0x@server:~$ sed -n '1,2p' auth.txt | cat -A
j.smith$
MyS3cretP@ssw0rd$
Sens : CR supprimé. Décision : Relancez le client ; si ça marche maintenant, vous venez d’économiser une heure de blâme LDAP inutile.
Task 11: Check for certificate revocation / CRL issues
cr0x@server:~$ sudo grep -E '^(crl-verify|ca|cert|key)' /etc/openvpn/server/corp.conf
ca /etc/openvpn/pki/ca.crt
cert /etc/openvpn/pki/issued/vpn-gateway-1.crt
key /etc/openvpn/pki/private/vpn-gateway-1.key
crl-verify /etc/openvpn/pki/crl.pem
Sens : Le CRL est appliqué. Un cert client révoqué peut bloquer l’accès même si le mot de passe est correct. Décision : Vérifiez si le cert connecté est révoqué et si le fichier CRL est à jour/lisible.
Task 12: Inspect the CRL file freshness and permissions
cr0x@server:~$ sudo ls -l /etc/openvpn/pki/crl.pem
-rw-r----- 1 root openvpn 2451 Nov 1 2024 /etc/openvpn/pki/crl.pem
Sens : Ancienne date. Si votre PKI tourne, vous pouvez appliquer un CRL périmé (ou manquer des révocations récentes). Décision : Régénérez/rafraîchissez le CRL comme partie des opérations PKI et assurez-vous qu’OpenVPN peut le lire.
Task 13: Confirm OpenVPN is reading the config you think it is
cr0x@server:~$ sudo systemctl cat openvpn-server@corp
# /lib/systemd/system/openvpn-server@.service
ExecStart=/usr/sbin/openvpn --status %t/openvpn-server/status-%i.log --status-version 2 --suppress-timestamps --config /etc/openvpn/server/%i.conf
Sens : L’instance utilise /etc/openvpn/server/corp.conf. Décision : Arrêtez d’éditer le mauvais fichier sous /etc/openvpn/ en espérant des miracles.
Task 14: Check management interface for real-time auth hints (if enabled)
cr0x@server:~$ printf "status 3\nquit\n" | nc 127.0.0.1 7505
OpenVPN STATISTICS
Updated,2025-12-27 09:13:02
CLIENT_LIST,UNDEF,198.51.100.44:51233,10.8.0.0,0,0,2025-12-27 09:12:31
END
Sens : Le client ne s’est jamais établi complètement (UNDEF common name est révélateur). Décision : Concentrez-vous sur l’étape d’auth, pas sur le routage/les options push.
Task 15: Verify server time (token/MFA and cert validity depend on it)
cr0x@server:~$ timedatectl
Local time: Fri 2025-12-27 09:13:55 UTC
Universal time: Fri 2025-12-27 09:13:55 UTC
RTC time: Fri 2025-12-27 09:13:55
Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
Sens : L’heure est synchronisée. Décision : Si elle n’était pas synchronisée, corrigez NTP avant de déboguer des échecs d’auth « aléatoires », surtout avec des tokens à courte durée de vie.
Task 16: Check DNS resolution on the VPN server (LDAP/RADIUS often uses hostnames)
cr0x@server:~$ getent hosts ldap01.corp.local
10.20.30.40 ldap01.corp.local
Sens : Le nom se résout. Décision : Si ça échoue ou résout vers une IP ancienne, corrigez DNS/hosts/SSSD resolver ; les backends d’auth ne seront pas joignables de façon fiable.
Task 17: If using RADIUS, confirm connectivity (timeout vs reject)
cr0x@server:~$ nc -vz radius01 1812
Connection to radius01 1812 port [tcp/*] succeeded!
Sens : La connectivité TCP existe (note : RADIUS est typiquement UDP ; ceci prouve seulement nom/route/firewall de base). Décision : Si le réseau est bloqué, le plugin RADIUS peut le présenter comme AUTH_FAILED.
Task 18: Check OpenVPN version alignment (behavior changes across versions)
cr0x@server:~$ openvpn --version
OpenVPN 2.6.8 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD]
library versions: OpenSSL 3.0.13 30 Jan 2024, LZO 2.10
Sens : Le serveur est en 2.6.x avec OpenSSL 3. Décision : Si les clients sont anciens, vérifiez data-ciphers et la version TLS minimum. Une incompatibilité peut ressembler à des « bizarreries d’auth » pour les utilisateurs.
Erreurs courantes (symptôme → cause racine → fix)
1) Symptom: “AUTH_FAILED” immediately after “Peer Connection Initiated”
Cause racine : Le plugin ou le script d’auth rejette ; les identifiants peuvent être corrects mais le backend est down ou la politique refuse l’utilisateur.
Fix : Inspectez les logs serveur autour de PLUGIN_CALL / AUTH-PAM / sortie script. Si c’est une panne de backend, traitez-la comme un incident et restaurez la santé de la dépendance.
2) Symptom: Credentials work via SSH/PAM, but OpenVPN says AUTH_FAILED
Cause racine : Le plugin PAM d’OpenVPN pointe vers un service PAM différent (ex. login) avec des restrictions supplémentaires (nologin, securetty, règles horaire).
Fix : Utilisez un fichier de service PAM dédié (ex. /etc/pam.d/openvpn) et configurez plugin ... openvpn en conséquence.
3) Symptom: Only Windows clients fail; Linux/macOS succeed
Cause racine : Fichier d’identifiants enregistré en CRLF, ajoutant un \r au mot de passe ; ou le client GUI envoie le nom d’utilisateur dans un format différent.
Fix : Normalisez les terminaisons de ligne ; évitez les fichiers de mot de passe quand possible ; testez en saisie manuelle ; standardisez le format du nom d’utilisateur.
4) Symptom: Only one user fails, repeatedly, across devices
Cause racine : Compte verrouillé, mot de passe expiré, utilisateur retiré du groupe requis, ou cert révoqué tandis que le mot de passe reste valide.
Fix : Vérifiez le statut dans le fournisseur d’identités pour cet utilisateur ; vérifiez l’appartenance au groupe ; vérifiez le CRL et l’état du certificat.
5) Symptom: Everyone fails right after an OpenVPN upgrade
Cause racine : Valeurs par défaut de chiffrement/TLS changées ; binaire du plugin incompatible ; ou vérification plus stricte révélant des problèmes de certs existants.
Fix : Validez data-ciphers et les versions TLS minimales ; confirmez le chemin et la compatibilité ABI du plugin ; effectuez un rollback si nécessaire, puis réintroduisez les changements de façon contrôlée.
6) Symptom: Random users fail, then succeed on retry
Cause racine : Timeouts backend (RADIUS/LDAP), instabilités DNS, serveur d’auth surchargé, ou politique de rate limiting/verrouillage.
Fix : Instrumentez et surveillez la latence des backends ; réduisez les timeouts avec précaution ; ajoutez de la redondance ; corrigez le DNS. Le « réessayer » n’est pas une stratégie.
7) Symptom: User enters correct password + MFA, still AUTH_FAILED
Cause racine : L’intégration MFA attend un format différent (appender OTP, utiliser challenge/response) ou requiert un attribut RADIUS spécifique.
Fix : Confirmez le flux MFA avec l’équipe d’identité ; mettez à jour les instructions client ; assurez-vous que le plugin supporte le mode MFA déployé.
8) Symptom: AUTH_FAILED on reconnect/renegotiation, not on first connect
Cause racine : Cache de token/renégociation en désaccord ; auth-nocache et politiques de token qui se battent ; état de session perdu après redémarrage serveur.
Fix : Décidez si vous voulez des tokens ; alignez les réglages serveur/client ; testez les fenêtres de renégociation ; évitez les configs « à moitié » pour les tokens.
Trois mini-récits d’entreprise venus des tranchées
Mini-story 1: The incident caused by a wrong assumption
L’entreprise avait une passerelle VPN qui « utilisait LDAP ». Cette phrase avait été répétée dans les tickets pendant des années, comme une incantation pour éviter des questions. Un nouveau SRE a reçu un pager pour une pluie d’AUTH_FAILED après un changement d’annuaire. Les utilisateurs insistaient que leurs identifiants étaient corrects. Le helpdesk garantissait que le VPN était OK. Le tableau de bord n’indiquait rien, parce qu’il n’existait pas.
Le SRE a suivi les logs OpenVPN et a vu PLUGIN_CALL suivi de status=1. Aucun détail. Super. Ils ont supposé des échecs de bind LDAP et ont commencé à chercher : connectivité, DNS, firewall. Tout semblait normal. Ils ont passé une heure à vérifier le calendrier de changements de l’équipe annuaire, préparant le message poli « avez-vous cassé LDAP ? ».
Avant l’envoi, ils ont vérifié la config du serveur OpenVPN et ont remarqué que le plugin était PAM, pas LDAP. LDAP n’était qu’une dépendance en amont via SSSD, et le cache SSSD était périmé parce que le serveur ne pouvait plus atteindre la source temporelle après un changement de routage. La couche Kerberos/LDAP ne tombait pas complètement ; elle devenait lente et incohérente. PAM retournait des échecs. OpenVPN rapportait AUTH_FAILED.
La mauvaise hypothèse était subtile : « AUTH_FAILED après changement d’annuaire implique échec de bind LDAP ». Le vrai problème était « la résolution d’identité time-out parce que la synchro d’heure a cassé », ce qui vous fait respecter NTP comme s’il s’agissait d’une base de données de production.
Ils ont corrigé le routage vers NTP, redémarré SSSD pour vider le cache le plus critique, et les échecs ont disparu. L’équipe annuaire n’a jamais su qu’un mail accusateur était resté en brouillon.
Mini-story 2: The optimization that backfired
Une équipe sécurité voulait moins d’invites de mot de passe. Ils ont activé la réauth basée sur token pour que les utilisateurs n’aient pas à retaper leurs identifiants lors des reconnexions. Ça semblait bien : moins d’invites, moins de verrouillages, moins de tickets. Ils l’ont déployé pendant une « semaine calme », ce qui en time corporate signifie « juste avant un congé ».
Au début, succès. Puis les laptops ont commencé à dormir/réveiller, changer de réseau et tenter des reconnexions. Certaines reconnexions fonctionnaient. D’autres échouaient avec AUTH_FAILED. Le helpdesk a escaladé en « problèmes de mot de passe ». Les utilisateurs ont commencé à réinitialiser leurs mots de passe, ce qui bien sûr ne réparait pas les échecs de token. Maintenant il y avait à la fois des échecs VPN et du churn lié aux réinitialisations.
La cause racine était un décalage entre la durée de vie des tokens et le comportement de renégociation. Certains clients présentaient un token périmé après un long sommeil ; le serveur le considérait invalide et rejetait. La journalisation était insuffisante, donc tout semblait être un utilisateur qui avait mal tapé son mot de passe alors qu’aucun mot de passe n’avait été tapé du tout.
Le correctif a été ennuyeux : aligner les politiques de token sur le comportement réaliste des appareils, augmenter la journalisation autour de la validation des tokens, et ajouter un fallback côté client pour inviter les identifiants quand l’auth token échoue. Aussi : ne modifiez pas le comportement d’auth juste avant les congés si vous n’aimez pas apprendre de nouveaux jurons pendant vos congés.
Mini-story 3: The boring but correct practice that saved the day
Une équipe plateforme interne gérait deux gateways OpenVPN derrière un load balancer. Rien de fancy. Le côté remarquable était leur discipline : chaque changement avait un canary, et chaque canary avait un utilisateur test connu bon et un utilisateur test connu mauvais. Ils gardaient aussi une petite suite de « vérifications de dépendances d’identité » qui s’exécutaient chaque minute : peut-on résoudre les hostnames LDAP, peut-on binder, peut-on joindre RADIUS, l’heure est-elle synchronisée.
Un matin, les utilisateurs ont commencé à signaler AUTH_FAILED — seulement sur une gateway. Les checks canary l’ont détecté en moins de deux minutes : la latence du bind LDAP a grimpé sur vpn2, pas sur vpn1. Le load balancer envoyait encore du trafic à vpn2 parce que les health checks se limitaient à « port ouvert ».
Parce qu’ils avaient des logs par nœud et des vérifications structurées, ils n’ont pas débattu pour savoir si les utilisateurs avaient oublié leurs mots de passe. Ils ont drainé vpn2 du pool, restaurant le service, puis ont debug calmement : vpn2 avait une dérive de config resolver pointant vers un vieux serveur DNS. La résolution LDAP échouait de façon intermittente, entraînant des timeouts d’auth et des rejets.
Ils ont corrigé la config resolver, ajouté un health check au load balancer qui testait réellement les dépendances d’auth, et rédigé un postmortem avec exactement une phrase de blâme : « Nous avons fait confiance à une vérif de port pour représenter une pipeline d’identité. » C’était ennuyeux, et ça a empêché la même incident de réapparaître sous un autre costume.
Listes de contrôle / plan étape par étape
Étape par étape : quand un utilisateur signale AUTH_FAILED
- Capturez un timestamp (avec timezone) et l’IP publique du client.
- Demandez le format exact du nom d’utilisateur qu’il a saisi (incluant domaine/realm).
- Confirmez s’il a utilisé un fichier d’identifiants ou une invite interactive.
- Vérifiez les logs serveur à ce timestamp. Trouvez la ligne de connexion et la ligne de décision d’auth.
- Identifiez le backend d’auth : PAM vs script vs RADIUS vs plugin LDAP.
- Testez le backend directement : test PAM, bind LDAP, connectivité RADIUS, appartenance aux groupes.
- Vérifiez les couches de politique : appartenance aux groupes, limites de sessions concurrentes, overrides CCD par utilisateur.
- Si les certs sont impliqués : vérifiez que le cert client n’est pas expiré/révoqué ; validez la fraîcheur du CRL.
- Décidez : remédiation utilisateur (déverrouiller/réinitialiser) vs incident infrastructure (backend down).
Étape par étape : quand beaucoup d’utilisateurs signalent AUTH_FAILED
- Supposez une panne de dépendance jusqu’à preuve du contraire.
- Vérifiez un utilisateur connu bon depuis une config client connue bonne. S’il échoue, ce n’est pas de l’éducation utilisateur.
- Vérifiez les backends d’identité : disponibilité des annuaires, santé des serveurs RADIUS, état du fournisseur MFA, DNS, synchronisation d’heure.
- Vérifiez les changements récents : upgrade OpenVPN, mises à jour de plugin, edits PAM, rotations de cert, changements firewall.
- Isolez par nœud si vous avez plusieurs gateways : videz un nœud à la fois pour voir si les échecs sont localisés.
- Augmentez la journalisation temporairement (en protégeant les données sensibles) pour capturer les chemins de sortie des plugins/scripts.
- Stabilisez d’abord : rollback ou contournez les fonctionnalités d’auth non critiques si la politique le permet (ex. désactiver temporairement des vérifs de groupe strictes).
- Notez la timeline. Vous oublierez en 24 heures, et le futur vous remerciera.
Ce qu’il faut éviter (opinion)
- Ne demandez pas aux utilisateurs de réinitialiser leur mot de passe comme première étape. Cela crée du bruit et masque des défaillances systémiques.
- Ne déboguez pas uniquement depuis le client. AUTH_FAILED est une décision côté serveur.
- Ne changez pas trois variables en même temps (« on a mis à jour OpenVPN, tourné les certs et modifié PAM »). Ce n’est pas de l’ingénierie ; c’est du hasard.
- Faites un client connu bon et gardez-le pristine. C’est votre groupe témoin.
FAQ
Pourquoi OpenVPN indique-t-il AUTH_FAILED alors que le mot de passe est correct ?
Parce que le serveur a rejeté la tentative d’authentification pour des raisons qui incluent — mais ne se limitent pas à — un mauvais mot de passe : compte verrouillé, mot de passe expiré, groupe manquant, timeout backend, plantage de plugin ou politique MFA.
Comment savoir si c’est un problème TLS/cert ou nom d’utilisateur/mot de passe ?
Recherchez un handshake TLS complété dans le log client. Si vous voyez « Peer Connection Initiated » puis AUTH_FAILED, TLS a probablement réussi et l’auth utilisateur/politique a échoué.
Un certificat révoqué peut-il provoquer AUTH_FAILED malgré des identifiants corrects ?
Oui. Si le serveur exige des certificats clients et applique un CRL, un certificat révoqué vous bloquera indépendamment du nom d’utilisateur/mot de passe.
Quel est le log serveur le plus rapide à vérifier sur un Linux basé systemd ?
journalctl -u openvpn-server@<instance> autour du moment de l’échec. Cherchez les appels de plugin, l’invocation de scripts et les lignes explicites AUTH_FAILED avec les noms d’utilisateur.
Pourquoi seuls les utilisateurs Windows échouent ?
Causes communes : CRLF dans un fichier d’identifiants, format de nom d’utilisateur différent envoyé par le client GUI, ou utilisateurs copiant un mot de passe avec un espace final. Validez le fichier d’identifiants avec cat -A et standardisez l’entrée.
Nous utilisons PAM. Pourquoi SSH marche mais OpenVPN échoue ?
PAM est modulaire. SSH peut utiliser le service PAM sshd tandis qu’OpenVPN utilise login (ou un autre). Ces piles peuvent différer sur les règles de compte, TTY autorisés ou le comportement nologin.
Des problèmes DNS peuvent-ils vraiment se présenter comme AUTH_FAILED ?
Oui. Si votre backend d’auth utilise des hostnames (LDAP, RADIUS, passerelles MFA), des échecs de résolution ou un DNS périmé peuvent provoquer des timeouts qui aboutissent à un rejet générique d’auth.
La synchronisation d’heure importe-t-elle pour l’auth VPN ?
Absolument. Les certificats ont des fenêtres de validité ; les systèmes MFA et tokens sont dépendants du temps ; l’auth Kerberos est extrêmement sensible au skew d’horloge. Corrigez l’heure d’abord si elle est fausse.
Faut-il activer une journalisation plus verbeuse en permanence ?
Maintenez des logs de base suffisants pour distinguer les échecs TLS des échecs de backend d’auth. Augmentez la verbosité temporairement lors d’incidents. Faites attention à ne pas logger d’informations sensibles depuis les scripts/plugins.
Est-il sûr de se fier à des health checks « port ouvert » pour des gateways VPN ?
Non. Un listener peut être sain alors que la pipeline d’auth est cassée. Ajoutez des health checks qui valident la reachabilité des dépendances (DNS, bind annuaire, réactivité RADIUS) et videz les nœuds quand celles-ci échouent.
Conclusion : prochaines étapes qui réduisent vraiment le bruit des pagers
Si vous ne faites que quelques actions à partir de ceci :
- Séparez les échecs TLS des échecs d’auth utilisateur en vous basant sur les logs client. Cessez de traiter AUTH_FAILED comme « mauvais mot de passe » automatiquement.
- Faites expliquer le serveur : assurez-vous que les logs incluent les issues plugins/scripts et soient faciles à interroger par timestamp.
- Testez les backends d’identités directement (PAM/SSSD/LDAP/RADIUS) pour pouvoir annoncer « panne d’identité » sans hésitation.
- Standardisez les formats de nom d’utilisateur et documentez les flux MFA en un seul endroit maintenu à jour.
- Créez un utilisateur test connu bon et une config client connue bonne, et utilisez-les comme groupe témoin lors des incidents.
AUTH_FAILED n’est pas un verdict. C’est un indice que le serveur a pris une décision. Votre travail est de trouver quel composant a chuchoté à son oreille.