可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm running a Sinatra app behind passenger/nginx. I'm trying to get it to respond to both http and https calls. The problem is, when both are defined in the server block https calls are responded to normally but http yields a 400 "The plain HTTP request was sent to HTTPS port" error. This is for a static page so I'm guessing Sinatra has nothing to do with this. Any ideas on how to fix this?
Here's the server block:
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;
}
回答1:
I ran into a similar problem. It works on one server and does not on another server with same Nginx configuration. Found the the solution which is answered by Igor here http://forum.nginx.org/read.php?2,1612,1627#msg-1627
Yes. Or you may combine SSL/non-SSL servers in one server:
server {
listen 80;
listen 443 default ssl;
# ssl on - remember to comment this out
}
回答2:
The above answers are incorrect in that most over-ride the 'is this connection HTTPS' test to allow serving the pages over http irrespective of connection security.
The secure answer using an error-page on an NGINX specific http 4xx error code to redirect the client to retry the same request to https. (as outlined here https://serverfault.com/questions/338700/redirect-http-mydomain-com12345-to-https-mydomain-com12345-in-nginx )
The OP should use:
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;
[....]
}
回答3:
The error says it all actually. Your configuration tells Nginx to listen on port 80 (HTTP) and use SSL. When you point your browser to http://localhost
, it tries to connect via HTTP. Since Nginx expects SSL, it complains with the error.
The workaround is very simple. You need two server
sections:
server {
listen 80;
// other directives...
}
server {
listen 443;
ssl on;
// SSL directives...
// other directives...
}
回答4:
I had the exact same issue, I have kind of the same configuration as your exemple and I got it working by removing the line :
ssl on;
To quote the doc:
If HTTP and HTTPS servers are equal, a single server that handles both HTTP and HTTPS requests may be configured by deleting the directive “ssl on” and adding the ssl parameter for *:443 port
回答5:
According to wikipedia article on status codes. Nginx has a custom error code when http traffic is sent to https port(error code 497)
And according to nginx docs on error_page, you can define a URI that will be shown for a specific error.
Thus we can create a uri that clients will be sent to when error code 497 is raised.
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;
}
}
However if a client makes a request via any other method except a GET, that request will be turned into a GET. Thus to preserve the request method that the client came in via; we use error processing redirects as shown in nginx docs on error_page
And thats why we use the 301 =307
redirect.
Using the nginx.conf file shown here, we are able to have http and https listen in on the same port
回答6:
Here is an example to config HTTP and HTTPS in same config block with ipv6 support. The config is tested in Ubuntu Server and NGINX/1.4.6 but this should work with all servers.
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;
}
Don't include ssl on
which may cause 400
error. The config above should work for
http://example.com
http://www.example.com
https://example.com
https://www.example.com
Hope this helps!
回答7:
if use phpmyadmin add: fastcgi_param HTTPS on;
回答8:
Actually you can do this with:
ssl off;
This solved my problem in using nginxvhosts; now I am able to use both SSL and plain HTTP.
Works even with combined ports.