When implementing HAProxy as a reverse proxy with SSL termination, two critical requirements often emerge:
- Preserving client IP information via X-Forwarded-For headers
- Properly signaling HTTPS usage to backend PHP applications
Here's a production-ready configuration that addresses both requirements:
frontend https-in
bind *:443 ssl crt /etc/haproxy/certs/example.com.pem
mode http
option forwardfor except 127.0.0.1
http-request set-header X-Forwarded-Proto https
http-request add-header X-Forwarded-Port 443
default_backend php_servers
backend php_servers
mode http
balance roundrobin
option httpchk HEAD /health-check HTTP/1.1\r\nHost:\ example.com
server php1 192.168.1.101:80 check
server php2 192.168.1.102:80 check
server php3 192.168.1.103:80 check
server php4 192.168.1.104:80 check
# Force backend to recognize forwarded HTTPS
http-request set-header X-Forwarded-Proto https if { ssl_fc }
http-request set-header X-Real-IP %[src]
On your Apache/PHP servers, ensure proper handling of forwarded headers:
# In your Apache virtual host
SetEnvIf X-Forwarded-Proto https HTTPS=on
# PHP application should check these values
if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
$_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
$_SERVER['HTTPS'] = 'on';
}
# Get real client IP
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$client_ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$client_ip = $_SERVER['REMOTE_ADDR'];
}
For pfSense users, navigate to:
- Services > HAProxy
- Create Frontend with SSL certificates
- Add "http-request set-header" rules in Advanced Settings
- Configure backend with health checks and proper header forwarding
- Enable SSL session caching in HAProxy for better performance
- Configure keepalive connections between HAProxy and backends
- Consider using HTTP/2 for frontend connections
If PHP still doesn't detect HTTPS:
# Additional check in PHP
if (isset($_SERVER['HTTP_X_FORWARDED_SSL']) &&
$_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') {
$_SERVER['HTTPS'] = 'on';
}
When implementing HAProxy as a reverse proxy for HTTPS traffic, we face three critical requirements:
- SSL termination at the proxy level
- Preservation of client IP addresses via X-Forwarded-For headers
- Proper SSL flag propagation to backend PHP applications
Here's a complete solution that addresses all requirements:
frontend http-in
bind *:80
bind *:443 ssl crt /etc/haproxy/certs/example.com.pem
option forwardfor except 127.0.0.1
http-request set-header X-Forwarded-Proto https if { ssl_fc }
http-request set-header X-Forwarded-Port %[dst_port]
default_backend apache_servers
backend apache_servers
balance roundrobin
option forwardfor
server server1 192.168.1.10:80 check
server server2 192.168.1.11:80 check
server server3 192.168.1.12:80 check
On your Apache servers, ensure these settings are configured:
# In Apache configuration
SetEnvIf X-Forwarded-Proto https HTTPS=on
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 192.168.1.0/24
For pfSense users, follow these additional steps:
- Install HAProxy package through Package Manager
- Upload your SSL certificate via System → Cert Manager
- Configure frontend with "SSL Offloading" enabled
- Enable "Forwarded-For Header" in advanced settings
Create a test PHP file to verify all components:
<?php
echo "Client IP: " . $_SERVER['HTTP_X_FORWARDED_FOR'] . "\n";
echo "HTTPS: " . ($_SERVER['HTTPS'] ? 'ON' : 'OFF') . "\n";
echo "Protocol: " . $_SERVER['HTTP_X_FORWARDED_PROTO'] . "\n";
?>
When using SSL termination:
- Enable SSL session caching in HAProxy:
ssl-default-server-options ssl-max-ver TLSv1.2 no-sslv3
- Consider adding
ssl-min-ver TLSv1.2
for better security - For high traffic sites, implement OCSP stapling
While nginx could serve as an alternative, HAProxy offers advantages:
- More efficient TCP-level load balancing
- Advanced health checking capabilities
- Better integration in pfSense environment
Use these HAProxy logging directives for troubleshooting:
global
log /dev/log local0 debug
frontend http-in
capture request header X-Forwarded-For len 50
capture request header X-Forwarded-Proto len 10