Nginx 反向代理 SSL 握手错误

Nginx 反向代理 SSL 握手错误

我拥有的:

  • 指向主机服务器的域名*.posmete.com。
  • 运行 ubuntu 18.04 的主机服务器(Google 云实例)
  • (主机服务器内部)名为“proxy”的 LXC 容器 1 运行 ubuntu 18.04 和 nginx 1.17 作为反向代理
  • (主机服务器内部)名为“web1”的 LXC 容器 2 运行 ubuntu 18.04 和 nginx 1.17 和 php7.4-fpm 以及 MySQL 8.0

两个带有 proxy_protocol=true 的 lxc 代理设备

igorkovalenko@xprs-tst:~$ lxc config device show proxy
myport80:
  connect: tcp:127.0.0.1:80
  listen: tcp:0.0.0.0:80
  proxy_protocol: "true"
  type: proxy
myport443:
  connect: tcp:127.0.0.1:443
  listen: tcp:0.0.0.0:443
  proxy_protocol: "true"
  type: proxy

我的容器列表:

igorkovalenko@xprs-tst:~$ lxc list
+-------+---------+----------------------+----------------------------------------------+-----------+-----------+
| NAME  |  STATE  |         IPV4         |                     IPV6                     |   TYPE    | SNAPSHOTS |
+-------+---------+----------------------+----------------------------------------------+-----------+-----------+
| proxy | RUNNING | 10.130.126.23 (eth0) | fd42:f63:4839:fedc:216:3eff:fe26:523b (eth0) | CONTAINER | 0         |
+-------+---------+----------------------+----------------------------------------------+-----------+-----------+
| web1  | RUNNING | 10.130.126.41 (eth0) | fd42:f63:4839:fedc:216:3eff:fe18:2fa3 (eth0) | CONTAINER | 0         |
+-------+---------+----------------------+----------------------------------------------+-----------+-----------+

我的 Nginx 反向代理配置(代理容器)

proxy_redirect              off;
proxy_set_header            Host            $http_host;
proxy_set_header            X-Real-IP       $remote_addr;
proxy_set_header            X-Forwared-For  $proxy_add_x_forwarded_for;
proxy_ssl_session_reuse on;
proxy_ssl_server_name on;

upstream backend {
      server web1:443;
}

server {

        server_name web1.posmete.com;

        location / {
#               proxy_set_header Host $host;
#               proxy_set_header X-Real-IP $remote_addr;
#               proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#               proxy_set_header X-Forwarded-Proto https;
#               proxy_ssl_session_reuse off;
#               proxy_ssl_server_name on;
#               proxy_ssl_protocols TLSv1.2;
#               proxy_set_header X-SSL-CERT $ssl_client_escaped_cert;
#               proxy_ssl_certificate  /etc/letsencrypt/live/web1.posmete.com/fullchain.pem;
#               proxy_ssl_certificate_key /etc/letsencrypt/live/web1.posmete.com/privkey.pem;
                proxy_pass https://backend;
#               proxy_redirect http:// https://;

        }

        real_ip_header proxy_protocol;
        set_real_ip_from 127.0.0.1;

    listen [::]:443 ssl proxy_protocol; # managed by Certbot
    listen 443 ssl proxy_protocol; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/web1.posmete.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/web1.posmete.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
    if ($host = web1.posmete.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


        listen 80 proxy_protocol;
        listen [::]:80 proxy_protocol;

        server_name web1.posmete.com;
    return 404; # managed by Certbot


}

我的 Nginx Web 服务器配置(web1 容器)

server {
#    listen       80;
    listen 443;

    server_name  web1.posmete.com;

    root   /usr/share/nginx/html;
    index  index.php;

    location = /50x.html {
        root   /usr/share/nginx/html;
    }


    location / {
                try_files $uri $uri/ /index.php?$args;
        }

       location = /favicon.ico {
                log_not_found off;
                access_log off;
        }

        location = /robots.txt {
                allow all;
                log_not_found off;
                access_log off;
        }

    location ~* \.php$ {
        if ($uri !~ "^/uploads/") {
            fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        }
        include                      fastcgi_params;
        fastcgi_intercept_errors     on;
        fastcgi_param                SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param                SCRIPT_NAME $fastcgi_script_name;
    }

     location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
            expires max;
            log_not_found off;
     }

    location ~ /\.ht {
        deny  all;
    }
}

我想要实现的目标:

我正在尝试通过 https 连接使用 Wordpress 安装脚本在 lxc 容器“web1”内安装 Wordpress。

我遇到过什么问题:

web1.posmete.com 502 错误网关

来自代理服务器日志的错误:

2020/03/24 15:20:44 [error] 4199#4199: *42 SSL_do_handshake() failed (SSL: error:1408F10B:SSL routines:ssl3_get_record:wrong version number) while SSL handshaking to upstream, client: 169.197.108.42, server: web1.posmete.com, request: "GET /remote/login HTTP/1.1", upstream: "https://10.130.126.41:443/remote/login", host: "35.198.175.173"
2020/03/24 15:20:44 [warn] 4199#4199: *42 upstream server temporarily disabled while SSL handshaking to upstream, client: 169.197.108.42, server: web1.posmete.com, request: "GET /remote/login HTTP/1.1", upstream: "https://10.130.126.41:443/remote/login", host: "35.198.175.173"
2020/03/24 15:20:44 [error] 4199#4199: *42 connect() failed (111: Connection refused) while connecting to upstream, client: 169.197.108.42, server: web1.posmete.com, request: "GET /remote/login HTTP/1.1", upstream: "https://[fd42:f63:4839:fedc:216:3eff:fe18:2fa3]:443/remote/login", host: "35.198.175.173"
2020/03/24 15:20:44 [warn] 4199#4199: *42 upstream server temporarily disabled while connecting to upstream, client: 169.197.108.42, server: web1.posmete.com, request: "GET /remote/login HTTP/1.1", upstream: "https://[fd42:f63:4839:fedc:216:3eff:fe18:2fa3]:443/remote/login", host: "35.198.175.173"
2020/03/24 15:20:49 [info] 4199#4199: *42 client 127.0.0.1 closed keepalive connection

来自 Web 服务器日志的错误:

10.130.126.23 - - [24/Mar/2020:15:20:44 +0000] "\x16\x03\x01\x00\xCD\x01\x00\x00\xC9\x03\x03\xB6j\x9Ef\x90\x08\x90O\x8A-VYw\xD8\x09rn\xD1\x10\xB1m\xCF\x0E\xDE\x95\x83]e\xC6J\x14\x06\x00\x008\xC0,\xC00\x00\x9F\xCC\xA9\xCC\xA8\xCC\xAA\xC0+\xC0/\x00\x9E\xC0$\xC0(\x00k\xC0#\xC0'\x00g\xC0" 400 157 "-" "-" "-"

我尝试了几乎所有通过互联网提供的说明,但仍然出现 502 错误。只有一个解决方案产生了积极效果 - 那就是将 SSL 证书从代理复制到 Web。但我想避免这种情况,并使用 certbot 从一个地方管理证书。

因此,基本上通过 HTTP 一切正常,但通过 https 出现 502 错误

答案1

如果不复制私钥和证书,握手就无法完成:

TLS(版本 1.3)握手由一条ClientHello消息发起,该消息的响应预期为ServerHelloEncryptedExtensionsCertificate和消息。该消息包含证书,而消息包含使用私钥计算的签名。因此,如果不复制私钥和证书,握手就无法完成。CertificateVerifyCertificateCertificateVerify

您需要复制。

当您考虑 SSL/TLS 的属性时,重复的需要应该变得直观,因为 SSL/TLS 用于服务器身份验证(这需要私钥,否则无法实现身份验证)。

或者,您可以使用两个不同的私钥和证书。如果您可以接受,我会详细说明。

相关内容