Apache反向代理到具有TLS证书的Nginx正向代理

时间:2019-09-04 10:37:34

标签: php apache nginx proxy

我们的一位客户希望通过其服务器运行一个网站到我们的Web服务器,因此该网站使用了他服务器的公共IP,而不是我们服务器的IP。这可以在http上正常工作,但是在https上却可以发疯。

客户端的服务器使用Apache运行Virtualmin,我们的服务器使用php-fpm运行Nginx。我们尝试为客户端的服务器和我们的Web服务器设置相同的证书,但是此站点始终显示握手错误。

两个服务器使用完全相同的证书。

客户端的Apache配置:

ProxyPass / http://1.2.3.4:8123/
ProxyPassReverse / http://1.2.3.4:8123/
SSLProxyEngine on
    SSLProxyCheckPeerCN on
    SSLProxyCheckPeerExpire on
SSLEngine on
SSLCertificateFile /foo/bar/ssl.cert
SSLCertificateKeyFile /foo/bar/ssl.key
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
SSLCACertificateFile /foo/bar/ssl.ca

我们的Nginx配置:

server {
  listen 8123;
  server_name some.site wwww.some.site;

  ssl_certificate /foo/bar/ssl.crt;
  ssl_certificate_key /foo/bar/ssl.crt
  ssl_prefer_server_ciphers on;

  root /var/www/some.site/public;
  index index.php;
  charset utf-8;

  location ~ /\. {
    deny all;
  }

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

  location ~ \.php$ {
    fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
    fastcgi_index index.php;
    include /etc/nginx/fastcgi_params;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header Host $host;
  }
}

我们希望此功能能够正常工作,以便我们可以使用https://1.2.3.4:8123/作为代理地址,以避免MITM攻击并能够通过https://some.site来为网站提供服务。

1 个答案:

答案 0 :(得分:0)

在nginx中创建一个单独的虚拟主机,我发现证书设置不正确。 curl -I -L https://1.2.3.4:8483返回了curl: (60) SSL certificate problem: unable to get local issuer certificate。运行openssl verify ssl.crt时引发了一个错误,而openssl verify -CAfile ssl.ca-bundle ssl.crt却没有,这表明ca束丢失了(source of verify commands)。

stated一样,nginx不支持单独的ca文件,因此我创建了一个新文件ssl.combined并将其添加到ssl_certificate指令中:cp ssl.crt ssl.combined; cat ssl.ca-bundle >> ssl.combined。卷毛现在很开心。

Apache也有同样的问题,但是确实支持ca文件。我使用SSLCertificateChainFile添加了ssl.ca-bundle

最后,使用sample configuration,我发现了罪魁祸首:ProxyPreserveHost On才能正常工作,这导致Apache发送正确的Host-header over Proxy,这反过来又使握手可以正常工作。

作为其他参考,我在下面添加了最终配置:

对于Apache(客户端服务器,反向代理):

[...]
SSLEngine on
SSLCertificateFile /foo/bar/ssl.cert
SSLCertificateKeyFile /foo/bar/ssl.key
SSLCertificateChainFile /foo/bar/ssl.ca

ProxyRequests off
ProxyPreserveHost On
SSLProxyEngine on
SSLProxyCheckPeerCN on
SSLProxyCheckPeerExpire on

ProxyPass / https://1.2.3.4:8483/
ProxyPassReverse / https://1.2.3.4:8483/

<Proxy *>
  allow from all
</Proxy>
[...]

对于nginx(我们的服务器,转发代理):

server {
  listen 8483 ssl;
  server_name site.url www.site.url;

  ssl on;
  ssl_certificate /foo/bar/ssl.combined;
  ssl_certificate_key /foo/bar/ssl.key;
  ssl_stapling on;
  ssl_stapling_verify on;

  root /var/www/site.url/public
  index index.php;
  charset utf-8;

  location ~ /\. {
    deny all;
  }

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

  location ~ \.php$ {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Host $host;
    fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
    fastcgi_index index.php;
    include /etc/nginx/fastcgi_params;
  }
}