基于名称的不可路由 IP 上的虚拟托管

基于名称的不可路由 IP 上的虚拟托管

我知道标题很模糊,但我不确定如何总结我想要实现的目标。

基本上,我有一个互联网路由器端口转发端口扩展端口 TCP 443 到运行 apache 2.2 的内部 IP 地址 linux 反向代理上的相同端口。

然后,该反向代理将连接转发到 Web 内容的实际主机。

以前,执行反向代理的服务器是互联网网关,并且它之所以能起作用是因为它具有 CNAME 解析为基于名称的虚拟托管的公共 IP 地址。

但是,由于现在该服务器具有内部 IP 地址,因此这已不起作用。

我该如何实现这一点,或者如果我想使用 CNAME 进行基于名称的虚拟托管,有没有更好的方法。

我曾经尝试过使用重写将地址重写为内部主机名,但是失败了,但由于这会改变客户端的地址,所以他们当然无法访问它。

<VirtualHost blah.somedomain.net:443>
    ServerName blah.somedomain.net

    RewriteEngine on
    RewriteCond %{HTTP_HOST} ^blah\.somedomain\.net$
    RewriteRule (.*) https://blah-proxy.somedomain.int
    <Location />
        Order deny,allow
        Allow from all
    </Location>
</VirtualHost>

<VirtualHost blah-proxy.somedomain.int:443>
    ServerName blah-proxy.somedomain.int
    ProxyPass / http://blah.somedomain.int/
    ProxyPassReverse / http://blah.somedomain.int/

    <Location />
        ProxyPassReverse /
        Order deny,allow
        Allow from all
    </Location>
    SSLEngine On
    Include /etc/letsencrypt/options-ssl-apache.conf
    SSLCertificateFile /etc/letsencrypt/live/blah.somedomain.net/cert.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/blah.somedomain.net/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/blah.somedomain.net/chain.pem
</VirtualHost>

有什么建议么?

干杯

安迪


我尝试了以下操作,添加了 IP 地址别名接口:

<VirtualHost 192.168.0.100:443>
    ServerName blah.somedomain.net
    ProxyPass / http://blah.somedomain.int/
    ProxyPassReverse / http://blah.somedomain.int/

    <Location />
        ProxyPassReverse /
        Order deny,allow
        Allow from all
    </Location>
    SSLEngine On
    Include /etc/letsencrypt/options-ssl-apache.conf
    SSLCertificateFile /etc/letsencrypt/live/blah.somedomain.net/cert.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/blah.somedomain.net/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/blah.somedomain.net/chain.pem
</VirtualHost>

我只是不明白来自外部来源的连接如何能够将端口转发到这个网络服务器,并且识别正确的虚拟主机并转发连接。

通过上述操作,它仍然会将 url 更改为 .int 并失败。

答案1

您的虚拟主机永远不匹配,因为您在其中使用了名称,尽管这是记录不推荐。您当前的设置就是原因之一。

由于您使用了名称,Apache 必须查找该名称以找到要侦听的 IP 地址,以便与该虚拟主机匹配的连接。由于该机器不再具有全局 IP 地址,因此 DNS 中的 IP 地址永远不会匹配。

您应该匹配任何地址。有时有充分的理由在 中指定 IP 地址<VirtualHost>,但几乎没有充分的理由使用名称。在这种情况下,没有真正的理由使用任何一个。

<VirtualHost *:443>

答案2

这里有多个问题。

  1. 如果您的 Web 服务器位于路由器后面,并且已启用端口转发,则会出现以下情况。来自 Internet 的请求会发送到路由器 Internet 连接的公共 IP。路由器根据端口转发规则识别内部站点的数据包,并替换所有这些数据包中的目标 IP。这意味着它会使用内部 IP 将该流量转发到您的内部服务器。对于您的服务器来说,没有其他事情,因为数据包的目标 IP 在通过路由器的过程中会发生变化。路由器还会确保正确识别从内部 Web 服务器获得的响应并将其发送回原始发送者,就好像它们是从路由器发送的一样。它会将您的内部服务器伪装(隐藏)在 Internet 上。因此,您应该在 VirtualHost 指令中使用内部 IP。

  2. 基于名称的 HTTPS (SSL) 虚拟主机于 2003 年制定,自 2007 年起开始提供。问题在于,基于名称的虚拟主机建立连接,然后在 HTTP 请求中发送站点名称。根据该 HTTP 请求的名称,Web 服务器知道正在寻址哪个虚拟站点。在 HTTPS 中,必须交换证书以验证站点,这样用户才能确定自己来到了正确的地方。在 HTTPS 请求中使用名称来请求站点为时已晚,因为那时必须已经交换了正确的证书。因此,引入了 SNI 扩展,允许基于名称的虚拟主机。请看这里https://wiki.apache.org/httpd/NameBasedSSLVHostsWithSNI和这里http://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslstrictsnivhostcheck。由于您有端口转发,因此目标 IP 将被替换,以便通过路由器到达您的虚拟主机。这意味着到达虚拟主机的数据包具有内部目标 IP,但站点名称不会改变。因此,您应该使用内部 IP 和正确的(外部)网站名称来进行虚拟主机配置。

  3. 然后,您就拥有了指向内容可用的实际站点的反向代理。您尚未指定该内容是在您的内部网络中还是在其他地方。事实上,这并不重要。您只需要确保可以使用反向代理配置中指定的地址从反向代理访问内容。尝试设置内部可访问的虚拟主机,您可以在其中测试反向代理。您可以通过为内部 IP 指定名称来做到这一点。使用 hosts 文件 (https://askubuntu.com/questions/183176/what-is-the-use-of-etc-hosts) 在您的客户端和 Web 服务器上。然后,您可以将这些名称用于基于内部名称的虚拟主机,您可以在其中测试代理和基于名称的虚拟主机。

我的建议是先设置一个站点,看看端口转发、反向代理等是否一切正常。然后添加其他站点。我在 DMZ 防火墙后面使用 SNI 配置了几乎相同的 Web 服务器,并将其用作内部网络中另一个站点的反向代理,并且运行良好。

答案3

经过一些修改和实验后,我得到了一个有效的配置:

<VirtualHost 192.168.20.250:443>
    ServerName blah.somedomain.net
    ProxyPass "/" "https://blah.somedomain.int/"
    ProxyPassReverse "/" "https://blah.somedomain.int/"

#    <Location />
#        ProxyPassReverse /
#        Order deny,allow
#        Allow from all
#    </Location>
    Loglevel debug
    ServerAdmin [email protected]
    ErrorLog logs/blah.somedomain.net-error_log
    CustomLog logs/blah.somedomain.net-access_log common
    SSLProxyEngine on
    SSLEngine On
    Include /etc/letsencrypt/options-ssl-apache.conf
    SSLCertificateFile /etc/letsencrypt/live/blah.somedomain.net/cert.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/blah.somedomain.net/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/blah.somedomain.net/chain.pem
</VirtualHost>

如果可以改进的话我很乐意听取建议但最重要的是它现在可以正常工作:)

感谢所有回复的人。

安迪

相关内容