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

Joh*_*nny 107 nginx

我在乘客/ nginx后面运行一个Sinatra应用程序.我试图让它响应http和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;
}
Run Code Online (Sandbox Code Playgroud)

bob*_*jam 191

我遇到了类似的问题.它适用于一台服务器,不适用于具有相同Nginx配置的其他服务器.找到了Igor在这里解答的解决方案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

}
Run Code Online (Sandbox Code Playgroud)

  • 你只需要删除`ssl on;行(不需要添加ssl).另外,由于我不记得哪个Nginx版本,所以不再需要在`listen 443`行使用`default`.所以OP配置没问题,只需要删除`ssl on`就可以了. (19认同)
  • 它如何通过注释 `ssl on` 来解决 SSL 目的。@MichaelJ.Evans 下面的回答是一个更好的解决方案。 (2认同)

Mic*_*ans 32

以上答案是不正确的,因为大多数覆盖'是这个连接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://$host:$server_port$request_uri;

  [....]
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*rov 17

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

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

server {
  listen 80;

  // other directives...
}

server {
  listen 443;

  ssl on;
  // SSL directives...

  // other directives...
}
Run Code Online (Sandbox Code Playgroud)

  • 您实际上不需要两个服务器部分.删除"ssl on"行并根据@ bobojam的答案更改监听行. (7认同)

Rem*_*miz 12

我有完全相同的问题,我有一些与你的例子相同的配置,我通过删除行来实现它:

ssl on;

引用文档:

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


Kom*_*omu 11

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

根据error_page上的nginx文档,您可以定义将针对特定错误显示的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;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果客户端通过除GET之外的任何其他方法发出请求,则该请求将变为GET.这样就保留了客户端通过的请求方法; 我们使用错误处理重定向,如error_page上的nginx文档中所示

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

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


Mad*_*ota 7

以下是在具有ipv6支持的同一配置块中配置HTTPHTTPS的示例.配置在Ubuntu ServerNGINX/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;
}
Run Code Online (Sandbox Code Playgroud)

不包括ssl on可能导致400错误的内容.上面的配置应该适用于

http://example.com

http://www.example.com

https://example.com

https://www.example.com

希望这可以帮助!