简体   繁体   English

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

[英]Apache reverse proxy to Nginx forward proxy with TLS certificate

One of our clients wants to run a website trough his server to our webserver, so the website has the public ip of his server instead of ours. 我们的一位客户希望通过他的服务器运行一个网站到我们的网络服务器,因此该网站拥有他服务器的公共IP,而不是我们服务器的IP。 This works fine over http, but over https all goes berserk. 这可以在http上正常工作,但是在https上却可以发疯。

The client's server runs Virtualmin with Apache and our server runs Nginx with php-fpm. 客户端的服务器使用Apache运行Virtualmin,我们的服务器使用php-fpm运行Nginx。 We tried setting the same certificates for both the client's server and our webserver, but this site keeps showing handshake errors. 我们尝试为客户端的服务器和Web服务器设置相同的证书,但是此站点始终显示握手错误。

Both servers use exactly the same certificates. 两台服务器使用完全相同的证书。

Client's Apache config: 客户端的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

Our Nginx config: 我们的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;
  }
}

We would like to get this to work so we can use https://1.2.3.4:8123/ as the proxy address, to avoid MITM attacks and to be able to serve the website over https://some.site . 我们希望使它起作用,因此我们可以使用https://1.2.3.4:8123/作为代理地址,以避免MITM攻击并能够通过https://some.site为网站提供服务。

Creating a separate vhost in nginx, I found that the certificate wasn't set up properly. 我在nginx中创建了一个单独的虚拟主机,我发现证书没有正确设置。 curl -I -L https://1.2.3.4:8483 returned curl: (60) SSL certificate problem: unable to get local issuer certificate . curl -I -L https://1.2.3.4:8483返回curl: (60) SSL certificate problem: unable to get local issuer certificate Running openssl verify ssl.crt threw an error, where openssl verify -CAfile ssl.ca-bundle ssl.crt didn't, which confirmed that the ca-bundles were missing ( source of verify commands ). 运行openssl verify ssl.crt引发错误,而openssl verify -CAfile ssl.ca-bundle ssl.crt没有,这表明ca-bundle丢失了( 验证命令的来源 )。

As stated , nginx doesn't support separate ca-files, so I created a new file ssl.combined and added that to the ssl_certificate directive: cp ssl.crt ssl.combined; cat ssl.ca-bundle >> ssl.combined 至于 ,nginx的不支持独立CA-文件,所以我创建了一个新的文件ssl.combined并补充说,到ssl_certificate指令: cp ssl.crt ssl.combined; cat ssl.ca-bundle >> ssl.combined cp ssl.crt ssl.combined; cat ssl.ca-bundle >> ssl.combined . cp ssl.crt ssl.combined; cat ssl.ca-bundle >> ssl.combined Curl was happy now. 卷毛现在很高兴。

Apache had the same issue, but did support ca-files. Apache也有同样的问题,但确实支持ca文件。 Using SSLCertificateChainFile I added the ssl.ca-bundle . 使用SSLCertificateChainFile我添加了ssl.ca-bundle

Finally, with a sample configuration , I found the culprit: ProxyPreserveHost On is required for it all to work, which causes Apache to send the Proper Host-header over Proxy , which in turn makes the handshake work as it should. 最终,通过一个示例配置 ,我发现了罪魁祸首: ProxyPreserveHost On是所有功能都必需的,这导致Apache 通过Proxy发送适当的主机头 ,这反过来又使握手正常进行。

As a reference for others, I've added my final configurations below: 作为其他参考,我在下面添加了最终配置:

For Apache (client's server, reverse 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>
[...]

For nginx (our server, forward 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;
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM