Et tomt $_ENV-array i et hook-script føles som bevis for, at OpenVPN ikke sendte noget videre. Det er som regel bevis for noget helt andet: PHP var konfigureret til ikke at udfylde den superglobal, og værdierne sad i processens miljø hele tiden. Den anden falske konklusion er mere subtil, fordi de to adressevariabler i et forbindelseshook betyder forskellige ting og bruges i flæng. Begge fejl koster en eftermiddag, hvis man starter med den forkerte.

To adresser, to forskellige påstande

Det ydre endepunkt er det, serveren observerede, da klienten koblede til, tilgængeligt som trusted_ip for IPv4 og trusted_ip6 for IPv6. Den virtuelle adresse er den, poolen tildelte til denne session, tilgængelig som ifconfig_pool_remote_ip.

De svarer på forskellige spørgsmål, og en post har som regel brug for én af dem frem for begge. Den første er, hvor forbindelsen kom fra, hvilket kan være en delt NAT-adresse, som hundredvis af mennesker bruger. Den anden er, hvor denne session lever inde i tunnelen, og den kan senere tildeles en anden session. At forveksle de to giver poster, der ser rimelige ud og er forkerte.

En minimal læsning ser sådan ud.

$outer4 = getenv('trusted_ip');
$outer6 = getenv('trusted_ip6');
$inner  = getenv('ifconfig_pool_remote_ip');
$outer  = $outer4 !== false ? $outer4 : $outer6;

Ingen af værdierne identificerer en person. Den ene er en netværksobservation, den anden en lease, og en post, der behandler en af dem som en stabil enhedsidentifikator, vil være forkert første gang en klient genopretter forbindelsen fra et andet netværk eller får en anden pooladresse. Vælg feltet efter det spørgsmål, posten skal besvare, og skriv så det spørgsmål ved siden af kolonnen.

Kontroller, hvordan PHP blev startet, ikke dit shell

Hooket kører som barn af VPN-dæmonen med et miljø, som dæmonen bygger. Dit interaktive shell har et andet, og at køre scriptet i hånden tester shellens miljø frem for hookets.

Begynd med at bekræfte, at hooket faktisk blev udløst i den fase, du forventede. Et script knyttet til den forkerte fase, eller et der aldrig kørte, fordi direktivet peger på en anden sti, giver præcis samme symptom som en manglende variabel. Tilføj en bevidst markørlinje i toppen af scriptet, og bekræft at den vises, før du undersøger noget andet. En enkelt tidsstemplet linje i loggen skiller aldrig kørt fra kørt uden værdien.

Bekræft derefter, hvilken fortolker og hvilken konfigurationsfil det kald bruger. At rette PHP-konfigurationen for en webserver ændrer intet ved en CLI-proces startet af OpenVPN, og de to kan indlæse helt forskellige php.ini-filer.

Hvorfor et tomt $_ENV ikke beviser noget

PHPs getenv-reference beskriver en direkte læsning af processens miljø, som returnerer false, når navnet mangler. Superglobalen $_ENV udfyldes separat, og direktivet variables_order afgør, hvilke superglobaler der bliver udfyldt.

Hvis det direktiv udelader E, forbliver $_ENV tomt, uanset hvad miljøet indeholder. Kode, der indekserer det, rapporterer så en manglende variabel, som faktisk er til stede, og undersøgelsen bevæger sig mod OpenVPN, mens svaret er i php.ini. Kontroller direktivet specifikt for CLI-konfigurationen, ikke for webserveren.

At læse med getenv undgår hele den klasse forvirring, og et wrapper-script, der rydder miljøet, før det kalder fortolkeren, genindfører den i en anden form.

Gem en association, ikke en rækkeopdatering

Afgør, hvilken værdi posten har brug for, før du skriver den. Hvis målet er at notere, hvor en session kom fra, så gem det ydre endepunkt og mærk det som en observation. Hvis målet er at knytte en session til en tunneladresse i en forbindelses varighed, så gem pooladressen og nøgl den til sessionen.

Opdater efter den godkendte identitet og den aktuelle session frem for efter hver række, der deler en tunneladresse, fordi pooladresser genbruges, og en sen afbrydelseshændelse ellers kan overskrive data fra en nyere forbindelse. Håndtér IPv6 eksplicit i stedet for lydløst kun at skrive IPv4-værdien. En række med en NULL ydre adresse er bedre end en række med den forkerte, fordi den første er synligt ufuldstændig.

Nøgl skrivningen til det sessions-id, OpenVPN leverer, så en genoprettet forbindelse opretter en ny post frem for at redigere den gamle. Brug parameteriserede sætninger og en konto med kun de tilladelser, operationen kræver. Et hook kører med dæmonens myndighed, så en skødesløs forespørgsel er et større problem end en forkert loglinje.

Diagnostiser uden at dumpe miljøet

Log hvilke navne der var til stede, hvilken fase der kørte, og hvilken fortolker der blev brugt. Udskriv ikke hele miljøet, fordi en hookproces kan arve uvedkommende værdier, som ikke bør ende i en logfil.

Verificér én forbindelse fra ende til anden: læs det ydre endepunkt, læs den tildelte adresse, og bekræft begge mod serverens eget syn på den session. Når parret er bekræftet for én klient, kan associationen stoles på andre steder.

Relaterede artikler