Điểm:0

NGINX định tuyến sai Máy chủ ảo khi tiêu đề Máy chủ chứa ký tự dấu hai chấm

lá cờ cn

Nginx.conf của tôi có một số phần "máy chủ" và phần máy chủ tổng hợp. Đây là một ví dụ nginx.conf để cung cấp cho bạn một ý tưởng:

dữ liệu www của người dùng;
worker_processes tự động;
worker_cpu_affinity tự động;
pid /run/nginx.pid;

sự kiện {
    worker_connections 4000;
    sử dụng epoll;
    chấp nhận tắt;
}

http {
    bao gồm /etc/nginx/mime.types;
    ứng dụng default_type/octet-stream;
    error_log /var/log/nginx/error.log;

    người phục vụ {
        nghe 80;

        server_name foo.com;

        địa điểm / {
            default_type văn bản/đơn giản;
            trả lại 200 "xin chào từ foo.com";
        }

        error_page 500 502 503 504 /500.html;
    }

    người phục vụ {
        nghe 80 default_server;
        tên máy chủ _;

        địa điểm / {
            trả lại 403 "xin lỗi";
        }
    }

}

Tôi hy vọng máy chủ sẽ trả về 403 nếu tiêu đề "Máy chủ" không phải là "foo.com".

Ai đó rõ ràng đang chạy Burp Suite trên máy chủ của tôi và tôi nhận thấy hành vi thú vị khi họ gửi tiêu đề "Host: foo.com:more-stuff-here": NGINX định tuyến yêu cầu đến phần "máy chủ" đầu tiên. Có vẻ như nó bỏ qua dấu hai chấm và mọi thứ sau nó trong giá trị tiêu đề.

Tôi có thể sao chép nó cục bộ với nginx.conf ở trên:

$ curl -H "Máy chủ: foo.com" http://127.0.0.1
xin chào từ foo.com

$ curl -H "Máy chủ: foo.com:unexpected-content" http://127.0.0.1
xin chào từ foo.com

$ curl -H "Máy chủ: bar.com" http://127.0.0.1
lấy làm tiếc

Tại sao NGINX làm điều này? Đây có phải là một hành vi dự kiến? Tôi nên thay đổi điều gì trong nginx.conf để đảm bảo các yêu cầu có tiêu đề "Host: foo.com:more-stuff-here" đi đến khối mặc định?

Cập nhật: Đối với bất kỳ ai nghiên cứu cùng một vấn đề, tôi cũng đã tạo một vé trong trình theo dõi vấn đề NGINX.

djdomi avatar
lá cờ za
gạch dưới làm mất hiệu lực tên máy chủ và đặt nó thành mặc định
Pēteris Caune avatar
lá cờ cn
@djdomi â tài liệu nginx cho biết dấu gạch dưới không có ý nghĩa đặc biệt, đó chỉ là một tên máy chủ không hợp lệ. Bit quan trọng là "default_server" trong lệnh nghe. Tôi bối rối tại sao nginx coi giá trị Máy chủ "foo.com:unexpected-content" là đối sánh trực tiếp với tên máy chủ "foo.com".
Điểm:3
lá cờ in

Định nghĩa cho tiêu đề máy chủ trong HTTP RFC chỉ ra rằng tiêu đề Máy chủ phải có dạng tổ cổng, với :Hải cảng là tùy chọn.

nginx xem mọi thứ sau dấu hai chấm là cổng cho máy chủ, nhưng nó không liên quan trong ngữ cảnh của bạn vì bạn chưa chỉ định khối máy chủ theo cách đó. Vì vậy, nó sử dụng kết quả phù hợp nhất mà nó có thể tìm thấy, Máy chủ lưu trữ không có "cổng".

Pēteris Caune avatar
lá cờ cn
Ah tôi thấy. Tôi có thể làm gì để sữa nó? Có thể làm cho nginx bỏ qua các yêu cầu có giá trị cổng không hợp lệ không?
lá cờ in
Có phải vấn đề của bạn là ứng dụng gửi yêu cầu không hợp lệ không hoạt động bình thường không? Nếu có, tôi sẽ sửa ứng dụng, nếu không, tôi sẽ bỏ qua nó.
lá cờ in
Tùy chọn duy nhất tôi có thể nghĩ đến là thử thêm `foo.com:*` làm server_alias vào máy chủ mặc định và hy vọng rằng nginx đủ thông minh để phân biệt nó.
Pēteris Caune avatar
lá cờ cn
Ứng dụng của tôi tạo cảnh báo về tiêu đề Máy chủ không hợp lệ. Tôi có thể tắt cảnh báo, nhưng tôi muốn NGINX có thể nắm bắt các yêu cầu không hợp lệ trước khi chúng được gửi tới ứng dụng.
Pēteris Caune avatar
lá cờ cn
Tôi đã kiểm tra `foo.com:*`, NGINX không khởi động và in ra lỗi: `tên máy chủ không hợp lệ hoặc ký tự đại diện "foo.com:*"`
lá cờ in
Đã nghĩ rất nhiều. Chà, sau đó tôi không nghĩ bạn có thể làm gì ở phía nginx. Điều này sẽ được khắc phục trong ứng dụng đưa ra các yêu cầu không hợp lệ.
Điểm:0
lá cờ us

Những điều sau đây có thể làm việc cho default_server:

người phục vụ {
    nghe 80 default_server;

    server_name _ ~example\.com:;

    địa điểm / {
        trả lại 403 "xin lỗi";
    }
}

Phần quan trọng là dấu ngã ~, biểu thị khớp cụm từ thông dụng.

Pēteris Caune avatar
lá cờ cn
Ý tưởng hay nhưng dường như không hiệu quả với tôi - yêu cầu vẫn được chuyển đến phần máy chủ khác.
Điểm:0
lá cờ tl

Ý tưởng thay thế duy nhất mà tôi có thể nghĩ đến là viết mã thứ gì đó ở cấp ứng dụng phía máy chủ để kiểm tra giá trị máy chủ và trả về phản hồi 403 trong mã.

Tuy nhiên, đây thực sự không phải là cách đúng đắn để thực hiện, vì sự cố là sự cố máy khách cần khắc phục chứ không phải cho ứng dụng của bạn.

ví dụ, lấy từ câu trả lời SO này đưa ra một ứng dụng PHP, bạn có thể dễ dàng sửa đổi logic này để đạt được hiệu quả mong muốn, lưu ý cụ thể việc kiểm tra SERVER_PORT theo Câu trả lời của Gerald

$allowed_hosts = mảng('foo.example.com', 'bar.example.com');
$allowed_ports = mảng(80,443);
if (!isset($_SERVER['HTTP_HOST']) || !in_array($_SERVER['HTTP_HOST'], $allowed_hosts) || !in_array($_SERVER['SERVER_PORT'], $allowed_ports )) {
    tiêu đề($_SERVER['SERVER_PROTOCOL'].' 400 Yêu cầu không hợp lệ');
    lối ra;
}
Pēteris Caune avatar
lá cờ cn
Cảm ơn vì câu trả lời. Đó là cách nó hiện đang hoạt động đối với tôi ở đây (ứng dụng phụ trợ sử dụng khung web Django, kiểm tra tiêu đề máy chủ dựa trên danh sách cho phép. Điều này ổn, nhưng tôi đã hy vọng NGINX hoạt động như một "lá chắn" trước ứng dụng phụ trợ , đảm bảo chỉ những yêu cầu hợp lệ, được định dạng tốt mới được chuyển đến ứng dụng phụ trợ)

Đăng câu trả lời

Hầu hết mọi người không hiểu rằng việc đặt nhiều câu hỏi sẽ mở ra cơ hội học hỏi và cải thiện mối quan hệ giữa các cá nhân. Ví dụ, trong các nghiên cứu của Alison, mặc dù mọi người có thể nhớ chính xác có bao nhiêu câu hỏi đã được đặt ra trong các cuộc trò chuyện của họ, nhưng họ không trực giác nhận ra mối liên hệ giữa câu hỏi và sự yêu thích. Qua bốn nghiên cứu, trong đó những người tham gia tự tham gia vào các cuộc trò chuyện hoặc đọc bản ghi lại các cuộc trò chuyện của người khác, mọi người có xu hướng không nhận ra rằng việc đặt câu hỏi sẽ ảnh hưởng—hoặc đã ảnh hưởng—mức độ thân thiện giữa những người đối thoại.