HAProxy 如何实现基于域名的虚拟主机多域名转发配置

文章导读
HAProxy 通过在前端(frontend)定义基于 HTTP Host 头的访问控制列表(ACL),将不同域名的请求分发到对应的后端(backend)服务器池,实现单 IP 多域名转发。该方案适用于 HTTP 和 HTTPS 流量共享同一入口 IP 的场景,配置错误可能导致请求被默认后端接收或返回 503 服务不可用。
📋 目录
  1. 快速处理思路
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
  6. 常见问题
  7. 参考来源
A A

HAProxy 通过在前端(frontend)定义基于 HTTP Host 头的访问控制列表(ACL),将不同域名的请求分发到对应的后端(backend)服务器池,实现单 IP 多域名转发。该方案适用于 HTTP 和 HTTPS 流量共享同一入口 IP 的场景,配置错误可能导致请求被默认后端接收或返回 503 服务不可用。

先说结论:HAProxy 实现多域名转发的核心是利用 layer 7 模式下的 acl 规则匹配 host 字段,并联动 use_backend 指令指向不同服务器组。

  • 适合:Web 服务多域名托管、SaaS 平台租户隔离、动静分离场景
  • 先准备:确保所有域名 DNS 解析已指向 HAProxy 服务器 IP
  • 验收:使用 curl 命令携带 Host 头验证路由指向是否正确

快速处理思路

HAProxy 配置基于文本文件,核心逻辑是在 frontend 段编写 acl 规则。以下是最小可用配置片段,直接替换 haproxy.cfg 中对应 section 即可。

frontend http_front
    bind *:80
    acl host_blog hdr(host) -i blog.example.com
    acl host_shop hdr(host) -i shop.example.com
    use_backend blog_servers if host_blog
    use_backend shop_servers if host_shop
    default_backend web_servers

backend blog_servers
    balance roundrobin
    server blog1 192.168.1.10:80 check

backend shop_servers
    balance roundrobin
    server shop1 192.168.1.20:80 check

backend web_servers
    balance roundrobin
    server web1 192.168.1.30:80 check

为什么会这样

HAProxy 工作在 OSI 模型第七层(应用层)时能够读取 HTTP 请求头中的 Host 字段。当客户端发起请求时,HAProxy 先接收连接,解析 HTTP Header,根据配置的 acl 规则匹配 Host 值,再决定将连接转发给哪个 backend 定义的真实服务器池,从而实现同一 IP 端口承载多个域名。

分步处理

按顺序修改配置文件并 reload 服务,每步完成后检查语法是否正确。

步骤 1:备份配置文件
操作动作:执行 cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak。
风险边界:防止配置错误导致服务无法启动,保留回滚依据。

步骤 2:编辑 frontend 段
操作动作:在 frontend section 中添加 acl 定义,使用 hdr(host) 匹配域名。
检查点:确保域名拼写正确,-i 参数表示忽略大小写。

步骤 3:定义 backend 段
操作动作:为每个 acl 对应的 use_backend 创建独立的 backend section。
检查点:backend 名称必须与 use_backend 调用的名称完全一致。

步骤 4:设置默认后端
操作动作:在 frontend 末尾添加 default_backend 指令。
风险边界:未设置默认后端时,不匹配任何 acl 的请求会返回 503 错误。

HAProxy 如何实现基于域名的虚拟主机多域名转发配置

步骤 5:验证并重载
操作动作:执行 haproxy -c -f /etc/haproxy/haproxy.cfg 检查语法,成功后执行 systemctl reload haproxy。
验证结果:命令返回 Configuration file is valid 且服务无中断。

怎么验证是否生效

使用 curl 命令模拟携带特定 Host 头的请求,观察响应内容或响应头。

检查命令:
curl -H "Host: blog.example.com" http://<HAProxy_IP>/
curl -H "Host: shop.example.com" http://<HAProxy_IP>/

日志位置:
/var/log/haproxy.log 或 journald 日志。
状态判断:日志中应显示不同 backend 的名称或后端服务器 IP,确认流量被分发到预期池。

常见坑

配置过程中容易忽略细节导致路由失效或安全风险,以下场景需谨慎处理。

  • 大小写敏感:虽然 HTTP 标准规定 Host 不区分大小写,但建议配置 acl 时加上 -i 参数确保兼容。
  • SSL 终止问题:如果是 HTTPS 流量,需在 frontend 绑定 443 端口并配置 crt 证书,否则 HAProxy 无法解密读取 Host 头。
  • 后端健康检查:未配置 check 参数时,HAProxy 可能将流量转发到已宕机的后端服务器。
  • Host 头注入:不要信任客户端传来的 Host 头用于生成重定向 URL,需在 backend 中强制重写 Host 或限制允许的值。

常见问题

HTTPS 域名转发需要特殊配置吗?

需要,HAProxy 必须先终止 SSL 才能读取 Host 头。需在 frontend bind 指令后添加 ssl crt 参数指定证书文件,或者使用 SNI 匹配在不解密情况下路由。

多个域名可以指向同一个后端吗?

可以,多个 acl 规则可以调用同一个 use_backend 指令,或者在一条 acl 中使用 -m beg 匹配多个子域名。

没有匹配到任何域名会怎样?

如果没有配置 default_backend,HAProxy 会返回 503 Service Unavailable 错误,建议始终配置默认后端处理未知域名。

参考来源

  • HAProxy Technologies, "HAProxy Configuration Manual", https://www.haproxy.com/documentation/haproxy-configuration-manual/latest/
  • HAProxy.org, "Introduction to HAProxy", https://www.haproxy.org/