Hook client-connect của OpenVPN: địa chỉ của bạn thực sự đi đâu
Một script client-connect không thể trả về địa chỉ bằng cách in nó. Hãy xem tệp tạm của hook, trạng thái thoát và cấu trúc liên kết quyết định IP của máy khách như thế nào.
Trả về một địa chỉ từ script client-connect có vẻ như phải đặt IP của máy khách. Nhưng không: kênh duy nhất của hook tới máy chủ là một tệp tạm có đường dẫn đến như đối số cuối cùng của script, và địa chỉ phải được ghi ở đó theo cú pháp ifconfig-push. Một script in địa chỉ hoặc thoát với số không mà không ghi gì sẽ tạo ra một máy khách đã kết nối với địa chỉ từ pool, và nhật ký máy chủ trông hoàn toàn khỏe mạnh.
Sự nhầm lẫn là hợp lý, vì một số hook khác thực sự trả lời qua mã thoát hoặc biến môi trường. Cái này có hợp đồng riêng, và hợp đồng bắt đầu bằng tên tệp.
Hook ghi tệp, không phải giá trị trả về
Khai báo gồm hai dòng: script-security 2 để cho phép gọi, sau đó client-connect /etc/openvpn/server/assign-address.sh. Khi một máy khách xác thực, máy chủ chạy script đó với đường dẫn tệp được tạo nối thêm làm đối số cuối cùng, chỉ là $1 nếu khai báo không truyền đối số bổ sung riêng. Mọi thứ áp dụng cho máy khách đó đều đi vào tệp đó dưới dạng chỉ thị thông thường, mỗi dòng một cái, đúng như chúng sẽ xuất hiện trong cấu hình. Một lớp bao thêm tham số riêng sẽ dịch chuyển vị trí, và triệu chứng cổ điển là script ghi vào đường dẫn trông giống --verbose.
Trạng thái thoát là nửa còn lại của hợp đồng. Số không nghĩa là chấp nhận và đọc tệp; bất cứ điều gì khác sẽ từ chối kết nối, và đó là cách một danh tính không được ánh xạ bị từ chối thay vì lặng lẽ quay lại pool. Hãy ghi chỉ thị đầy đủ trước khi trả về thành công, để một tệp ghi dở không bao giờ trở thành cấu hình của máy khách.
Hai chỉ thị đáng chú ý vì chúng tương tác với mọi thứ khác. ifconfig-push cố định địa chỉ, trong khi route được đẩy cho máy khách biết những gì có thể tiếp cận qua đường hầm; trả về cái đầu và quên cái sau và bạn nhận được một máy khách có địa chỉ mà không có nơi nào để đi. Thứ tự trong tệp không quan trọng, nhưng tính đầy đủ thì có. Một hook đẩy tuyến cho một tiền tố mà không ngang hàng nào có thể tới là cùng một lỗi nhìn từ đầu bên kia.
Đầu vào đến qua biến môi trường: common_name, trusted_ip, ifconfig_pool_remote_ip và phần còn lại. Hãy coi tất cả như chuỗi từ bên ngoài máy chủ, không bao giờ như mảnh shell.
Ánh xạ địa chỉ là chính sách, không phải số học
Một lối tắt hấp dẫn là phân tích tên chứng chỉ và dùng các chữ số của nó làm octet cuối. Đó không phải là bộ cấp phát, và nó thất bại theo những cách thông thường: hai tên có cùng hậu tố xung đột, một tên kết thúc bằng 300 không phải là địa chỉ, và một chứng chỉ được quản trị viên đổi tên sẽ âm thầm di chuyển thiết bị. Xác thực tư cách thành viên subnet, dải máy chủ có thể dùng, địa chỉ dành riêng và tính duy nhất trong mỗi lần gọi, và giữ ánh xạ trong một bảng mà con người có thể đọc.
Ai kiểm soát tên thì kiểm soát địa chỉ, vì vậy hãy quyết định common_name thực sự đại diện cho điều gì trong triển khai này. Khi bật username-as-common-name, danh tính là thông tin đăng nhập chứ không phải chủ thể chứng chỉ. Không bao giờ chuyển giá trị đó vào đánh giá shell, và không bao giờ để máy khách ảnh hưởng đến đường dẫn tệp.
Một bộ cấp phát dựa trên sổ đăng ký phải chịu được đồng thời. Đặt trước địa chỉ một cách nguyên tử, xử lý ghi thất bại mà không nhận một máy khách cấu hình dở, và gắn thẻ mỗi cấp phát bằng kết nối sở hữu nó, để một lần ngắt kết nối muộn từ phiên cũ không thể giải phóng địa chỉ mà phiên mới hơn đã giữ. Nhiều phiên bản máy chủ chia sẻ một pool khiến yêu cầu đó sắc nét hơn chứ không phải tùy chọn.
Cấu trúc liên kết quyết định ý nghĩa của ifconfig-push
Với topology subnet trên 10.77.0.0/24, ifconfig-push 10.77.0.20 255.255.255.0 là một địa chỉ cộng với mặt nạ mạng của nó. Dưới topology net30 đối số thứ hai hoàn toàn không phải mặt nạ mà là địa chỉ của ngang hàng, vì vậy sao chép dạng subnet sang máy chủ net30 cho bạn một máy khách kết nối được mà không truyền được lưu lượng. Thay đổi cấu trúc liên kết một cách có chủ đích, không bao giờ để một ví dụ trông nhất quán. Một máy chủ đã chạy net30 có máy khách đang sống trên cách đánh địa chỉ cũ, nên việc chuyển đổi là một cuộc di chuyển có cửa sổ bảo trì, không phải chỉnh sửa một dòng.
Địa chỉ tĩnh phải nằm ngoài pool động và ngoài mọi phép gán tĩnh khác, kể cả những địa chỉ do các tệp client-config-dir thông thường cấp. Nếu hai cơ chế có thể tạo ra cùng một địa chỉ cho các máy khách khác nhau, một trong số chúng cuối cùng sẽ làm vậy.
Kiểm tra bốn trường hợp trước khi tin tưởng nó
Chạy các kiểm tra tương tự trên danh tính đã ánh xạ, chưa ánh xạ, kết nối lại và lỗi sổ đăng ký mô phỏng. openvpn --config client.ovpn --verb 4 hiển thị địa chỉ được cấp trong phản hồi push, và trên máy chủ grep -A2 PUSH_REPLY /var/log/openvpn/openvpn.log xác nhận những gì thực sự được gửi. Với danh tính chưa ánh xạ, kết quả mong đợi là một kết nối bị từ chối, không phải địa chỉ từ pool.
Sau đó kiểm tra thư mục mà daemon ghi các tệp tạm đó. Script chạy trong ngữ cảnh dịch vụ bị hạ quyền, vì vậy một đường dẫn mà root có thể ghi nhưng daemon thì không sẽ biến mỗi kết nối thành từ chối với lỗi quyền bị chôn vài dòng bên dưới trong nhật ký.
Cấp phát không phải là ủy quyền: một địa chỉ được ghim vẫn không cấp quyền truy cập tới mọi đích phía sau máy chủ. Giữ chính sách định tuyến và tường lửa trong lớp riêng của nó, và xác minh nó với địa chỉ bạn vừa cố định.