Chuyển tiếp các byte đã mã hóa mà không bao giờ giữ chứng chỉ là việc một relay TLS passthrough làm, và cách bố trí này vừa tiện lợi vừa hơi khó hiểu. Vì không có gì được giải mã, không có thứ gì có dạng HTTP để lọc, nên khối location thông thường và các quy tắc truy cập của nó không có tác dụng ở đây. Quyết định mà NGINX có liên quan đến chính kết nối: peer mạng nào đã gõ cửa, và có nên chuyển tiếp peer đó hay không.

Quyết định nằm ở stream, không phải HTTP

Trong ngữ cảnh stream, NGINX làm việc với các phiên TCP. Nó thấy địa chỉ peer của kết nối và có thể áp dụng các quy tắc allow và deny có thứ tự lên đó trước khi bất kỳ byte nào đến backend. Đây là một quyết định chấp nhận đầy đủ và không cần khóa riêng, chứng chỉ hay phân tích HTTP.

MechanismWhat it decidesWhere it lives
stream allow/denyWhether this TCP peer is relayedstream server block
ssl_preread mapWhich backend a named connection goes tostream, with the preread module
HTTP location ruleWhether an HTTP request is servedhttp server block

Ba dòng đó không bao giờ thay thế lẫn nhau. Sao chép một chỉ thị truy cập HTTP vào bất kỳ tệp nào đề cập đến cổng 443 không thay đổi gì, vì máy chủ stream không bao giờ đọc ngữ cảnh http.

Chấp nhận kết nối trước khi chuyển tiếp

Giả sử có một bản cài đặt hiện có với các mô-đun stream và stream-access, các máy khách VPN giữ địa chỉ nguồn trong 10.90.0.0/24, và một backend tại 192.168.50.20:443 đã phục vụ danh tính HTTPS dự định.

stream {
    server {
        listen 443;

        allow 10.90.0.0/24;
        deny all;

        proxy_pass 192.168.50.20:443;
    }
}

Hãy đọc đây như một mảnh của listener mới, không phải sự thay thế trực tiếp của một cấu hình đang chạy. Trước tiên hãy xem lại các listener và include hiện có, vì listener thứ hai trên một cổng đã bị chiếm sẽ thất bại khi reload, không phải tại thời điểm yêu cầu.

Hãy chú ý điều gì còn thiếu: không có listen ... ssl, không có chỉ thị chứng chỉ. NGINX chuyển tiếp luồng đã mã hóa, và backend kết thúc TLS và trình bày chứng chỉ mà máy khách xác thực. Một máy khách không vượt qua allowlist sẽ bị từ chối phiên TCP, không phải trang HTTP 403, và bất kỳ công cụ nào mong đợi mã trạng thái sẽ báo cáo điều gì đó vô ích.

allowlist bao gồm gì và không bao gồm gì

Nếu relay đã chọn backend theo tên máy chủ, ssl_preread và một map có thể tiếp tục công việc đó, miễn là mô-đun có sẵn. Tên vẫn do máy khách cung cấp, và việc trình bày một tên không chứng minh rằng máy khách đã tham gia VPN.

Quy tắc ví dụ bao gồm toàn bộ listener stream. Điều đó khiến nó không phù hợp với một điểm vào duy nhất phục vụ hỗn hợp các trang công khai và trang chỉ dành cho VPN, nơi cần có ngoại lệ theo từng tên; các listener riêng thường rõ ràng hơn một chính sách phụ thuộc tên mà không ai đọc được.

Cần nêu thêm hai khoảng trống. Việc khớp tiền tố không cho biết gói tin đến qua giao diện nào, và một quy tắc HTTP ở nơi khác không thể ràng buộc listener này. Cả hai là lý do để giữ chính sách ingress ở cấp máy chủ trong bức tranh thay vì coi một dòng allow là toàn bộ ranh giới. Hãy viết ranh giới thành hai kiểm soát phải đồng ý với nhau, để mọi thay đổi ở một trong hai đều được xem xét.

NGINX thực sự thấy địa chỉ của ai?

Một bộ cân bằng tải, một proxy khác hoặc source NAT có thể đặt một trung gian trước NGINX, nên peer quan sát được không phải địa chỉ bên trong của máy khách VPN. Hãy kiểm tra đường đi thực trước khi chọn tiền tố, vì một allowlist viết cho địa chỉ sai hoặc cho phép mọi người phía sau bộ dịch hoặc không cho ai cả.

Giao thức PROXY và xử lý IP thực là những câu trả lời hợp lệ, và chỉ nên được cấu hình cho những người gửi tương thích và được tin cậy rõ ràng. Cả hai cơ chế đều tin vào điều người gửi nói, và đó chính là lý do danh sách người gửi phải ngắn. Tin vào tiêu đề danh tính từ bất kỳ máy khách internet nào không làm cho thông tin nguồn trở nên đáng tin cậy trở lại; nó biến một lời từ chối đúng thành một sự chấp nhận giả mạo.

Kiểm tra cả hai kết quả trước khi reload

Xác thực cấu hình, reload, sau đó kiểm tra hai lần: một phiên mới được phép phải hoạt động và một phiên bị từ chối không được hoạt động. Giữ việc xác minh chứng chỉ backend bình thường trong bài kiểm tra được phép, vì một relay kết nối được nhưng không thể xác thực backend đã giải quyết một vấn đề và tạo ra vấn đề khác.

nginx -t
ss -tnp | grep ':443'

Kiểm tra cả tuyến đến backend và phản hồi một cách riêng biệt. Vượt qua allowlist chỉ chứng minh rằng NGINX đã chấp nhận phiên; nó không thể buộc một backend không thể truy cập trả lời, và không thể sửa một đường về đã thiếu trước khi bạn bắt đầu.

Bài viết liên quan