Празен масив $_ENV в hook скрипт изглежда като доказателство, че OpenVPN не е предал нищо. Обикновено това е доказателство за нещо съвсем друго: PHP е бил конфигуриран да не запълва тази суперглобална променлива и стойностите са стояли в средата на процеса през цялото време. Второто погрешно заключение е по-фино, защото двете променливи за адрес в hook-а за връзка означават различни неща и се използват взаимозаменяемо. И двете грешки струват един следобед, ако започнете от грешната.

Два адреса, две различни претенции

Външната крайна точка е това, което сървърът е наблюдавал при свързването на клиента, достъпна като trusted_ip за IPv4 и trusted_ip6 за IPv6. Виртуалният адрес е това, което пулът е назначил за тази сесия, достъпен като ifconfig_pool_remote_ip.

Те отговарят на различни въпроси и записът обикновено се нуждае от един от тях, а не от двата. Първият е откъде е дошла връзката, което може да е споделен NAT адрес, използван от стотици хора. Вторият е къде живее тази сесия вътре в тунела и може по-късно да бъде преназначен на друга сесия. Объркването на двете създава записи, които изглеждат правдоподобни и са грешни.

Минималното четене изглежда така.

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

Нито една от двете стойности не идентифицира човек. Едната е мрежово наблюдение, другата е наем, и запис, който третира която и да е от тях като стабилен идентификатор на устройство, ще бъде грешен първия път, когато клиент се свърже от друга мрежа или получи друг адрес от пула. Изберете полето според въпроса, на който записът трябва да отговори, и после напишете този въпрос до колоната.

Проверете как е стартиран PHP, а не вашата обвивка

Hook-ът работи като дете на VPN демона със среда, която демонът построява. Вашата интерактивна обвивка има друга среда и ръчното стартиране на скрипта тества средата на обвивката, а не тази на hook-а.

Започнете с потвърждение, че hook-ът наистина се е задействал на етапа, който очаквате. Скрипт, прикачен към грешен етап, или такъв, който никога не е стартирал, защото директивата сочи друг път, дава точно същия симптом като липсваща променлива. Добавете умишлен маркерен ред в началото на скрипта и потвърдете, че се появява, преди да проверявате каквото и да е друго. Един ред с отметка за време в журнала разделя „никога не е стартирал“ от „стартирал без стойността“.

След това потвърдете кой интерпретатор и кой конфигурационен файл използва това извикване. Редактирането на PHP конфигурацията за уеб сървър не променя нищо за CLI процес, стартиран от OpenVPN, и двата могат да заредят напълно различни файлове php.ini.

Защо празен $_ENV не доказва нищо

Документацията на getenv описва директно четене на средата на процеса, което връща false, когато името липсва. Суперглобалната променлива $_ENV се запълва отделно, а директивата variables_order решава кои суперглобални променливи се запълват.

Ако тази директива пропуска E, $_ENV остава празна независимо какво съдържа средата. Код, който я индексира, тогава съобщава за липсваща променлива, която всъщност присъства, и разследването поема към OpenVPN, докато отговорът е в php.ini. Проверете директивата именно за CLI конфигурацията, а не за уеб сървъра.

Четенето с getenv избягва целия този клас объркване, а скрипт-обвивка, който изчиства средата преди извикване на интерпретатора, го връща в друга форма.

Съхранявайте асоциация, а не обновяване на ред

Решете коя стойност е нужна на записа, преди да го напишете. Ако целта е да отбележите откъде е дошла сесията, съхранете външната крайна точка и я означете като наблюдение. Ако целта е да свържете сесия с адрес на тунел за времетраенето на връзката, съхранете адреса от пула и го обвържете със сесията.

Обновявайте по удостоверената идентичност и текущата сесия, а не по всеки ред, който споделя адрес на тунел, защото адресите от пула се преизползват и закъсняло събитие за прекъсване иначе може да презапише данните на по-нова връзка. Работете с IPv6 изрично, вместо тихо да записвате само стойността за IPv4. Ред с NULL външен адрес е по-добър от ред с грешен, защото първият е видимо непълен.

Обвържете записа към идентификатора на сесията, който OpenVPN предоставя, така че повторното свързване да създава нов запис, а не да редактира стария. Използвайте параметризирани изрази и акаунт само с разрешенията, които операцията изисква. Hook-ът работи с правомощията на демона, така че небрежна заявка е по-широк проблем от грешен ред в журнала.

Диагностицирайте, без да изхвърляте средата

Записвайте кои имена са присъствали, кой етап е работил и кой интерпретатор е използван. Не отпечатвайте цялата среда, защото процесът на hook-а може да наследи несвързани стойности, които не бива да попадат в журнал.

Проверете една връзка от край до край: прочетете външната крайна точка, прочетете назначения адрес и потвърдете двете спрямо собствения изглед на сървъра за тази сесия. След като двойката е потвърдена за един клиент, асоциацията може да се вярва и другаде.

Подобни статии