훅 스크립트에서 $_ENV 배열이 비어 있으면 OpenVPN 이 아무것도 넘기지 않았다는 증거처럼 느껴집니다. 대개는 전혀 다른 것의 증거로, PHP가 그 슈퍼글로벌을 채우지 않도록 설정되어 있었고, 값은 내내 프로세스 환경에 있었습니다. 두 번째 잘못된 결론은 더 미묘한데, 연결 훅의 두 주소 변수는 서로 다른 것을 뜻하면서 바꿔 쓰이기 때문입니다. 두 실수 모두 잘못된 쪽에서 시작하면 반나절을 잡아먹습니다.

두 주소, 두 가지 다른 주장

바깥 끝점은 클라이언트가 연결할 때 서버가 관측한 것이며, IPv4에는 trusted_ip, IPv6에는 trusted_ip6 로 제공됩니다. 가상 주소는 풀이 이 세션에 할당한 것이며, 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 설정을 고쳐도 OpenVPN이 띄운 CLI 프로세스에는 아무 영향이 없고, 둘은 전혀 다른 php.ini 파일을 읽어 들일 수 있습니다.

빈 $_ENV가 아무것도 증명하지 않는 이유

PHP의 getenv 레퍼런스 는 프로세스 환경을 직접 읽는 방법을 설명하며, 이름이 없으면 false 을 돌려줍니다. $_ENV 슈퍼글로벌은 따로 채워지고, 어떤 슈퍼글로벌이 채워질지는 variables_order 지시문이 결정합니다.

그 지시문이 E 을 빼면 환경에 무엇이 있든 $_ENV 은 비어 있습니다. 그것을 인덱싱하는 코드는 실제로 존재하는 변수를 없다고 보고하고, 답은 php.ini 에 있는데도 조사는 OpenVPN 쪽으로 향합니다. 지시문은 CLI 설정에 대해서 확인하십시오, 웹 서버가 아니라.

getenv 로 읽으면 이런 혼동의 부류 전체를 피할 수 있지만, 인터프리터를 부르기 전에 환경을 지우는 래퍼 스크립트는 다른 형태로 그것을 되살립니다.

행 업데이트가 아니라 연관을 저장하십시오

쓰기 전에 기록에 어떤 값이 필요한지 정하십시오. 목적이 세션이 어디서 왔는지 적는 것이라면 바깥 끝점을 저장하고 관측으로 표시하십시오. 연결이 유지되는 동안 세션을 터널 주소에 대응시키는 것이 목적이라면 풀 주소를 저장하고 세션에 연결하십시오.

풀 주소는 재사용되고 늦게 도착한 연결 해제 이벤트가 더 새로운 연결의 데이터를 덮어쓸 수 있으므로, 터널 주소를 공유하는 모든 행이 아니라 인증된 신원과 현재 세션을 기준으로 갱신하십시오. IPv4 값만 조용히 쓰지 말고 IPv6를 명시적으로 다루십시오. 바깥 주소가 NULL인 행은 앞쪽이 눈에 띄게 불완전하므로 잘못된 값이 든 행보다 낫습니다.

다시 연결할 때 예전 기록을 고치는 대신 새 기록을 만들도록 쓰기를 OpenVPN이 주는 세션 식별자에 묶으십시오. 매개변수화된 문과 작업에 필요한 권한만 가진 계정을 쓰십시오. 훅은 데몬의 권한으로 돌기 때문에 부주의한 쿼리는 잘못된 로그 한 줄보다 큰 문제입니다.

환경을 쏟아내지 않고 진단하십시오

어떤 이름이 있었는지, 어느 단계가 돌았는지, 어느 인터프리터가 쓰였는지 기록하십시오. 환경 전체를 출력하지 마십시오, 훅 프로세스는 로그 파일에 남아서는 안 될 무관한 값을 물려받을 수 있습니다.

연결 하나를 끝에서 끝까지 검증하려면, 바깥 끝점을 읽고 할당된 주소를 읽고, 둘 다 그 세션에 대한 서버 자신의 시각과 대조해 확인하십시오. 한 클라이언트에서 짝이 확인되면 그 연관은 다른 곳에서도 신뢰할 수 있습니다.

관련 글