Tomcat server.xml多主机配置下Apache mod_proxy转发仅默认主机生效
Tomcat 匹配多虚拟主机的核心依据是 HTTP 请求的原生 Host 头字段,而非 X-Forwarded-Host 这类自定义转发头。
你使用的 mod_proxy 默认开启 ProxyPreserveHost Off:转发请求时会自动将原始请求的 Host 头替换为后端 Tomcat 的访问地址(即 localhost:8222),Tomcat 收到的 Host 既不匹配 www.AAA.com 也不匹配 www.BBB.com,只能 fallback 到 defaultHost 指定的默认主机,因此出现请求只能走默认主机的现象。
Tomcat 默认不会读取 X-Forwarded-* 头来做虚拟主机路由,所以你确认这些头配置正确也无法生效。
方案一:直接透传原始 Host 头(最常用,无额外配置)
在 Apache 的代理配置中新增 ProxyPreserveHost On,关闭 mod_proxy 对 Host 头的自动替换:
# 新增配置,保留客户端请求的原始Host头 ProxyPreserveHost On ProxyPass /path http://localhost:8222/path ProxyPassReverse /path http://localhost:8222/path
修改后重启 Apache 即可生效。此时 Tomcat 收到的 Host 头就是用户实际访问的域名,可直接匹配对应虚拟主机。
方案二:配置 Tomcat 自动解析转发头(无需修改 Apache Host 头逻辑)
如果因环境限制不能开启 ProxyPreserveHost,可以在 Tomcat 端配置 RemoteIpValve,让 Tomcat 自动用 X-Forwarded-Host 头的值替换请求的 Host 字段:
在 server.xml 的 <Engine> 或对应 <Host> 节点下添加以下 Valve 配置:
<Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="X-Forwarded-For" protocolHeader="X-Forwarded-Proto" portHeader="X-Forwarded-Port" hostHeader="X-Forwarded-Host" />
这个配置会自动覆盖 Tomcat 当前收到的原始 Host 头,用你已经配置正确的 X-Forwarded-Host 值来做虚拟主机匹配,同时还能顺带处理客户端真实 IP、协议识别的问题。
配置修改完成后,可通过 curl 模拟两个域名的请求直接测试 Tomcat:
# 测试AAA域名的请求 curl -H "Host: www.AAA.com" http://localhost:8222/path # 测试BBB域名的请求 curl -H "Host: www.BBB.com" http://localhost:8222/path
如果两个请求分别返回对应 docBase 配置的应用内容,就说明虚拟主机路由已经正常。
内容的提问来源于stack exchange,提问作者dashman

