Hook PHP d’OpenVPN : trusted_ip face à ifconfig_pool_remote_ip
Deux adresses aux sens différents, lues par un processus que vous n’avez pas lancé. Ce que sont les variables du hook, et pourquoi un $_ENV vide ne prouve rien.
Un tableau $_ENV vide dans un script de hook donne l’impression d’une preuve que OpenVPN n’a rien transmis. C’est en général la preuve de tout autre chose : PHP était configuré pour ne pas remplir cette superglobale, et les valeurs se trouvaient dans l’environnement du processus depuis le début. La seconde conclusion fausse est plus subtile, car les deux variables d’adresse d’un hook de connexion désignent des choses différentes et s’emploient l’une pour l’autre. Les deux erreurs coûtent un après-midi si vous partez de la mauvaise.
Deux adresses, deux affirmations différentes
Le point de sortie externe est ce que le serveur a observé à la connexion du client, disponible sous trusted_ip pour IPv4 et trusted_ip6 pour IPv6. L’adresse virtuelle est celle que le pool a attribuée à cette session, disponible sous ifconfig_pool_remote_ip.
Elles répondent à des questions différentes, et un enregistrement a généralement besoin de l’une plutôt que des deux. La première est l’origine de la connexion, qui peut être une adresse NAT partagée par des centaines de personnes. La seconde est l’emplacement de cette session dans le tunnel, et elle peut être réattribuée à une autre session plus tard. Confondre les deux produit des enregistrements plausibles et faux.
Une lecture minimale ressemble à ceci.
$outer4 = getenv('trusted_ip');
$outer6 = getenv('trusted_ip6');
$inner = getenv('ifconfig_pool_remote_ip');
$outer = $outer4 !== false ? $outer4 : $outer6;Aucune des deux valeurs n’identifie une personne. L’une est une observation réseau, l’autre un bail, et un enregistrement qui traite l’une ou l’autre comme un identifiant d’appareil stable sera faux la première fois qu’un client se reconnecte depuis un autre réseau ou reçoit une autre adresse du pool. Choisissez le champ selon la question à laquelle l’enregistrement doit répondre, puis écrivez cette question à côté de la colonne.
Vérifiez comment PHP a été lancé, pas votre shell
Le hook s’exécute comme enfant du démon VPN avec un environnement que le démon construit. Votre shell interactif en a un autre, et exécuter le script à la main teste l’environnement du shell plutôt que celui du hook.
Commencez par confirmer que le hook s’est bien déclenché à l’étape attendue. Un script rattaché à la mauvaise étape, ou un script qui n’a jamais tourné parce que la directive pointe vers un autre chemin, produit exactement le même symptôme qu’une variable absente. Ajoutez une ligne de marquage volontaire en tête du script et confirmez qu’elle apparaît avant d’inspecter quoi que ce soit d’autre. Une seule ligne horodatée dans le journal sépare « n’a jamais tourné » de « a tourné sans la valeur ».
Confirmez ensuite quel interpréteur et quel fichier de configuration cette invocation utilise. Modifier la configuration PHP d’un serveur web ne change rien à un processus CLI lancé par OpenVPN, et les deux peuvent charger des fichiers php.ini entièrement différents.
Pourquoi un $_ENV vide ne prouve rien
La référence getenv de PHP documente une lecture directe de l’environnement du processus, qui renvoie false lorsque le nom est absent. La superglobale $_ENV est remplie séparément, et la directive variables_order décide quelles superglobales sont remplies.
Si cette directive omet E, $_ENV reste vide quel que soit le contenu de l’environnement. Le code qui l’indexe signale alors une variable absente qui est en fait présente, et l’enquête part vers OpenVPN alors que la réponse est dans php.ini. Vérifiez la directive spécifiquement pour la configuration CLI, pas pour le serveur web.
Lire avec getenv évite toute cette classe de confusion, et un script d’enveloppe qui vide l’environnement avant d’appeler l’interpréteur la réintroduit sous une autre forme.
Stockez une association, pas une mise à jour de ligne
Décidez de la valeur dont l’enregistrement a besoin avant de l’écrire. Si le but est de noter d’où vient une session, stockez le point de sortie externe et étiquetez-le comme une observation. Si le but est de relier une session à une adresse de tunnel pendant une connexion, stockez l’adresse du pool et liez-la à la session.
Mettez à jour selon l’identité authentifiée et la session courante plutôt que selon chaque ligne partageant une adresse de tunnel, car les adresses du pool sont réutilisées et un événement de déconnexion tardif peut sinon écraser les données d’une connexion plus récente. Traitez IPv6 explicitement au lieu d’écrire silencieusement la seule valeur IPv4. Une ligne avec une adresse externe NULL vaut mieux qu’une ligne avec la mauvaise, car la première est visiblement incomplète.
Liez l’écriture à l’identifiant de session fourni par OpenVPN pour qu’une reconnexion crée un nouvel enregistrement plutôt que de modifier l’ancien. Utilisez des requêtes paramétrées et un compte disposant uniquement des droits nécessaires à l’opération. Un hook s’exécute avec l’autorité du démon, donc une requête négligée est un problème plus large qu’une ligne de journal erronée.
Diagnostiquez sans vider l’environnement
Journalisez quels noms étaient présents, quelle étape a tourné et quel interpréteur a été utilisé. N’imprimez pas tout l’environnement, car un processus de hook peut hériter de valeurs sans rapport qui ne devraient pas finir dans un fichier de journal.
Vérifiez une connexion de bout en bout : lisez le point de sortie externe, lisez l’adresse attribuée, et confirmez les deux face à la vue du serveur sur cette session. Une fois la paire confirmée pour un client, l’association peut être fiable ailleurs.