Hook PHP của OpenVPN: trusted_ip so với ifconfig_pool_remote_ip
Hai địa chỉ với hai ý nghĩa khác nhau, được đọc bởi một tiến trình mà bạn không khởi chạy. Biến hook là gì, và tại sao một $_ENV rỗng không chứng minh được gì.
Một mảng $_ENV rỗng trong script hook có vẻ là bằng chứng rằng OpenVPN không truyền gì cả. Thường thì nó chứng minh một điều hoàn toàn khác: PHP được cấu hình để không điền siêu biến toàn cục đó, và các giá trị vẫn nằm trong môi trường tiến trình suốt thời gian. Kết luận sai thứ hai tinh tế hơn, vì hai biến địa chỉ trong hook kết nối mang ý nghĩa khác nhau và được dùng thay thế cho nhau. Cả hai sai lầm đều tốn một buổi chiều nếu bạn bắt đầu từ cái sai.
Hai địa chỉ, hai khẳng định khác nhau
Điểm cuối bên ngoài là điều máy chủ quan sát khi máy khách kết nối, có sẵn dưới dạng trusted_ip cho IPv4 và trusted_ip6 cho IPv6. Địa chỉ ảo là thứ mà nhóm địa chỉ gán cho phiên này, có sẵn dưới dạng ifconfig_pool_remote_ip.
Chúng trả lời những câu hỏi khác nhau, và một bản ghi thường cần một trong hai chứ không phải cả hai. Cái đầu tiên là nơi kết nối đến từ, có thể là một địa chỉ NAT dùng chung cho hàng trăm người. Cái thứ hai là nơi phiên này sống bên trong đường hầm, và nó có thể được gán lại cho một phiên khác sau này. Nhầm lẫn hai thứ sẽ tạo ra các bản ghi trông hợp lý nhưng sai.
Một lần đọc tối thiểu trông như thế này.
$outer4 = getenv('trusted_ip');
$outer6 = getenv('trusted_ip6');
$inner = getenv('ifconfig_pool_remote_ip');
$outer = $outer4 !== false ? $outer4 : $outer6;Không giá trị nào nhận dạng một con người. Một là quan sát mạng, cái kia là hợp đồng thuê, và một bản ghi coi một trong hai là định danh thiết bị ổn định sẽ sai ngay lần đầu máy khách kết nối lại từ mạng khác hoặc nhận địa chỉ nhóm khác. Chọn trường theo câu hỏi mà bản ghi phải trả lời, rồi ghi câu hỏi đó bên cạnh cột.
Kiểm tra cách PHP được khởi chạy, không phải shell của bạn
Hook chạy như con của tiến trình nền VPN với môi trường do tiến trình nền tạo ra. Shell tương tác của bạn có môi trường khác, và chạy script bằng tay là kiểm tra môi trường của shell chứ không phải của hook.
Bắt đầu bằng việc xác nhận hook thực sự kích hoạt ở giai đoạn bạn mong đợi. Một script gắn vào giai đoạn sai, hoặc một script chưa bao giờ chạy vì chỉ thị trỏ tới đường dẫn khác, cho đúng triệu chứng giống như một biến bị thiếu. Thêm một dòng đánh dấu có chủ đích ở đầu script và xác nhận nó xuất hiện trước khi bạn kiểm tra bất cứ thứ gì khác. Một dòng có dấu thời gian trong nhật ký phân biệt «chưa bao giờ chạy» với «chạy mà không có giá trị».
Sau đó xác nhận lần gọi đó dùng trình thông dịch nào và tệp cấu hình nào. Sửa cấu hình PHP cho một máy chủ web không thay đổi gì ở tiến trình CLI do OpenVPN khởi chạy, và cả hai có thể nạp những tệp php.ini hoàn toàn khác nhau.
Tại sao một $_ENV rỗng không chứng minh được gì
PHP tài liệu getenv mô tả việc đọc trực tiếp môi trường tiến trình, trả về false khi không có tên. Siêu biến $_ENV được điền riêng, và chỉ thị variables_order quyết định siêu biến nào được điền.
Nếu chỉ thị đó bỏ qua E, $_ENV vẫn rỗng bất kể môi trường chứa gì. Đoạn mã đánh chỉ mục vào nó sau đó báo một biến bị thiếu mà thực tế đang có, và cuộc điều tra hướng về OpenVPN trong khi câu trả lời nằm trong php.ini. Hãy kiểm tra chỉ thị riêng cho cấu hình CLI, không phải cho máy chủ web.
Đọc bằng getenv tránh toàn bộ sự nhầm lẫn này, và một script bọc dọn sạch môi trường trước khi gọi trình thông dịch lại đưa nó trở lại dưới một dạng khác.
Lưu một liên kết, không phải cập nhật dòng
Quyết định bản ghi cần giá trị nào trước khi ghi nó. Nếu mục tiêu là ghi lại phiên đến từ đâu, hãy lưu điểm cuối bên ngoài và gắn nhãn đó là quan sát. Nếu mục tiêu là ánh xạ một phiên tới một địa chỉ đường hầm trong suốt thời gian kết nối, hãy lưu địa chỉ nhóm và khóa nó với phiên.
Cập nhật theo danh tính đã xác thực và phiên hiện tại thay vì theo từng dòng chia sẻ một địa chỉ đường hầm, vì địa chỉ nhóm được tái sử dụng và một sự kiện ngắt kết nối muộn có thể ghi đè dữ liệu của kết nối mới hơn. Xử lý IPv6 một cách rõ ràng thay vì âm thầm chỉ ghi giá trị IPv4. Một dòng có địa chỉ bên ngoài NULL tốt hơn một dòng có địa chỉ sai, vì dòng đầu tiên thiếu rõ ràng.
Khóa việc ghi với định danh phiên mà OpenVPN cung cấp để lần kết nối lại tạo bản ghi mới thay vì sửa bản ghi cũ. Dùng câu lệnh có tham số và một tài khoản chỉ có các quyền mà thao tác cần. Hook chạy với quyền của tiến trình nền, nên một truy vấn bất cẩn là vấn đề rộng hơn một dòng nhật ký sai.
Chẩn đoán mà không đổ môi trường ra
Ghi nhật ký những tên nào đã có, giai đoạn nào đã chạy và trình thông dịch nào đã dùng. Đừng in toàn bộ môi trường, vì một tiến trình hook có thể thừa hưởng những giá trị không liên quan không nên kết thúc trong tệp nhật ký.
Xác minh một kết nối từ đầu đến cuối: đọc điểm cuối bên ngoài, đọc địa chỉ được cấp, và đối chiếu cả hai với góc nhìn của chính máy chủ về phiên đó. Khi cặp đã được xác nhận cho một máy khách, có thể tin cậy liên kết ở nơi khác.