Hook PHP di OpenVPN: trusted_ip contro ifconfig_pool_remote_ip
Due indirizzi con due significati diversi, letti da un processo che non hai avviato tu. Cosa sono le variabili dell’hook e perché un $_ENV vuoto non dimostra nulla.
Un array $_ENV vuoto in uno script di hook sembra la prova che OpenVPN non abbia passato nulla. Di solito è la prova di qualcosa di completamente diverso: PHP era configurato per non popolare quella superglobale, e i valori stavano nell’ambiente del processo per tutto il tempo. La seconda conclusione falsa è più sottile, perché le due variabili di indirizzo in un hook di connessione significano cose diverse e vengono usate l’una per l’altra. Entrambi gli errori costano un pomeriggio se si parte da quello sbagliato.
Due indirizzi, due affermazioni diverse
L’endpoint esterno è ciò che il server ha osservato quando il client si è connesso, disponibile come trusted_ip per IPv4 e trusted_ip6 per IPv6. L’indirizzo virtuale è quello che il pool ha assegnato a questa sessione, disponibile come ifconfig_pool_remote_ip.
Rispondono a domande diverse, e un record di solito ha bisogno di uno dei due anziché di entrambi. Il primo è da dove è arrivata la connessione, che può essere un indirizzo NAT condiviso usato da centinaia di persone. Il secondo è dove vive questa sessione dentro il tunnel, e può essere riassegnato a un’altra sessione in seguito. Confondere i due produce record che sembrano plausibili e sono sbagliati.
Una lettura minima ha questo aspetto.
$outer4 = getenv('trusted_ip');
$outer6 = getenv('trusted_ip6');
$inner = getenv('ifconfig_pool_remote_ip');
$outer = $outer4 !== false ? $outer4 : $outer6;Nessuno dei due valori identifica una persona. Uno è un’osservazione di rete, l’altro un contratto di locazione, e un record che tratta l’uno o l’altro come identificatore stabile del dispositivo sarà sbagliato la prima volta che un client si riconnette da un’altra rete o riceve un altro indirizzo del pool. Scegli il campo in base alla domanda a cui il record deve rispondere, poi scrivi quella domanda accanto alla colonna.
Controlla come è stato avviato PHP, non la tua shell
L’hook gira come figlio del demone VPN con un ambiente che il demone costruisce. La tua shell interattiva ne ha un altro, ed eseguire lo script a mano verifica l’ambiente della shell anziché quello dell’hook.
Inizia confermando che l’hook si sia davvero attivato nella fase che ti aspettavi. Uno script agganciato alla fase sbagliata, o uno che non è mai partito perché la direttiva punta a un altro percorso, produce esattamente lo stesso sintomo di una variabile mancante. Aggiungi una riga marcatore deliberata in cima allo script e conferma che compaia prima di ispezionare qualsiasi altra cosa. Una sola riga con marca temporale nel log separa non è mai partito da è partito senza il valore.
Poi conferma quale interprete e quale file di configurazione usa quella invocazione. Modificare la configurazione PHP di un server web non cambia nulla in un processo CLI avviato da OpenVPN, e i due possono caricare file php.ini completamente diversi.
Perché un $_ENV vuoto non dimostra nulla
La documentazione di getenv di PHP descrive una lettura diretta dell’ambiente del processo, che restituisce false quando il nome è assente. La superglobale $_ENV viene popolata separatamente, e la direttiva variables_order decide quali superglobali vengono popolate.
Se quella direttiva omette E, $_ENV resta vuoto qualunque cosa contenga l’ambiente. Il codice che lo indicizza allora segnala una variabile assente che in realtà è presente, e l’indagine va verso OpenVPN mentre la risposta è in php.ini. Controlla la direttiva specificamente per la configurazione CLI, non per il server web.
Leggere con getenv evita tutta questa classe di confusione, e uno script wrapper che svuota l’ambiente prima di invocare l’interprete la reintroduce in un’altra forma.
Memorizza un’associazione, non un aggiornamento di riga
Decidi quale valore serve al record prima di scriverlo. Se lo scopo è annotare da dove è venuta una sessione, memorizza l’endpoint esterno e etichettalo come osservazione. Se lo scopo è mappare una sessione a un indirizzo di tunnel per la durata di una connessione, memorizza l’indirizzo del pool e collegalo alla sessione.
Aggiorna per identità autenticata e sessione corrente anziché per ogni riga che condivide un indirizzo di tunnel, perché gli indirizzi del pool vengono riutilizzati e un evento di disconnessione tardivo può altrimenti sovrascrivere i dati di una connessione più recente. Gestisci IPv6 esplicitamente invece di scrivere in silenzio solo il valore IPv4. Una riga con indirizzo esterno NULL è meglio di una con quello sbagliato, perché la prima è visibilmente incompleta.
Collega la scrittura all’identificatore di sessione fornito da OpenVPN così che una riconnessione crei un nuovo record invece di modificare quello vecchio. Usa istruzioni parametrizzate e un account con solo i permessi necessari all’operazione. Un hook gira con l’autorità del demone, quindi una query distratta è un problema più ampio di una riga di log sbagliata.
Diagnostica senza riversare l’ambiente
Registra quali nomi erano presenti, quale fase è girata e quale interprete è stato usato. Non stampare tutto l’ambiente, perché un processo di hook può ereditare valori estranei che non dovrebbero finire in un file di log.
Verifica una connessione da un capo all’altro: leggi l’endpoint esterno, leggi l’indirizzo assegnato e conferma entrambi contro la visione del server di quella sessione. Una volta confermata la coppia per un client, l’associazione è affidabile altrove.