Một yêu cầu đến ứng dụng của bạn mang hai loại bằng chứng về địa chỉ: peer đã mở kết nối mạng và một trường HTTP khẳng định địa chỉ của một máy khách trước đó. Chúng trả lời những câu hỏi khác nhau. Peer socket được quan sát, còn tiêu đề do người viết nó khẳng định, và không bên nào nên âm thầm thay thế bên kia trong nhật ký hay trong quy tắc truy cập. Phần so sánh dưới đây giữ chúng tách biệt, rồi cho thấy cách bố trí duy nhất mà tiêu đề trở nên dùng được.

Mô tả đường đi trước khi so sánh bất cứ điều gì:

Client -> approved reverse proxy -> application origin

Trong cách bố trí đó, peer socket của nguồn thường là proxy, và một tiêu đề chuyển tiếp có thể mang khẳng định của proxy về máy khách. Giá trị của nó đến từ quan hệ được kiểm soát với proxy đó, không phải từ tên của tiêu đề.

Hai loại bằng chứng về địa chỉ

Peer socket là một sự thật về một kết nối TCP: có thứ gì đó đã hoàn tất bắt tay từ địa chỉ đó. Nó không nhất thiết là người, thiết bị hay tài khoản mà bạn quan tâm, vì VPN hoặc lối ra Tor có thể là nguồn mà một dịch vụ quan sát một cách hợp pháp. Tuy vậy nó vẫn là địa chỉ duy nhất mà chính máy chủ đã xác minh, và đó là toàn bộ giá trị của nó.

Trường chuyển tiếp là siêu dữ liệu về một chuỗi. X-Forwarded-For, X-Real-IP và trường chuẩn hóa Forwarded có thể do bất kỳ máy khách nào chạm tới một điểm cuối phản chiếu chúng viết, nên độ tin cậy của chúng hoàn toàn phụ thuộc vào việc ai được phép đặt chúng.

Giữ cả hai trong ngữ cảnh yêu cầu dưới những tên khác nhau. Một ứng dụng ghi đè peer bằng tiêu đề sẽ mất khả năng tái dựng một lỗi tin cậy về sau, và đó chính là lúc bạn cần đến nó.

Tiêu đề không bao giờ định tuyến lại kết nối

Viết một địa chỉ vào trường chuyển tiếp không thay đổi nguồn của kết nối TCP đến máy chủ, và không thay đổi định tuyến ở bất kỳ đâu trên đường đi. Định tuyến VPN thông thường hoặc NAT nguồn chuyển lưu lượng mà không có bất kỳ tiêu đề HTTP nào. Tương tự, một cổng trung chuyển không viết lại một trao đổi HTTPS được bảo vệ đúng cách mà không thay đổi cách bố trí điểm cuối TLS.

Sai lầm ngược lại cũng phổ biến: HTTPS không làm cho một tiêu đề chuyển tiếp do máy khách cung cấp thành đúng. Nó bảo vệ việc vận chuyển một khẳng định sai hệt như một khẳng định đúng.

Nếu một đồng nghiệp đề xuất thay đổi tiêu đề để sửa một vấn đề định tuyến, chẩn đoán đã đi sai. Hãy sửa đường đi, hoặc sửa cấu hình proxy ghi tiêu đề.

Hãy đặt tên proxy được phép khẳng định

Hai quy tắc làm cho một trường chuyển tiếp dùng được, và cả hai là cấu hình chứ không phải mã. Biên chuẩn hóa hoặc bỏ mọi thứ đến từ bên ngoài, theo hành vi được ghi tài liệu của nó cho những trường đó. Sau đó nguồn lấy địa chỉ thay thế từ đường đi proxy mà bạn đã đặt tên và không từ đâu khác. Quy tắc thứ hai chỉ đúng khi máy khách không thể đến nguồn bằng cách khác, vì một nguồn trả lời cả yêu cầu trực tiếp lẫn yêu cầu qua proxy không biết mình đang phục vụ cái nào.

Mô-đun IP thực của NGINX cho thấy sự phân tách rõ ràng. set_real_ip_from nêu tên những người gửi mà khẳng định của họ được tính, và real_ip_header cho biết trường nào mang nó; cái đầu thực hiện sự tin cậy, cái sau chỉ nói nơi cần nhìn.

set_real_ip_from 10.20.0.0/24;
real_ip_header X-Forwarded-For;
# real_ip_recursive off - take the rightmost value in the field
# real_ip_recursive on  - walk the list back past every trusted address

Chỉ một chỉ thị chọn tiêu đề vẫn chưa xác lập gì về việc ai đã gửi giá trị.

An toàn vận chuyển phải chạy suốt đường đi giữa các thành phần bạn tin cậy. Một biên chuẩn hóa đúng cũng mất giá trị đó ngay khi một chặng không được bảo vệ ở phía dưới cho phép người khác sửa khẳng định trong lúc nó đang di chuyển.

Xử lý có chủ đích các chuỗi nhiều chặng

Nhiều proxy cần một mô hình chuỗi rõ ràng. Đừng lấy giá trị tận cùng bên trái hay bên phải được phân tách bằng dấu phẩy chỉ vì một bài blog đã làm thế; hãy tìm ra proxy nào của bạn thêm vào, cái nào thay thế và cái nào giữ lại trường đi vào. Ví dụ, NGINX có thể duyệt danh sách ngược lại so với tập tin cậy của nó và dừng ở địa chỉ đầu tiên mà nó không sở hữu, và đó là quy tắc của sản phẩm đó, không phải một luật mà mọi khuôn khổ đều tuân theo. Hãy đọc tài liệu của proxy bạn dùng với đúng hai câu hỏi: nó chọn giá trị nào, và nó tin những người gửi nào?

Hãy ghi chuỗi ra: thứ tự chặng, chặng nào đặt trường và chặng nào loại bỏ các bản sao đi vào. Sau đó giữ ghi chú đó bên cạnh cấu hình proxy, không chỉ trong phiếu. Sau đó hãy kiểm tra bằng cách gửi một yêu cầu với tiêu đề giả qua quy trình xác minh đã được phê duyệt và xác nhận rằng nguồn bỏ qua nó.

Khi bạn thêm một chặng, hãy xem lại tài liệu đó. Một bộ cân bằng tải mới được chèn trước proxy tin cậy có thể thay đổi địa chỉ nào thắng mà không ai sửa ứng dụng.

Giữ cả hai quan sát trong nhật ký

Ở nơi chẩn đoán được cho phép, hãy ghi nhật ký peer của kết nối và địa chỉ máy khách đã chuẩn hóa thành hai trường riêng biệt, và chỉ thêm siêu dữ liệu chuyển tiếp mà mục đích thực sự cần. Sau đó chứng minh việc triển khai bằng hai yêu cầu: một qua proxy mà lẽ ra phải ghi cả hai giá trị một cách hợp lý, và một nỗ lực trực tiếp đến nguồn phải bị từ chối.

Hãy nhớ cặp đôi này có nghĩa gì. Tiêu đề thêm ngữ cảnh do một thành phần mà bạn đã chọn tin cậy cung cấp; peer vẫn là địa chỉ duy nhất mà máy chủ của bạn thực sự thấy. Không cái nào là bằng chứng về danh tính cá nhân, và một thiết kế coi bất kỳ cái nào là bằng chứng sẽ sai về ai đó.

Bài viết liên quan