Docker容器虚拟主机SSL配置

时间:2017-11-09 17:57:47

标签: apache ssl docker virtualhost http-proxy

我有以下设置并正常工作(我在Docker 1.6上):

enter image description here

一个Docker容器充当在各个Docker容器中运行的其他Web应用程序的虚拟主机代理。 (我应该补充一点,我不是在配置服务器或网络时的高手。)

我一直在尝试将SSL添加到设置中,但收效甚微。每个容器都在主机上安装文件目录以获取证书。例如,要在使用以下内容后运行容器:

docker run -d -P --name build \
    -v /home/applications/src/ssl-cert:/etc/ssl/certs \
    -e "DBL=mysql:dbname=build;host=192.168.0.1;port=3306" \
    -e "DB_USER=foo" -e "DB_PASS=bar" \
    --link mysql56:mysql \
    --add-host dockerhost:`/sbin/ip addr | grep 'eth0' | grep 'inet' | cut -d'/' -f1 | awk '{print $2}'` \
    -p 8001:80 -p 4431:443 \
     repos/build:latest

如果我尝试连接到https://build.example.com,我会收到证书错误,无法连接。容器的Apache配置在default-ssl.conf中为证书文件配置了相应的配置(如果这是一个独立的实例,则可以使用):

<VirtualHost _default_:443>
    ServerAdmin webmaster@localhost

    DocumentRoot /var/www/html/

    # Enable/Disable SSL for this virtual host.
    SSLEngine on

    SSLProtocol all -SSLv2 -SSLv3
    SSLHonorCipherOrder On
    SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS

    SSLCertificateFile /etc/ssl/certs/build.crt
    SSLCertificateKeyFile /etc/ssl/certs/build.key
    SSLCACertificateFile /etc/ssl/certs/digicert/digicertca.crt

    #SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
    <FilesMatch "\.(cgi|shtml|phtml|php)$">
        SSLOptions +StdEnvVars
    </FilesMatch>
    <Directory /usr/lib/cgi-bin>
        SSLOptions +StdEnvVars
    </Directory>

    BrowserMatch "MSIE [2-6]" \
        nokeepalive ssl-unclean-shutdown \
        downgrade-1.0 force-response-1.0
    # MSIE 7 and newer should be able to use keepalive
    BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown

</VirtualHost>

然后我尝试为代理容器运行以下命令:

docker run -it -d -P --name apache_proxy \
    -v /home/applications/src/ssl-cert:/etc/ssl/certs \
    -p 8000:80 -p 443:443 \
    repos/apache-proxy:latest

此容器还包含相同的default-ssl.conf。

我尝试过几种不同的配置:

  • 仅在Apache代理容器中运行SSL配置
  • 仅在构建应用程序容器中运行SSL配置
  • 在两个容器中运行SSL配置

如果觉得我错过了一些明显的东西,却无法指责它会是什么。在这样的配置中运行SSL时,我有什么遗漏的东西吗?

2 个答案:

答案 0 :(得分:4)

当我们想要向反向代理后面的主机添加SSL时,我们可以通过三种方式配置主机:

  • Edge:反向代理解密传入的HTTPS流量,并通过纯文本HTTP与后端服务器通信。
  • 传递:后端服务器解密所有流量,反向代理只是将HTTPS请求转发给它们。
  • 混合:反向代理解密HTTPS流量,然后重新加密绑定到后端服务器的流量。

第一个选项是最容易设置 - 我们只需要在反向代理上安装证书并配置SSL。第二个,&#34;传递&#34;方法使后端服务器能够独立地管理他们的SSL配置,但反向代理现在是盲目的&#34;因为它无法读取加密流量,我们可能希望为(示例)日志记录执行此操作。当代理必须读取流量但我们也不信任代理和后端服务器之间的网络时,我们使用第三种混合配置。

根据问题中的信息,第一个选项似乎最合适,因为我们信任反向代理和后端服务器之间的内部Docker网络。我们可以从后端服务器中删除SSL配置,并将来自反向代理的请求转发到其标准HTTP端口。

此设置需要两个额外的组件:

  • 在代理上配置的基于名称的虚拟主机,用于转发每个后端服务的请求。
  • 证书,用于保护所有后端域名(作为多个主题或通配符,如 * .example.com

这是我们可以构建的示例虚拟主机配置部分:

<VirtualHost *:443>
    ServerName build.example.com
    ProxyRequests Off
    ProxyPreserveHost On 
    ProxyPass / http://build:8001/ 
    ProxyPassReverse / http://build:8001/
</VirtualHost>
<VirtualHost *:443>
    ServerName cicd.example.com
    ProxyRequests Off
    ProxyPreserveHost On 
    ProxyPass / http://cicd:8002/ 
    ProxyPassReverse / http://cicd:8002/
</VirtualHost>

...并且记得在默认虚拟主机块中配置SSL指令。如果我们链接容器或在同一个Docker网络上运行它们,我们可以在我们的 httpd.conf 中使用它们的容器名称作为主机名,如上所示。

说到网络,问题似乎表明我们需要仔细研究Docker networking,因为我没有看到任何提示表明容器被配置为相互通信的提示( 503响应状态支持这种假设)。反向代理容器必须将请求转发到每个后端容器,但除非我们link the containers已弃用)或在容器之间创建内部user-defined network,否则它不能这样做:

$ docker network create build_network
$ docker run --network build_network --name apache_proxy ...
$ docker run --network build_network --name build ...
$ docker run --network build_network --name cicd ...

当我们在同一个用户定义的网络上运行容器时,他们可以通过Docker的内部DNS解析器按容器名解析其他容器的IP地址(如果我们指定{{1},则可以通过备用主机名解析其他容器的IP地址} --hostname的参数。另请注意,由于每个容器代表离散主机,因此我们不需要增加其端口号( 8001 8002 等)。我们可以使用端口80来提供来自内部网络上每个容器的HTTP流量。

docker run

答案 1 :(得分:2)

通常,如果您的服务器在Apache服务器后面运行,您只需要配置Apache即可使用SSL证书。 如果Apache是​​唯一的“外部”公开服务器,而其他服务器无法直接从外部访问

您需要使用apache通过URL或端口代理其他服务器,例如:。

<VirtualHost *:443>
    ServerName SERVERNAME_HERE

    SSLProtocol all -SSLv2 -SSLv3
    SSLHonorCipherOrder On
    SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS

    SSLCertificateFile /etc/ssl/certs/build.crt
    SSLCertificateKeyFile /etc/ssl/certs/build.key
    SSLCACertificateFile /etc/ssl/certs/digicert/digicertca.crt

    # Proxy pass to other server
    ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass / http://OTHER_SERVER_IP_WITHIN_DOCKER_NETWORK:8081/
    ProxyPassReverse / http://OTHER_SERVER_IP_WITHIN_DOCKER_NETWORK:8081/

<!--Other config-->
</VirtualHost>

希望能帮助你...