访问 docker 容器内的 https 站点时超时,使用 http 可以正常工作

Lis*_*iso 8 ssl docker dockerfile

我无法使用 SSL 访问 docker 容器内的网站。下面是 的输出curl -Ls -o /dev/null -v http://docker-mydomain.xyz

\n
...\n...\n* TLSv1.2 (IN), TLS handshake, Finished (20):\n{ [16 bytes data]\n* SSL connection using TLSv1.2 / ECDHE-ECDSA-AES256-GCM-SHA384\n* ALPN, server accepted to use http/1.1\n* Server certificate:\n*  subject: CN=docker-mydomain.xyz\n*  start date: Jan 26 07:12:47 2023 GMT\n*  expire date: Apr 26 07:12:46 2023 GMT\n*  subjectAltName: host "docker-mydomain.xyz" matched cert's "docker-mydomain.xyz"\n*  issuer: C=US; O=Let's Encrypt; CN=R3\n*  SSL certificate verify ok.\n* TLSv1.2 (OUT), TLS header, Supplemental data (23):\n} [5 bytes data]\n> GET / HTTP/1.1\n> Host: docker-mydomain.xyz\n> User-Agent: curl/7.81.0\n> Accept: */*\n>\n
Run Code Online (Sandbox Code Playgroud)\n

它会停留在Accept: */*进程上直到超时,但是如果我切换到 http,它就可以正常工作。容器设置为侦听8080端口。

\n

docker ps输出。

\n
CONTAINER ID   IMAGE             COMMAND                  CREATED       STATUS       PORTS                      NAMES\n150f5a5c08c4   liso/testdocker   "/usr/local/bin/dock\xe2\x80\xa6"   6 hours ago   Up 6 hours   127.0.0.1:8080->8080/tcp   testdocker\n
Run Code Online (Sandbox Code Playgroud)\n

docker 容器外部的VirtualHost 。

\n
<VirtualHost *:80>\n    ServerName docker-mydomain.xyz\n    Redirect permanent / https://docker-mydomain.xyz/\n</VirtualHost>\n\n<VirtualHost *:443>\n    ServerName docker-mydomain.xyz    \n    ProxyRequests Off    \n    <Location />\n        ProxyPreserveHost On\n        ProxyPass http://127.0.0.1:8080/\n        ProxyPassReverse http://127.0.0.1:8080/\n    </Location>\n    # SSL Location\n    SSLEngine on\n    SSLCertificateFile /etc/le/docker-mydomain.xyz/cert.pem\n    SSLCertificateKeyFile /etc/le/docker-mydomain.xyz/site.key\n    SSLCertificateChainFile /etc/le/docker-mydomain.xyz/fullchain.cer\n</VirtualHost>\n
Run Code Online (Sandbox Code Playgroud)\n

docker 容器内的虚拟主机。

\n
<VirtualHost *:8080>\n    DocumentRoot /var/www/testdocker\n    <Directory /var/www/testdocker/>\n         Options FollowSymLinks MultiViews\n         AllowOverride None\n         Require all granted\n    </Directory>\n    ErrorLog ${APACHE_LOG_DIR}/error.log\n    CustomLog ${APACHE_LOG_DIR}/access.log combined\n</VirtualHost>\n
Run Code Online (Sandbox Code Playgroud)\n

我可以确认网站在 docker 容器外工作没有问题,我检查了容器内的 apache 日志,发现没有传入流量。

\n
\n

请随意询问任何问题,如果需要,我很乐意发布任何日志。

\n

docker 容器外部的网站使用 http/https 可以正常工作。

\n

Von*_*onC 2

如果我理解正确的话,你有:

\n
Client (Browser)\n       \xe2\x94\x82\n       \xe2\x94\x82 HTTPS Request\n       \xe2\x96\xbc\n[Reverse Proxy (Apache outside Docker)]\n       \xe2\x94\x82 SSL Termination\n       \xe2\x94\x82\n       \xe2\x94\x82 HTTP Request\n       \xe2\x96\xbc\n[Apache Server Inside Docker Container]\n       \xe2\x94\x82 Listens on Port 8080\n       \xe2\x94\x82\n       \xe2\x94\x82 (The request seems to hang here)\n       \xe2\x94\x82\n       \xe2\x96\xbc\n[Web Application in Docker (Files in /var/www/testdocker)]\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 客户端(如 Web 浏览器)向您的域发起 HTTPS 请求 ( docker-mydomain.xyz)。
  • \n
  • 该请求到达在 Docker 容器外部使用 Apache 设置的反向代理。此处,发生 SSL 终止,将 HTTPS 请求转换为 HTTP 请求。
  • \n
  • 然后,此 HTTP 请求被转发到在 Docker 容器内运行的 Apache 服务器,监听端口 8080。
  • \n
  • Docker 容器内的 Apache 服务器应该处理此 HTTP 请求,并从目录中获取所需的文件/var/www/testdocker来为请求的网页提供服务。
  • \n
  • 但是,根据您的描述,请求似乎挂在 Docker 容器内的 Apache 服务器上,并且请求未到达/var/www/testdocker.
  • \n
\n

这意味着 Docker 容器内的反向代理和 Apache 服务器之间的交互导致 HTTP 请求无法按预期得到处理。

\n

首先检查该ProxyPreserveHost On指令:它是在端口 443 的配置中设置的。VirtualHost这意味着当请求代理到后端服务器时,传入请求的主机标头将被保留。在您的情况下,Docker 容器期望端口 8080 上的 HTTP 流量。保留 HTTPS 主机标头可能会导致问题。您可以考虑将其关闭,看看是否能解决问题。

\n

您还提到在 Docker 容器内的 Apache 日志中没有观察到传入流量。这可能意味着容器内的 Apache 设置存在网络或配置问题。
\n仔细检查 Apache 是否确实在容器内的端口 8080 上运行并侦听。您可能想尝试使用curl或直接从容器内访问 Apache,wget看看它是否正确响应 HTTP 请求。

\n

从容器外部,用于curl通过 HTTP 直接与容器内的 Apache 服务器交互,以查看其是否可访问。您可以运行类似于下面的命令:

\n
Client (Browser)\n       \xe2\x94\x82\n       \xe2\x94\x82 HTTPS Request\n       \xe2\x96\xbc\n[Reverse Proxy (Apache outside Docker)]\n       \xe2\x94\x82 SSL Termination\n       \xe2\x94\x82\n       \xe2\x94\x82 HTTP Request\n       \xe2\x96\xbc\n[Apache Server Inside Docker Container]\n       \xe2\x94\x82 Listens on Port 8080\n       \xe2\x94\x82\n       \xe2\x94\x82 (The request seems to hang here)\n       \xe2\x94\x82\n       \xe2\x96\xbc\n[Web Application in Docker (Files in /var/www/testdocker)]\n
Run Code Online (Sandbox Code Playgroud)\n

如果这不起作用,请查看是否有任何防火墙或安全设置阻止反向代理通过 HTTP 与 Docker 容器内的 Apache 服务器进行通信。

\n
\n
\n
    \n
  • 防火墙已关闭
  • \n
  • 我可以确认使用其端口(curl https://127.0.0.1:8080 )直接卷曲容器可以正常工作。
  • \n
  • 更改ProxyPreseveHost OnOff没有任何效果。
  • \n
  • openssl s_client -connect docker-mydomain.xyz:443在“扩展主密钥:否”上停留 1 分钟,然后关闭并且命令结束。
  • \n
\n
\n

考虑到这些观察结果,我们可以怀疑问题可能出在反向代理设置和 Docker 容器之间。检查 Apache 配置中的 SSL 设置和代理指令可能会有所帮助。

\n
    \n
  • 确保SSLCipherSuiteApache 配置中的指令配置正确并支持必要的协议。有时,SSL 配置的差异可能会导致此类问题。

    \n
  • \n
  • 检查端口 443 的代理配置。VirtualHost鉴于直接卷曲到容器的端口工作正常,问题似乎出在代理设置中。考虑查看ProxyPassProxyPassReverse指令以确保它们配置正确。

    \n
  • \n
  • 重新访问反向代理服务器上的 Apache 错误和访问日志,以获取可能表明连接终止原因的任何其他提示或错误消息。

    \n
  • \n
  • SSL 握手可能存在问题。考虑重新评估 Apache 设置中的 SSL 证书配置。
    \n作为调试步骤,您可以尝试设置一个VirtualHost不带 SSL 的 HTTP(端口 80)来代理对 Docker 容器的请求,以查看在不使用 SSL 层的情况下是否可以正常工作。

    \n
  • \n
\n

如果所有其他方法都失败,作为最后的手段,请考虑从头开始设置反向代理配置,一步一步,在每个阶段进行测试以确保其正常工作。

\n