Apache反向代理异常:仅一个代理指令生效,第二个被忽略
问题描述
在Windows Server 2019 Essentials系统上使用Apache 2.4.58,服务器有1个公网IP和两张内网网卡(192.168.3.100、192.168.3.200),在httpd-ssl.conf中配置了如下虚拟主机代理:
<VirtualHost _default_:443> <Proxy "http://192.168.3.100:20300/"> Require expr "(%{HTTP_HOST} == 'domain1.com') || (%{HTTP_HOST} == 'www.domain1.com')" ProxyPreserveHost On RequestHeader set X-ProxyBase "/" </Proxy> ProxyPass "/" "http://192.168.3.100:20300/" ProxyPassReverse "/" "http://192.168.3.100:20300/" <Proxy "http://192.168.3.200:20600/"> Require expr "(%{HTTP_HOST} == 'domain2.com') || (%{HTTP_HOST} == 'www.domain2.com')" ProxyPreserveHost On RequestHeader set X-ProxyBase "/" </Proxy> ProxyPass "/" "http://192.168.3.200:20600/" ProxyPassReverse "/" "http://192.168.3.200:20600/" </VirtualHost>
实际运行时仅http://192.168.3.100:20300/的代理生效,能正常访问domain1.com;访问domain2.com时会弹出**Forbidden You don't have permission to access this resource.**的权限错误。调换两个代理顺序问题依旧,只有注释掉第一个代理配置,才能正常访问domain2.com。
故障原因
- ProxyPass指令的匹配规则导致覆盖:Apache的
ProxyPass按配置顺序匹配请求路径,当你配置两个ProxyPass "/"指向不同后端时,第一个指令会先匹配所有请求,后续的ProxyPass "/"直接被忽略,所有请求都会被强制转发到第一个后端http://192.168.3.100:20300/。 - 权限规则不匹配触发403:当访问domain2.com时,请求被转发到第一个后端,但第一个
<Proxy>块的权限规则仅允许domain1.com的请求访问该后端,不符合规则就返回403禁止错误,完全没机会触发第二个代理的配置逻辑。
正确配置方案
要实现基于域名的反向代理,推荐两种配置方式:
方案1:独立VirtualHost配置(优先推荐)
给每个域名单独配置SSL虚拟主机,需确保每个域名有对应SSL证书:
# domain1.com的SSL虚拟主机 <VirtualHost *:443> ServerName domain1.com ServerAlias www.domain1.com SSLEngine on SSLCertificateFile "path/to/domain1.crt" SSLCertificateKeyFile "path/to/domain1.key" <Proxy "http://192.168.3.100:20300/"> Require all granted ProxyPreserveHost On RequestHeader set X-ProxyBase "/" </Proxy> ProxyPass "/" "http://192.168.3.100:20300/" ProxyPassReverse "/" "http://192.168.3.100:20300/" </VirtualHost> # domain2.com的SSL虚拟主机 <VirtualHost *:443> ServerName domain2.com ServerAlias www.domain2.com SSLEngine on SSLCertificateFile "path/to/domain2.crt" SSLCertificateKeyFile "path/to/domain2.key" <Proxy "http://192.168.3.200:20600/"> Require all granted ProxyPreserveHost On RequestHeader set X-ProxyBase "/" </Proxy> ProxyPass "/" "http://192.168.3.200:20600/" ProxyPassReverse "/" "http://192.168.3.200:20600/" </VirtualHost>
方案2:同一VirtualHost内使用条件判断
如果要在同一个VirtualHost里实现,可通过If指令结合HTTP_HOST区分请求:
<VirtualHost _default_:443> SSLEngine on # 配置通配符或多域名SSL证书 SSLCertificateFile "path/to/multi-domain.crt" SSLCertificateKeyFile "path/to/multi-domain.key" # 处理domain1.com的请求 <If "%{HTTP_HOST} in {'domain1.com', 'www.domain1.com'}"> <Proxy "http://192.168.3.100:20300/"> Require all granted ProxyPreserveHost On RequestHeader set X-ProxyBase "/" </Proxy> ProxyPass "/" "http://192.168.3.100:20300/" ProxyPassReverse "/" "http://192.168.3.100:20300/" </If> # 处理domain2.com的请求 <If "%{HTTP_HOST} in {'domain2.com', 'www.domain2.com'}"> <Proxy "http://192.168.3.200:20600/"> Require all granted ProxyPreserveHost On RequestHeader set X-ProxyBase "/" </Proxy> ProxyPass "/" "http://192.168.3.200:20600/" ProxyPassReverse "/" "http://192.168.3.200:20600/" </If> </VirtualHost>
内容的提问来源于stack exchange,提问作者Louis
相关产品推荐
相关产品推荐

