Apache 可以借助 mod_proxy 模块及其相关子模块充当反向代理,把客户端请求转发给后端服务器并返回后端的响应。
反向代理作为客户端请求的中间层,将请求定向到一台或多台内部后端服务器。它对互联网提供统一的入口,同时隐藏内部网络架构。其好处包括增强安全性、负载均衡、SSL/TLS 终止、缓存以及简化后端管理。
启用 mod_proxy
要把 Apache 配置为反向代理,必须启用核心模块 mod_proxy 以及特定的子模块。这些模块提供不同的协议支持和功能。
必需模块:
mod_proxy:核心代理模块。mod_proxy_http:用于代理 HTTP 和 HTTPS 流量。mod_proxy_balancer:在多台后端服务器之间做负载均衡时必需。mod_proxy_wstunnel:用于 WebSocket 代理。mod_ssl:当 Apache 需要处理客户端连接的 SSL/TLS 终止时使用。
在基于 Debian/Ubuntu 的系统上使用 a2enmod 命令启用模块;在基于 CentOS/RHEL 的系统上,则取消 httpd.conf 中 LoadModule 指令的注释:
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_balancer
sudo a2enmod proxy_wstunnel
sudo a2enmod ssl
sudo systemctl restart apache2
基本 HTTP 反向代理配置
反向代理最基本的指令是 ProxyPass 和 ProxyPassReverse。配置通常放在 <VirtualHost> 块中,或直接写入 httpd.conf。
<VirtualHost *:80>
ServerName yourdomain.com
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
# 将 /app 的所有请求代理到后端服务器
ProxyPass /app http://backend-app-server:8080/app
ProxyPassReverse /app http://backend-app-server:8080/app
# 将根路径 / 的所有请求代理到另一台后端
ProxyPass / http://backend-web-server:8000/
ProxyPassReverse / http://backend-web-server:8000/
# 在 Apache 上做 SSL/TLS 终止,并以 HTTP 转发到后端
# RequestHeader set X-Forwarded-Proto "https"
</VirtualHost>
关键指令
ProxyRequests Off:这一项至关重要。它会关闭 Apache 的正向代理功能,防止服务器变成开放代理,否则将带来严重的安全风险。对于反向代理,该指令必须始终设置为Off。ProxyPreserveHost On:该指令确保客户端请求中的原始Host头被传递给后端服务器。若设为Off,Host头会被替换为后端服务器的主机名和端口。ProxyPass [path] [url]:把本地 URL 路径(path)映射到后端 URL(url)。Apache 会拦截与path匹配的请求并转发到url。- 示例:
ProxyPass /app http://backend-app-server:8080/app表示对http://yourdomain.com/app/page.html的请求会被转发到http://backend-app-server:8080/app/page.html。
- 示例:
ProxyPassReverse [path] [url]:重写后端服务器返回的 HTTP 响应中的Location、Content-Location和URI头。这样,后端生成的重定向或链接会指向对外的代理 URL,避免客户端接触到内部 URL。<Proxy *>:定义对代理本身的访问控制。Require all granted允许所有客户端使用该代理。若需要更严格的安全策略,可只放行特定的 IP 地址或网段。
mod_proxy 高级功能
负载均衡
mod_proxy_balancer 可以把进入的请求分发到多台后端服务器,从而提升可用性和可扩展性。
<VirtualHost *:80>
ServerName app.yourdomain.com
ProxyRequests Off
ProxyPreserveHost On
<Proxy balancer://mycluster>
BalancerMember http://backend1.internal:8080 route=1 loadfactor=10
BalancerMember http://backend2.internal:8080 route=2 loadfactor=10
# 可选:用 ProxySet 设置具体的负载均衡参数
ProxySet lbmethod=byrequests stickysession=JSESSIONID nofailover=Off
# 要实现会话保持,后端必须下发类似 JSESSIONID 的 cookie
</Proxy>
ProxyPass / balancer://mycluster/
ProxyPassReverse / balancer://mycluster/
<Location "/balancer-manager">
SetHandler balancer-manager
Require ip 192.168.1.0/24 # 限制只允许内部网络访问
</Location>
</VirtualHost>
