Xử lý lỗi nginx 400 "Yêu cầu HTTP thuần túy đã được gửi đến cổng HTTPS"


115

Tôi đang chạy một ứng dụng Sinatra sau hành khách / nginx. Tôi đang cố gắng để nó phản hồi cả cuộc gọi http và https. Vấn đề là, khi cả hai được xác định trong khối máy chủ, các cuộc gọi https được phản hồi bình thường nhưng http dẫn đến lỗi 400 "Yêu cầu HTTP thuần túy đã được gửi đến cổng HTTPS". Đây là một trang tĩnh nên tôi đoán Sinatra không liên quan gì đến điều này. có ý tưởng nào để sửa cái này không?

Đây là khối máy chủ:

server {
        listen 80;
        listen 443  ssl;
        server_name localhost;
        root /home/myhome/app/public;
        passenger_enabled on;

        ssl on;
        ssl_certificate      /opt/nginx/ssl_keys/ssl.crt;
        ssl_certificate_key  /opt/nginx/ssl_keys/ssl.key;
        ssl_protocols        SSLv3 TLSv1;
        ssl_ciphers          HIGH:!aNULL:!MD5;

        location /static {
            root  /home/myhome/app/public;
            index  index.html index.htm index.php;
        }

        error_page 404 /404.html;

        # redirect server error pages to the static page /50x.html
        error_page 500 /500.html;

        access_log /home/myhome/app/logs/access.log;
        error_log /home/myhome/app/logs/error.log;
}

Trong trường hợp của tôi là url trong trình duyệt: my.example.com:443không hoạt động. Thay vào đó thay vào đó để https://my.example.comlàm việc. Kỳ lạ, chưa bao giờ có vấn đề này với apache.
Sebastian

1
ssl on;cho NGINX biết máy chủ BẤT KỲ nội dung nào thông qua SSL. Sử dụng cờ "ssl" ở cuối listen 443;ví dụ listen 443 ssl;của bạn nếu máy chủ của bạn phân phối cả lưu lượng truy cập http và https và xóa ssl on;chỉ thị.
Stphane

Câu trả lời:


195

Tôi đã gặp phải một vấn đề tương tự. Nó hoạt động trên một máy chủ và không hoạt động trên máy chủ khác có cùng cấu hình Nginx. Đã tìm thấy giải pháp được Igor trả lời tại đây http://forum.nginx.org/read.php?2,1612,1627#msg-1627

Đúng. Hoặc bạn có thể kết hợp máy chủ SSL / không SSL trong một máy chủ:

server {
  listen 80;
  listen 443 default ssl;

  # ssl on   - remember to comment this out

}

Mỗi gì rapam Iosif nói, hãy chắc chắn bạn cũng bao gồmssl off;
aceofspades

20
Bạn chỉ cần xóa dòng ssl on;(không cần thêm ssl tắt). Ngoài ra, kể từ khi tôi không nhớ mà Nginx phiên bản, không có nhu cầu nhiều hơn để sử dụng defaulttrên listen 443dòng. Vì vậy, cấu hình OP đã ổn, chỉ cần gỡ bỏ ssl onvà nó sẽ hoạt động.
đoạt giải 2/12/12

@bobojam vui lòng bao gồm lời giải thích từ câu trả lời của tôi, để câu trả lời của bạn sẽ đầy đủ hơn. Tôi đã yêu cầu tác giả OP chấp nhận câu trả lời của bạn.
Alexander Azarov

2
Làm thế nào nó giải quyết mục đích SSL bằng cách bình luận ssl on. @ MichaelJ.Evans câu trả lời dưới đây là một giải pháp tốt hơn nhiều.
Neel

1
Dường như không hoạt động với nhiều tệp conf. Cho biết có 2 mặc định trùng lặp. Sử dụng giải pháp của Alexander.
Ryall

39

Các câu trả lời trên không chính xác vì hầu hết kiểm tra quá trình kiểm tra 'đây có phải là kết nối HTTPS không' để cho phép cung cấp các trang qua http bất kể bảo mật kết nối.

Câu trả lời an toàn sử dụng trang lỗi trên mã lỗi http 4xx cụ thể của NGINX để chuyển hướng khách hàng thử lại cùng một yêu cầu tới https. (như được nêu ở đây /server/338700/redirect-http-mydomain-com12345-to-https-mydomain-com12345-in-nginx )

OP nên sử dụng:

server {
  listen        12345;
  server_name   php.myadmin.com;

  root         /var/www/php;

  ssl           on;

  # If they come here using HTTP, bounce them to the correct scheme
  error_page 497 https://$host:$server_port$request_uri;

  [....]
}

1
Bạn có thể muốn $ server_name thay vì $ host, server_name có lẽ được đặt thành CN mà chứng chỉ SSL xác thực. Bằng cách đó, người dùng sẽ không nhận được màn hình sợ hãi nếu họ truy cập qua IP hoặc localhost.
George

Tôi đã cố gắng để thực hiện điều này trên địa phương của tôi cài đặt của GitLab , nhưng sử dụng các thiết lập tùy chỉnh Chèn nginx vào GitLab khối máy chủ phương pháp như vậy nginx['custom_gitlab_server_config'] = "error_page 497 https://$host:$server_port$request_uri;"đã làm các trick
Aaron C

17

Thực ra lỗi nói lên tất cả. Cấu hình của bạn yêu cầu Nginx lắng nghe trên cổng 80 (HTTP) và sử dụng SSL. Khi bạn trỏ trình duyệt của mình đến http://localhost, trình duyệt sẽ cố gắng kết nối qua HTTP. Vì Nginx mong đợi SSL nên nó sẽ phàn nàn về lỗi.

Cách giải quyết rất đơn giản. Bạn cần hai serverphần:

server {
  listen 80;

  // other directives...
}

server {
  listen 443;

  ssl on;
  // SSL directives...

  // other directives...
}

7
Bạn không thực sự cần hai phần máy chủ. Xóa dòng "ssl on" và thay đổi dòng nghe theo câu trả lời của @ bobojam.
toxaq

12

Tôi đã gặp chính xác vấn đề tương tự, tôi có loại cấu hình giống như ví dụ của bạn và tôi đã làm cho nó hoạt động bằng cách xóa dòng:

ssl on;

Để trích dẫn tài liệu:

Nếu máy chủ HTTP và HTTPS bằng nhau, một máy chủ duy nhất xử lý cả yêu cầu HTTP và HTTPS có thể được định cấu hình bằng cách xóa chỉ thị “ssl on” và thêm thông số ssl cho cổng *: 443


1
Bất kỳ cơ hội bạn có liên kết đến tài liệu?
Adam Parkin

12

Theo bài báo wikipedia về mã trạng thái . Nginx có mã lỗi tùy chỉnh khi lưu lượng truy cập http được gửi đến cổng https (mã lỗi 497)

Và theo tài liệu nginx trên error_page , bạn có thể xác định một URI sẽ được hiển thị cho một lỗi cụ thể.
Do đó, chúng ta có thể tạo một tiểu mà khách hàng sẽ được gửi đến khi mã lỗi 497 được nâng lên.

nginx.conf

#lets assume your IP address is 89.89.89.89 and also 
#that you want nginx to listen on port 7000 and your app is running on port 3000

server {
    listen 7000 ssl;
 
    ssl_certificate /path/to/ssl_certificate.cer;
    ssl_certificate_key /path/to/ssl_certificate_key.key;
    ssl_client_certificate /path/to/ssl_client_certificate.cer;

    error_page 497 301 =307 https://89.89.89.89:7000$request_uri;

    location / {
        proxy_pass http://89.89.89.89:3000/;

        proxy_pass_header Server;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Protocol $scheme;
    }
}

Tuy nhiên, nếu khách hàng đưa ra yêu cầu thông qua bất kỳ phương thức nào khác ngoại trừ GET, yêu cầu đó sẽ được chuyển thành GET. Do đó, để duy trì phương thức yêu cầu mà khách hàng đã đến qua; chúng tôi sử dụng chuyển hướng xử lý lỗi như được hiển thị trong tài liệu nginx trên error_page

Và đó là lý do tại sao chúng tôi sử dụng 301 =307chuyển hướng.

Sử dụng tệp nginx.conf được hiển thị ở đây, chúng tôi có thể có http và https lắng nghe trên cùng một cổng


điều này phù hợp với tôi - error_page 497 301 = 307 89.89.89.89:7000$request_uri ;
ugali soft

7

Đây là một ví dụ để cấu hình HTTPHTTPS trong cùng một khối cấu hình với hỗ trợ ipv6 . Cấu hình được kiểm tra trong Ubuntu ServerNGINX / 1.4.6 nhưng cấu hình này sẽ hoạt động với tất cả các máy chủ.

server {
    # support http and ipv6
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    # support https and ipv6
    listen 443 default_server ssl;
    listen [::]:443 ipv6only=on default_server ssl;

    # path to web directory
    root /path/to/example.com;
    index index.html index.htm;

    # domain or subdomain
    server_name example.com www.example.com;

    # ssl certificate
    ssl_certificate /path/to/certs/example_com-bundle.crt;
    ssl_certificate_key /path/to/certs/example_com.key;

    ssl_session_timeout 5m;

    ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
    ssl_prefer_server_ciphers on;
}

Không đưa vào ssl oncó thể gây ra 400lỗi. Cấu hình ở trên sẽ hoạt động cho

http://example.com

http://www.example.com

https://example.com

https://www.example.com

Hi vọng điêu nay co ich!



4

Trên thực tế, bạn có thể làm điều này với:

ssl off; 

Điều này đã giải quyết vấn đề của tôi trong việc sử dụng nginxvhosts; bây giờ tôi có thể sử dụng cả SSL và HTTP đơn giản. Hoạt động ngay cả với các cổng kết hợp.


Công trình đối với tôi trên nginx / 1.6.3 :)
djthoms
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.