处理nginx 400“纯HTTP请求已发送到HTTPS端口”错误

我正在客户/ nginx后面运行一个Sinatra应用程序。 我试图让它响应http和https调用。 问题是,当在服务器块中定义https时,HTTPS调用通常会得到响应,但是HTTP会产生一个400“纯HTTP请求已发送到HTTPS端口”错误。 这是一个静态页面,所以我猜测Sinatra与此无关。 有想法该怎么解决这个吗?

这是服务器块:

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; } 

我遇到了类似的问题。 它可以在一台服务器上运行,而不在具有相同Nginxconfiguration的另一台服务器上运行。 find了伊戈尔在这里回答的解决schemehttp://forum.nginx.org/read.php?21612,1627#msg-1627

是。 或者您可以在一台服务器中组合SSL /非SSL服务器:

 server { listen 80; listen 443 default ssl; # ssl on - remember to comment this out } 

上面的答案是不正确的,因为大多数情况下不考虑连接安全性,而是通过http连接“HTTPS”testing来允许服务页面。

使用NGINX特定http 4xx错误代码中的错误页面的安全答案来redirect客户端,以重试相同的请求到https。 (如这里概述的https://serverfault.com/questions/338700/redirect-http-mydomain-com12345-to-https-mydomain-com12345-in-nginx

OP应该使用:

 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; [....] } 

这个错误实际上说了这一切。 您的configuration告诉Nginx监听端口80(HTTP)并使用SSL。 当您将浏览器指向http://localhost ,它会尝试通过HTTP进行连接。 由于Nginx希望SSL,它抱怨错误。

解决方法非常简单。 你需要两个server部分:

 server { listen 80; // other directives... } server { listen 443; ssl on; // SSL directives... // other directives... } 

我有完全相同的问题,我有一个与你的例子相同的configuration,我得到它通过删除行的工作:

ssl on;

引用文档:

如果HTTP和HTTPS服务器相同,则可以通过删除指令“ssl on”并为*:443端口添加ssl参数来configuration同时处理HTTP和HTTPS请求的单个服务器

根据维基百科关于状态码的文章 。 httpstream量发送到https端口时,Nginx具有自定义错误代码(错误代码497)

根据error_page上的nginx文档 ,您可以定义一个将显示特定错误的URI。
因此,我们可以创build一个uri,当错误代码497被引发时,客户端将被发送到uri。

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; } } 

但是,如果客户端通过除GET之外的其他方法发出请求,则该请求将变成GET。 从而保留客户端通过的请求方式; 我们使用error handlingredirect,如error_page上的nginx文档所示

这就是为什么我们使用301 =307redirect。

使用这里显示的nginx.conf文件,我们可以让http和https在同一个端口上监听

如果使用phpmyadmin添加:fastcgi_param HTTPS;

这里是一个configurationHTTPHTTPSipv6支持相同的configuration块的例子。 该configuration在Ubuntu服务器NGINX / 1.4.6testing,但这应该与所有服务器。

 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; } 

不要包含可能导致400错误的ssl on 。 上面的configuration应该为

http://example.com

http://www.example.com

https://example.com

https://www.example.com

希望这可以帮助!

其实你可以这样做:

 ssl off; 

这解决了我使用nginxvhosts的问题; 现在我可以同时使用SSL和纯HTTP。 即使合并端口也可以工作。