VPS 部署实录:Caddy 反代 FreePBX 与内部 Web 服务共存

技术专业 · 昨天

环境:VPS, Caddy (Web Server), FreePBX (Asterisk/Apache), 内部Web服务

域名:xx.com (示例)

1. 部署目标

在同一台 VPS 上同时运行 FreePBX 和另一个内部 Web 服务,并通过 Caddy 作为前置反向代理实现以下需求:

  1. 统一入口:Caddy 监听标准的 80 和 443 端口,对外提供 HTTPS 服务。
  2. 路径分流

    • 访问 /xx-path (特定路径) -> 转发给 内部Web服务 (端口 8088)。
    • 访问 根路径 / 及其他 -> 转发给 FreePBX (端口 8080)。
  3. 安全加密:FreePBX 的 SIP 流量 (5061) 复用 Caddy 申请的证书实现 TLS 加密。

2. 遇到的问题

问题一:端口冲突与 HTTPS 证书申请失败

  • 现象:FreePBX 默认占用 80 端口,导致 Caddy 无法启动且无法申请 Let's Encrypt 证书。
  • 解决:将 FreePBX (Apache) 的监听端口改为 8080,腾出 80443 给 Caddy。

问题二:FreePBX 的“显性跳转”顽疾 (Critical)

  • 现象:

    虽然 Caddy 已经配置了反向代理,但在浏览器访问 https://xx.com 时,浏览器地址栏会自动变成 http://xx.com:8080/admin/...

    这暴露了后端真实端口,且因为是 HTTP 协议,浏览器提示“不安全”。

  • 原因分析:

    FreePBX (Apache) 并没有意识到自己运行在代理后面。当它需要进行页面重定向(如跳转到登录页)时,它根据自己监听的端口 (8080) 生成了 HTTP 302 跳转响应(Location Header),直接把用户踢回了 8080 端口。

  • 尝试修复:

    最初尝试添加请求头 X-Forwarded-Proto https 和 X-Forwarded-Port 443,但这只能解决一部分内部链接生成问题,无法拦截 Apache 已经发出的 Location 跳转指令。

3. 最终解决方案

通过修改 Caddyfile,实施了双重策略:

  1. 请求欺骗 (Header Up):告诉 FreePBX “用户是用 HTTPS 和 443 端口进来的,请配合”。
  2. 响应篡改 (Header Down):这是关键一招。当 Caddy 收到 FreePBX 返回的“去 8080”的跳转指令时,强行将其修改为正确的 HTTPS 地址,再发给浏览器。

最终生效的 Caddyfile 配置:

代码段

xx.com {
    # --- 流量分流策略 ---
    
    # 1. 特殊路径分流给内部Web服务 (8088)
    reverse_proxy /xx-path 127.0.0.1:8088 {
        header_up Host {host}
        header_up X-Real-IP {remote}
        header_up X-Forwarded-For {remote}
        # 支持 WebSocket
        header_up Connection {http.request.header.Connection}
        header_up Upgrade {http.request.header.Upgrade}
    }

    # 2. 默认流量分流给 FreePBX (8080)
    reverse_proxy 127.0.0.1:8080 {
        header_up Host {host}
        header_up X-Real-IP {remote}
        header_up X-Forwarded-For {remote}
        
        # 欺骗后端:这是 HTTPS 请求
        header_up X-Forwarded-Proto https
        header_up X-Forwarded-Port 443
        
        # 【关键修复】拦截并重写响应头中的跳转地址
        # 将 http://...:8080 替换为 https://...
        # 彻底解决浏览器跳转到 8080 端口的问题
        header_down Location http://xx.com:8080 https://xx.com
    }
}

4. 实施结果

  1. HTTPS 完美访问:访问 https://xx.com 不再跳转端口,全程保持 HTTPS 绿锁状态。
  2. 分流正常:特定路径 /xx-path 正确指向内部服务,互不干扰。
  3. 安全性提升:可以通过防火墙彻底封锁 8080 和 8088 的对外直接访问,仅允许 Caddy 访问,消除了安全隐患。

5. 后续备忘 (SIP TLS)

  • FreePBX 的 SIP 通话加密 (TLS 5061) 不经过 Caddy,但可复用证书。
  • 配置方法:需将 Caddy 申请的证书 (/var/lib/caddy/...) 复制到 /etc/asterisk/keys/,并授权给 asterisk 用户,然后在 FreePBX 面板启用 TLS 绑定 5061 端口即可。
Theme Jasmine by Kent Liao