Trỏ một máy chủ ảo Subversion tới địa chỉ VPN thay đổi trang nào trả lời một yêu cầu, không phải ai được phép gửi nó. Việc kiểm tra truy cập diễn ra sau đó, theo các quy tắc trong phần khớp với URL, và tên máy chủ không bao giờ đi vào quyết định đó. Nếu ServerName là thay đổi duy nhất của bạn, kho lưu trữ vẫn dễ truy cập đúng như hôm qua. Hai câu hỏi riêng biệt phải được trả lời trong cấu hình: socket nào đã nhận kết nối và yêu cầu mang danh tính nào.

ServerName thực sự quyết định điều gì

Lưu trữ ảo dựa trên tên so sánh tiêu đề Host với các mục ServerName và ServerAlias, chọn một máy chủ và để nó xử lý yêu cầu. Bản thân kết nối đã được một socket Listen thuộc về máy chủ chấp nhận trước đó, không phải máy chủ ảo. Vì vậy một cái tên trông riêng tư không mang lại bảo vệ nào: bất kỳ ứng dụng khách nào chạm tới socket đều có thể gửi tiêu đề Host đó. Tên là một khóa định tuyến, và khóa định tuyến do bên gọi chọn.

Bạn có thể xem ánh xạ mà không cần đoán. apachectl -S in ra từng máy chủ, cổng và tên của nó, và đánh dấu cái nào là mặc định cho địa chỉ.

RequireAll là vùng chứa khiến cả hai kiểm tra trở thành bắt buộc

Apache 2.4 bọc các chỉ thị Require của một phần trong một RequireAny ngầm, nên hai chỉ thị trần có nghĩa là chỉ cần một trong hai. Thêm vùng chứa và ý nghĩa đảo ngược:

<Location /svn/repo>
    AuthType Basic
    AuthName "Subversion"
    AuthBasicProvider file
    AuthUserFile /etc/apache2/svn.htpasswd
    <RequireAll>
        Require ip 10.8.0.0/24
        Require valid-user
    </RequireAll>
</Location>

RequireAll yêu cầu cả hai điều kiện: một địa chỉ nguồn trong dải đường hầm và một người dùng mà kho lưu trữ chấp nhận. Đó là điều VPN-riêng nên có nghĩa với một URL Subversion. Tài liệu tham chiếu mod_authz_core ghi lại các quy tắc của vùng chứa. Giữ khối bên trong Location hiện có của kho lưu trữ và để nguyên các chỉ thị DAV đang hoạt động, vì đoạn này không thay thế AuthType, tệp mật khẩu hay việc phân quyền ở cấp đường dẫn.

Kiểm tra nguồn đến từ mod_authz_host, nên hãy xác nhận nó đã được nạp trước khi gỡ lỗi bất cứ điều gì khác: apachectl -M | grep authz_host.

Địa chỉ mà Apache đánh giá là địa chỉ socket

Require ip so sánh với địa chỉ mà Apache đã ghi lại cho kết nối, và đó không phải lúc nào cũng là địa chỉ mà ứng dụng khách nghĩ mình có.

Khi VPN định tuyến địa chỉ của nó không qua biên dịch, Apache thấy địa chỉ đường hầm và 10.8.0.0/24 khớp. Khi một cổng vào biên dịch, Apache thấy cổng vào và quy tắc lặng lẽ không khớp với gì; điều tương tự xảy ra sau một bộ cân bằng tải kết thúc TLS trước máy chủ. Với trường hợp đó có mod_remoteip. RemoteIPHeader X-Forwarded-For cùng với RemoteIPTrustedProxy cho bộ cân bằng thay thế địa chỉ đã ghi, và chỉ khi đó dải mới có thứ để so sánh.

Tin vào một tiêu đề chuyển tiếp tùy ý còn tệ hơn là không có quy tắc nào. Bất kỳ ứng dụng khách nào cũng có thể gửi X-Forwarded-For chứa 10.8.0.9 và thỏa mãn một kiểm tra dải chưa bao giờ được neo vào một chặng đáng tin.

Xếp lớp trình lắng nghe và chính sách kho lưu trữ

Ràng buộc địa chỉ là một kiểm soát riêng và thường đơn giản hơn. Listen 10.8.0.1:443 quyết định những socket nào tồn tại, và một yêu cầu không thể chọn máy chủ trên một socket chưa bao giờ được mở. Cái giá là thứ tự khởi động: nếu giao diện đường hầm đang xuống khi Apache khởi động, việc ràng buộc thất bại và dịch vụ không lên. Hãy ghép nó với thứ tự đơn vị, hoặc ràng buộc vào một địa chỉ tồn tại độc lập với đường hầm.

Quyền trên đường dẫn vẫn nằm trong AuthzSVNAccessFile. Một tài khoản hợp lệ cho trang không phải là cùng một cấp quyền như quyền ghi vào đường dẫn dự án, và quy tắc mạng không thay đổi điều đó.

Chú ý đến việc hợp nhất phần khi khối nằm trong một tệp được đưa vào. Apache hợp nhất các vùng chứa phân quyền qua các phần lồng nhau và phần khớp cụ thể nhất có thể thay thế yêu cầu thay vì bổ sung vào nó, nên một quy tắc trên /svn có thể không tới được /svn/repo/trunk một khi một phần hẹp hơn định nghĩa phần của riêng nó.

Chứng minh cả hai lần từ chối trước khi gọi là xong

Hãy thử bốn yêu cầu, không phải một. Bên trong VPN với tài khoản hợp lệ, bạn sẽ nhận được danh sách kho lưu trữ. Bên trong VPN với mật khẩu sai, bạn sẽ nhận 401 thay vì danh sách. Từ bên ngoài VPN với thông tin đăng nhập hợp lệ, bạn sẽ nhận 403, và cùng yêu cầu công khai đó tới một tên máy chủ khác cũng phải thất bại theo cách tương tự.

Một lệnh cho mỗi trường hợp là đủ: curl -sI -u user:pass https://svn.example.com/svn/repo/, rồi đọc dòng trạng thái. Lặp lại trường hợp hoạt động qua ứng dụng khách thật nữa, vì svn info thực hành các phương thức DAV mà commit và cập nhật sẽ dùng.

Nếu bất kỳ kết quả nào trong bốn kết quả không khớp với chính sách bạn dự định, cấu hình chưa xong, và đổi tên máy chủ sẽ không thay đổi điều đó.

Bài viết liên quan