Thiết lập đúng máy chủ Nginx mặc định của Wikipedia cho https


71

Tôi có một số máy chủ đang chạy trên cùng một máy, một số chỉ có http, một số có cả http và https. Có một số khối máy chủ được xác định trong các tệp riêng biệt được bao gồm từ tệp cấu hình chính.

Tôi đã thiết lập một máy chủ "mặc định" cho http, nó sẽ phục vụ một "trang bảo trì" chung cho các yêu cầu không khớp với bất kỳ máy chủ nào khác trong các tệp cấu hình khác. Máy chủ mặc định http hoạt động như mong đợi, nó sử dụng server_name "_" và nó xuất hiện đầu tiên trong danh sách bao gồm (vì tôi đã quan sát thấy rằng trong trường hợp trùng lặp server_names trên các máy chủ, lần đầu tiên xuất hiện sẽ được sử dụng). Điều này làm việc tuyệt vời.

Tôi sẽ mong đợi khối máy chủ chính xác tương tự (chỉ chuyển "nghe 80 default_server" sang "nghe 443 default_server" và thay vì phục vụ trang "return 444") tuy nhiên không được. Thay vào đó, có vẻ như máy chủ https mặc định mới thực sự lấy tất cả các kết nối https đến và khiến chúng bị lỗi, mặc dù các khối máy chủ khác có tên máy chủ phù hợp hơn cho các yêu cầu đến. Xóa máy chủ https mặc định mới sẽ khiến hành vi bán đúng trở lại: tất cả các trang web có https sẽ tải chính xác; nhưng tất cả các trang web không có https sẽ được chuyển đến máy chủ https đầu tiên trong các tệp bao gồm (theo tài liệu, nếu không có "default_server" xuất hiện, thì khối máy chủ đầu tiên xuất hiện sẽ là "mặc định").

Vì vậy, câu hỏi của tôi là, cách chính xác để xác định một "máy chủ mặc định" trong nginx cho các kết nối ssl là gì? Tại sao khi tôi đặt "default_server" một cách rõ ràng thì nó lại tham lam và lấy tất cả các kết nối trong khi tôi ngầm để nginx quyết định "máy chủ mặc định" thì nó hoạt động như tôi mong đợi (với máy chủ không chính xác được đặt làm mặc định và các máy chủ thực khác cư xử đúng)?

Đây là "máy chủ mặc định" của tôi. Http hoạt động mà không phá vỡ các máy chủ khác. Https phá vỡ các máy chủ khác và tiêu thụ tất cả.

server {
    listen 443 ssl default_server;
    server_name _;

    access_log /var/log/nginx/maintenance.access.log;
    error_log /var/log/nginx/maintenance.error.log error;

    return 444;
}

server {
    listen *:80 default_server;
    server_name _;
    charset utf-8;

    access_log /var/log/nginx/maintenance.access.log;
    error_log /var/log/nginx/maintenance.error.log error;

    root /home/path/to/templates;

    location / {
        return 503;
    }

    error_page 503 @maintenance;

    location @maintenance {
        rewrite ^(.*)$ /maintenance.html break;
    }
}

Bất cứ ai trong số các bạn thấy những gì có thể sai ở đây?

ssl  https  nginx 

Câu trả lời:


27

Bạn không có bất kỳ ssl_cert ve hoặc ssl_cert ve_key được xác định trong khối https "mặc định" của bạn. Mặc dù bạn không có hoặc muốn có một khóa thực sự cho kịch bản mặc định này, bạn vẫn cần định cấu hình một hoặc nếu không nginx sẽ có hành vi không mong muốn mà bạn mô tả.

Tạo chứng chỉ tự ký với Tên chung là * và cắm nó vào cấu hình của bạn và nó sẽ bắt đầu hoạt động như bạn muốn.

Hành vi "mặc định" trong thiết lập này sẽ là trình duyệt sẽ nhận được cảnh báo rằng chứng chỉ không thể tin cậy được, nếu người dùng thêm chứng chỉ làm ngoại lệ, kết nối sẽ bị nginx loại bỏ và họ sẽ thấy mặc định của trình duyệt của họ Thông báo lỗi "không thể kết nối".


1
Tôi đã thử điều này nhưng nó vẫn không hoạt động: Tất cả các yêu cầu ssl đến IP đều đi đến máy chủ ssl khác của tôi. Bất cứ điều gì khác tôi có thể thử?
Michael Härtl

23

Tôi quản lý để định cấu hình lưu trữ dành riêng được chia sẻ trên một IP với nginx. HTTP và HTTPS mặc định phục vụ 404 cho các miền không xác định đến.

1 - Tạo vùng mặc định

Vì nginx đang tải vhost theo thứ tự ascii, bạn nên tạo một 00-defaultliên kết tệp / biểu tượng vào /etc/nginx/sites-enabled.

2 - Điền vào vùng mặc định

Điền vào các 00-defaultvhost mặc định của bạn . Đây là khu vực tôi đang sử dụng:

server {
    server_name _;
    listen       80  default_server;
    return       404;
}


server {
    listen 443 ssl;
    server_name _;
    ssl_certificate /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx.key;
    return       404;
}

3 - Tạo certif tự ký, kiểm tra và tải lại

Bạn sẽ cần phải tạo một chứng chỉ tự ký vào /etc/nginx/ssl/nginx.crt.

Tạo chứng chỉ tự ký mặc định:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt

Chỉ là một lời nhắc nhở:

  • Kiểm tra cấu hình nginx trước khi tải lại / khởi động lại: nginx -t
  • Tải lại thưởng thức: sudo service nginx reload

Hy vọng nó giúp.


2
Không giải quyết cảnh báo trình duyệt truy cập một trang web không an toàn.
gdbj

5
Không thể giải quyết vì tất cả bắt phải khớp với bất kỳ miền nào. Không có SSL có thể ký tự đại diện cho tất cả các tên miền. Hãy tưởng tượng nếu bạn giả mạo địa chỉ google.fr trên máy chủ của mình, bạn sẽ có thể xác thực máy chủ của mình là google.fr. Đây sẽ là một vấn đề bảo mật nghiêm trọng :(
Ifnot

Ya, tôi đoán điều đó có ý nghĩa. Thật không may trong Chrome, bạn được đưa ra một cảnh báo đáng sợ trước khi thấy trang 404 tệ hơn là máy chủ chỉ từ chối lưu lượng. Làm cho nó trông giống như máy chủ bị cấu hình sai.
gdbj

Cảm ơn rât nhiều. Điều này làm việc cho tôi, ngoại trừ việc tôi phải thêm default_serverđể nghe 443 và tôi đã thêm địa chỉ IPv6 [::]: 80 và [::]: 443 với default_server.
chmike

16

Về cơ bản, chúng tôi muốn tránh bằng mọi giá rằng định nghĩa máy chủ đầu tiên trong tệp cấu hình của chúng tôi được phục vụ như một máy chủ bắt tất cả cho các kết nối SSL. Chúng ta đều biết rằng nó làm điều đó (trái ngược với http và sử dụng cấu hình default_server hoạt động độc đáo).

Điều này không thể đạt được khai báo cho SSL (chưa) vì vậy chúng tôi phải mã hóa nó bằng IF ...

Biến $hostlà tên máy chủ từ dòng yêu cầu hoặc tiêu đề http. Biến $server_namelà tên của khối máy chủ chúng ta đang ở ngay bây giờ.

Vì vậy, nếu hai cái này không bằng nhau thì bạn đã phục vụ khối máy chủ SSL này cho một máy chủ khác để nó bị chặn.

Mã này không chứa các tham chiếu cụ thể đến các địa chỉ IP máy chủ của bạn để có thể dễ dàng sử dụng lại cho các cấu hình máy chủ khác mà không cần sửa đổi.

Thí dụ:

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    ###
    ### Section: SSL

    #
    ## Check if this certificate is really served for this server_name
    ##   http://serverfault.com/questions/578648/properly-setting-up-a-default-nginx-server-for-https
    if ($host != $server_name) {
        #return 404 "this is an invalid request";
        return       444;
    }

    ...

bạn có thể giải thích những gì listen [::]:443 ssl http2;không? Tôi đang gặp khó khăn khi tìm tài liệu cho nó.
Andrew Brown

Tôi nghĩ rằng tôi đã tìm thấy nó, chỉ cần biết những gì để tìm kiếm. Chỉ thị IPV4 và IPV6.
Andrew Brown

7

Để giải thích thêm về câu trả lời của Radmilla Mustafa:

Nginx sử dụng tiêu đề 'Máy chủ' để khớp với server_name. Nó không sử dụng TLS SNI. Điều này có nghĩa là đối với máy chủ SSL, nginx phải có khả năng chấp nhận kết nối SSL, điều này có nghĩa là có chứng chỉ / khóa. Chứng chỉ / khóa có thể là bất kỳ, ví dụ như tự ký.

Xem tài liệu

Do đó, giải pháp là:

server {
    server_name _;
    listen 80 default_server;
    listen 443 ssl default_server;

    ## To also support IPv6, uncomment this block
    # listen [::]:80 default_server;
    # listen [::]:443 ssl default_server;

    ssl_certificate <path to cert>;
    ssl_certificate_key <path to key>;
    return 404; # or whatever
}

Tôi cảm thấy rằng đây nên là câu trả lời được chấp nhận. Cảm ơn nhiều.
tổng

2

Cho bất cứ ai mất nhiều tóc như tôi (đã dành gần cả ngày cho việc này ngày hôm nay). Tôi đã thử hầu hết mọi thứ, và điều khiến nó cuối cùng hoạt động chính xác là dòng ngu ngốc này:

ssl_session_tickets off;

Dựa trên câu trả lời của Ifnot , ví dụ làm việc của tôi là:

server {
    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;
    server_name _;

    ssl_certificate /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx.key;
    ssl_session_tickets off;

    return 404;
}

Tôi không biết tại sao điều này lại cần thiết, nguyên tắc duy nhất tôi rút ra từ việc này là nginx cư xử rất kỳ lạ khi chúng tôi không cho anh ta những gì anh ta muốn.


1
bạn là một huyền thoại.
Nizar Blond

1

Nếu bạn muốn hoàn toàn chắc chắn, thì hãy sử dụng các địa chỉ IP riêng cho các máy chủ không nên trả lời trên HTTPS và các máy chủ nên. Điều này cũng giải quyết vấn đề cảnh báo trình duyệt "chứng chỉ không hợp lệ".

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.