Порожній масив $_ENV у скрипті хука здається доказом того, що OpenVPN нічого не передав. Зазвичай він доводить зовсім інше: PHP було налаштовано не заповнювати цю суперглобальну змінну, а значення весь час лежали в середовищі процесу. Другий хибний висновок тонший, бо дві змінні адреси в хуку з'єднання означають різні речі, а використовуються як взаємозамінні. Обидві помилки коштують півдня, якщо почати з неправильної.

Дві адреси, два різні твердження

Зовнішня кінцева точка — це те, що сервер спостерігав під час підключення клієнта, доступна як 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, а не свою оболонку

Хук працює як дочірній процес демона VPN із середовищем, яке створює демон. У вашої інтерактивної оболонки воно інше, і запуск скрипта вручну перевіряє середовище оболонки, а не хука.

Почніть із підтвердження, що хук справді спрацював на тому етапі, якого ви чекали. Скрипт, прикріплений до неправильного етапу, або такий, що так і не запустився, бо директива вказує на інший шлях, дає точно такий самий симптом, як відсутня змінна. Додайте навмисний рядок-маркер на початок скрипта і переконайтеся, що він з'являється, перш ніж перевіряти будь-що інше. Один рядок із позначкою часу в журналі відрізняє «так і не запускався» від «запускався без значення».

Потім переконайтеся, який інтерпретатор і який файл конфігурації використовує цей виклик. Правка конфігурації PHP для вебсервера нічого не змінює в процесі CLI, запущеному OpenVPN, і обидва можуть завантажувати зовсім різні файли php.ini.

Чому порожній $_ENV нічого не доводить

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

Якщо ця директива пропускає E, $_ENV залишається порожнім незалежно від того, що містить середовище. Код, який до нього звертається, тоді повідомляє про відсутню змінну, яка насправді є, і розслідування йде в бік OpenVPN, тоді як відповідь лежить у php.ini. Перевіряйте директиву саме для конфігурації CLI, а не для вебсервера.

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

Зберігайте зв'язок, а не оновлення рядка

Вирішіть, яке значення потрібне запису, перш ніж його писати. Якщо мета — зазначити, звідки прийшов сеанс, збережіть зовнішню кінцеву точку і позначте її як спостереження. Якщо мета — пов'язати сеанс з адресою тунелю на час з'єднання, збережіть адресу з пулу і прив'яжіть її до сеансу.

Оновлюйте за автентифікованою особою та поточним сеансом, а не за кожним рядком з тією самою адресою тунелю, бо адреси з пулу використовуються повторно, і пізня подія від'єднання інакше може перезаписати дані новішого з'єднання. Обробляйте IPv6 явно, а не пишіть мовчки лише значення IPv4. Рядок із NULL у зовнішній адресі кращий за рядок із неправильною, бо перший видимо неповний.

Прив'язуйте запис до ідентифікатора сеансу, який надає OpenVPN, щоб перепідключення створювало новий запис, а не редагувало старий. Використовуйте параметризовані запити та обліковий запис лише з тими правами, які потрібні операції. Хук працює з повноваженнями демона, тому недбалий запит — проблема ширша, ніж неправильний рядок журналу.

Діагностуйте, не вивалюючи середовище

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

Перевірте одне з'єднання від початку до кінця: прочитайте зовнішню кінцеву точку, прочитайте видану адресу і звірте обидві з власним уявленням сервера про цей сеанс. Щойно пару підтверджено для одного клієнта, зв'язку можна довіряти і в інших місцях.

Схожі статті