处理 nginx 400“普通 HTTP 请求被发送到 HTTPS 端口”错误

我在“乘客”/nginx 后面运行一个 Sinatra 应用程序。我试图让它同时响应 http 和 https 呼叫。问题是,当两者都在服务器块中定义时,HTTPS 调用通常会得到响应,但是 HTTP 会产生400个“普通 HTTP 请求被发送到 HTTPS 端口”错误。这是一个静态页面,所以我猜辛纳特拉与此无关。有办法解决吗?

这是服务器块:

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;
}
233144 次浏览

这个错误实际上说明了一切。您的配置告诉 Nginx 侦听端口80(HTTP)并使用 SSL。当您将浏览器指向 http://localhost时,它会尝试通过 HTTP 进行连接。因为 Nginx 期望使用 SSL,所以它会抱怨这个错误。

变通方法非常简单,需要两个 server部分:

server {
listen 80;


// other directives...
}


server {
listen 443;


ssl on;
// SSL directives...


// other directives...
}

我也遇到过类似的问题。它可以在一台服务器上工作,但不能在具有相同 Nginx 配置的另一台服务器上工作。找到了答案,这里的答案是伊戈尔 http://forum.nginx.org/read.php?2,1612,1627#msg-1627

是的,或者您可以将 SSL/非 SSL 服务器合并到一个服务器中:

server {
listen 80;
listen 443 default ssl;


# ssl on   - remember to comment this out


}

实际上你可以这样做:

ssl off;

这解决了我在使用 nginxvhosts 时遇到的问题; 现在我可以同时使用 SSL 和普通 HTTP。 即使与组合端口一起工作。

如果使用 phpmyadmin 添加: fastcgi _ param HTTPS 上;

上述答案是不正确的,因为大多数超越“是这个连接 HTTPS”测试,以允许通过 http 服务页面,而不考虑连接安全性。

安全应答使用 NGINX 特定的 http 4xx 错误代码上的错误页面将客户端重定向到 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://$server_name:$server_port$request_uri;


[....]
}

我也遇到了同样的问题,我的配置和你们的例子差不多,我通过删除这一行来解决这个问题:

ssl on;

引用医生的话:

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

根据 关于状态代码的维基百科文章.Nginx,当 http 流量被发送到 https 端口时,有一个自定义错误代码(错误代码497)

根据 Nginx docs on error _ page,您可以定义一个 URI,它将显示一个特定的错误。
因此,我们可以创建一个 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。因此,为了保留客户端通过的请求方法,我们使用错误处理重定向,如 Nginx docs on error _ page所示

这就是为什么我们使用 301 =307重定向。

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

下面的示例将 HTTPHTTPS配置为具有 Ipv6支持的同一配置块。该配置在 Ubuntu 服务器NGINX/1.4.6中进行了测试,但是应该可以在所有服务器上使用。

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

Http://example.com

Http://www.example.com

Https://example.com

Https://www.example.com

希望这个能帮上忙!

它的错误497,而不是错误400。你可以像这样处理错误497,并用301(永久移动)或302(临时移动)重定向 http 到 https,如下所示:

error_page 497 = @foobar;


location @foobar {
return 301 https://$host:$server_port$request_uri;
}

这将重定向您到确切的网址您请求,但替换您的请求“ http”与“ https”没有错误或确认(其301重定向,并计算为搜索引擎优化安全)

就我而言,我的回答从 Jenkins 转到了443

刚刚在 nginx 配置中添加了一个代理重定向来使其工作

proxy_redirect http://test.example.com:443/ https://test.example.com/;