我在应用程序前面使用 nginx 作为代理来终止 TLS。我已将其设置为监听端口 80 并重定向到 443。
最初,Chromium 会下载一个名为“download”的文件,而不是重定向,但由于某种原因,它不再这样做了(我尝试了这个问题但这并没有帮助)。尽管问题显然仍然存在,但 Chromium 可以正确重定向,而 Firefox 仍然会对此做出反应,认为这是一个文件下载:
该问题在 curl 中最明显:
curl -v http://example.com
* Rebuilt URL to: http://example.com/
* Trying 54.213.157.146...
* Connected to example.com (54.213.157.146) port 80 (#0)
> GET / HTTP/1.1
> Host: example.com
> User-Agent: curl/7.50.0
> Accept: */*
>
* Connection #0 to host example.com left intact
����
它似乎没有返回通常的标头/状态/等,而是返回了二进制数据。同时,https 版本似乎可以正常工作:
curl -v https://example.com
* Rebuilt URL to: https://example.com/
* Trying 54.213.157.146...
* Connected to example.com (54.213.157.146) port 443 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: CN=example.com
* start date: Jul 29 18:50:00 2016 GMT
* expire date: Oct 27 18:50:00 2016 GMT
* subjectAltName: host "example.com" matched cert's "example.com"
* issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
* SSL certificate verify ok.
> GET / HTTP/1.1
> Host: example.com
> User-Agent: curl/7.50.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx/1.11.1
< Date: Fri, 29 Jul 2016 22:53:33 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 1121
< Connection: keep-alive
< X-Powered-By: Express
< ETag: W/"461-VBuWbiWQQ/3ptwQjG8pM3w"
< Strict-Transport-Security: max-age=63072000; includeSubdomains; preload
< X-Frame-Options: SAMEORIGIN
< X-Content-Type-Options: nosniff
<
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
...
显然我的 nginx 配置错误,但我不清楚具体原因。
我的nginx.conf:
user nginx;
worker_processes 2;
events {
worker_connections 8096;
multi_accept on;
use epoll;
}
http {
include mime.types;
default_type application/octet-stream;
proxy_cache_path /var/cache/nginx keys_zone=anonymous:10m;
proxy_temp_path /var/tmp/nginx;
sendfile on;
client_max_body_size 20M;
tcp_nodelay off;
tcp_nopush on;
keepalive_timeout 65;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
#Include the vhost files.
include vhosts/*.conf;
}
以及 vhosts 文件:
server {
listen 80 http2;
server_name ${DOMAIN};
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name ${DOMAIN};
ssl_certificate /etc/letsencrypt/live/${PATH}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${PATH}/privkey.pem;
ssl_dhparam /etc/ssl/dhparams.pem;
ssl_ciphers "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA";
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload" always;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
root /etc/letsencrypt/webrootauth;
location / {
proxy_pass http://${UPSTREAM};
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_cache anonymous;
proxy_cache_valid 200 301 302 30m;
expires 30m;
proxy_buffering off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
}
location ~* \.(html|css|jpg|gif|ico|js)$ {
proxy_cache cache;
proxy_cache_key $host$uri$is_args$args;
proxy_cache_valid 200 301 302 30m;
expires 30m;
proxy_pass http://backend;
}
location /.well-known/acme-challenge {
alias /etc/letsencrypt/webrootauth/.well-known/acme-challenge;
location ~ /.well-known/acme-challenge/(.*) {
add_header Content-Type application/jose+json;
}
}
}
有谁知道这是什么原因造成的吗?
答案1
您使用的 http2 指令意味着该端口具有 SSL 支持(没有 SSL 它就无法工作),因此您看到的二进制数据实际上是 nginx 尝试在没有任何证书的情况下通过端口 80 进行安全通信。
您可以使用以下方法验证:
curl --tlsv1.2 https://your-domain-name.is:80
这将为你带来:
curl: (35) error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol
而其他任何服务器都会给你
curl: (35) Unknown SSL protocol error in connection to example.com:80
从端口 80 删除 http2 指令(并将其放到端口 443)
如果您坚持将 http2 指令保留在端口 80 上,至少将所有与 ssl 相关的参数添加到该部分,这样您就可以使用 ssl 进行通信https://your-domain-name.is:80
(开个玩笑......)