Tại sao nghe 443 default_server; ghi đè quy tắc nginx đã được cấu hình quy tắc (quy tắc http hoạt động bình thường)?


9

Tôi có một nginx và các tên miền phụ khác nhau:

a.mydomain.com
b.mydomain.com
c.mydomain.com

Nginx có 4 quy tắc:

1) quy tắc viết lại:

server {
  listen 80
  server_name gl.udesk.org;

  root /nowhere;
  rewrite ^ https://a.mydomain.com$request_uri permanent;
}

2) Quy tắc https:

server {

  listen 443;
  server_name a.mydomain.com;

  root /home/a/a/public;

  ssl on;
  ssl_certificate conf.d/ssl/a.crt;
  ssl_certificate_key conf.d/ssl/a.key;
  ssl_protocols ...
  ssl_ciphers ...
  ssl_prefer_server_ciphers on;

  location ...
}

3) quy tắc mặc định http:

server {
  listen 80 default_server;
  return 444;
}

4) Quy tắc mặc định https:

server {
  listen 443 default_server;
  return 444;
}

Vì vậy, nếu tôi bắt đầu nginx và:

  • nếu tôi truy cập vào trình duyệt tới http://a.mydomain.com thì nó sẽ chuyển hướng đến https://a.mydomain.com và sau đó nó sẽ trả về Lỗi 107 (net :: ERR_SSL_PROTOCOL_ERROR): lỗi giao thức SSL.
  • nếu tôi truy cập trình duyệt tới https://b.mydomain.com, tôi hy vọng rằng nó sẽ trả về Lỗi 444. Nhưng thay vào đó, nó trả về cùng một Lỗi 107 (net :: ERR_SSL_PROTOCOL_ERROR): lỗi giao thức SSL.
  • và như vậy đối với tất cả các CNAME của nhà cung cấp DNS đã đăng ký (tức là a, b, c)
  • tất cả các phiên bản http (ví dụ quy tắc 3 -) hoạt động như mong đợi:

Vậy tại sao các quy tắc https trong nginx rất khó cấu hình và tôi nên định cấu hình chúng đúng cách để có hành vi giống như với phiên bản http?

Cập nhật:

Tạo chứng chỉ mới và thêm:

ssl on;
ssl_certificate conf.d/ssl/default.crt;
ssl_certificate_key conf.d/ssl/default.key;

hoạt động ngay bây giờ, nhưng tôi sẽ có một giải pháp mà không cần bất kỳ chứng chỉ SSL nào. Chỉ cần đặt lại tất cả các kết nối cho tất cả các tên miền phụ https (cổng 443) ngoại trừ https://a.mydomain.com mà không cần cung cấp chứng chỉ.


2
Bạn không thể. SSL yêu cầu chứng chỉ trước khi máy chủ web biết tên miền bạn muốn . Nó phải có một chứng chỉ để gửi, hoặc nó không thể thiết lập kết nối để nói chuyện với khách hàng.
Darth Android

2
@DarthAndroid: Phép thuật được gọi là SNI - en.wikipedia.org/wiki/Server_Name_Inication .
Shi

@Shi Tôi nhận thức được SNI - Điều đó cho phép các máy chủ web để chọn giấy chứng nhận để gửi, nhưng nó vẫn phải chọn một chứng chỉ. nginxkhông đủ thông minh để nhận ra rằng nó không cần chứng chỉ cho những gì người dùng muốn làm.
Darth Android

Câu trả lời:


3

Đừng trộn Cổng 443 với ssl! Nginx là cổng bất khả tri. Bạn cũng có thể cung cấp https qua Cổng 80. Phiên bản nginx hiện đại cho phép

listen 1234 ssl;

và bạn không cần ssl on;dòng sau đó.

Nhưng nếu bạn muốn phục vụ https, bạn cần chỉ định chứng chỉ. Máy chủ của bạn nhập https khi viết lại yêu cầu http thành yêu cầu https.

Bạn nhận được PROTOCOL ERROR, vì Bắt tay SSL được thực hiện trước mọi thứ khác. Vì vậy, return 444không đạt được. Và bất kỳ Bắt tay SSL nào cũng sẽ cần chứng chỉ và khóa riêng để cung cấp thuật toán mã hóa với cặp chứng chỉ / khóa riêng.


3

Lệnh returnnày là một phần của mô-đun viết lại. Nếu bạn kiểm tra tài liệu , bạn có thể thấy rằng nó hoạt động với các yêu cầu. Trong HTTPS, các yêu cầu chỉ có thể được thực hiện sau khi bắt tay xong.

Có một yêu cầu tính năng: https://trac.nginx.org/nginx/ticket/195 và một giải pháp khắc phục được cung cấp.

server {
    listen 443 ssl;
    server_name bbb.example.com;
    ssl_ciphers aNULL;
    ssl_certificate /path/to/dummy.crt;
    ssl_certificate_key /path/to/dummy.key;
    return 444;
}

Lưu ý này sẽ phá vỡ các khách hàng HTTPS phi SNI có khả năng (như nginx của riêng proxy_pass, trừ khi bạn đặt proxy_ssl_server_name on;) xâm nhập bất kỳ khác server_names(vì vậy về cơ bản phá vỡ hợp pháp server_namecủa bạn làm muốn cho qua). Xem trac.nginx.org/nginx/ticket/195#comment:11 để biết chi tiết.
nh2
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.