When working behind a proxy or load balancer, the client's original IP address is often masked. The X-Forwarded-For (XFF) header becomes crucial in such scenarios. This header contains a comma-separated list of IP addresses through which the request has passed.
# Example X-Forwarded-For header format:
X-Forwarded-For: client_ip, proxy1_ip, proxy2_ip
To properly handle the XFF header in Apache (especially when your proxy IP is in the 10.1.1.x range), you'll need to modify your configuration:
<VirtualHost *:80>
ServerName example.com
# Trust X-Forwarded-For from your proxy IPs
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 10.1.1.0/24
# Restrict access to specific IPs
<Location "/">
Require ip 192.168.1.100 # Example client IP
Require ip 10.1.1.0/24 # Your proxy IP range
</Location>
# Or use X-Forwarded-For directly in access control
<IfModule mod_setenvif.c>
SetEnvIf X-Forwarded-For "^10\.1\.1\.[0-9]+" allowed_proxy
</IfModule>
<RequireAny>
Require env allowed_proxy
Require ip 192.168.1.100
</RequireAny>
</VirtualHost>
For more robust handling, consider using Apache's mod_remoteip:
LoadModule remoteip_module modules/mod_remoteip.so
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 10.1.1.0/24
RemoteIPTrustedProxy 10.1.1.0/24
# Then use standard IP-based restrictions
<Directory "/var/www/html">
Require ip 192.168.1.100
Require ip 10.1.1.0/24
</Directory>
To properly log client IPs when using XFF:
LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined_with_xff
CustomLog logs/access_log combined_with_xff
When implementing XFF-based access control:
- Always validate the XFF header content
- Only trust XFF headers from known proxies (like your 10.1.1.x range)
- Consider rate limiting based on the original client IP
- Implement proper logging for security audits
Use curl to test your setup:
# Without proxy IP in XFF
curl -H "X-Forwarded-For: 192.168.1.100" http://example.com
# With your proxy IP in XFF
curl -H "X-Forwarded-For: 192.168.1.100, 10.1.1.5" http://example.com
Remember to restart Apache after configuration changes:
sudo systemctl restart apache2
When your Apache server sits behind a proxy (like 10.1.1.x network), the client's original IP gets masked. The X-Forwarded-For (XFF) header becomes crucial for proper access control. Here's how to handle it securely:
First, ensure mod_remoteip is enabled:
sudo a2enmod remoteip
Then configure /etc/apache2/apache2.conf or your virtual host:
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 10.1.1.0/24
For basic IP restriction using the original client IP:
<Location "/protected">
Require ip 192.168.1.0/24
</Location>
When working with multiple proxy hops:
SetEnvIf X-Forwarded-For "^10\.1\.1\.[0-9]+" trusted_proxy
<RequireAny>
Require env trusted_proxy
Require ip 192.168.1.100
</RequireAny>
Combine with mod_rewrite for complex scenarios:
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-For} ^10\.1\.1\.[0-9]+
RewriteRule ^ - [E=TRUSTED_PROXY:1]
<RequireAll>
Require expr %{REQUEST_URI} =~ m#^/api/v1/#
Require expr %{ENV:TRUSTED_PROXY} == 1
</RequireAll>
Always validate XFF headers to prevent spoofing:
# Only trust your known proxies
RemoteIPInternalProxy 10.1.1.1 10.1.1.2 10.1.1.3
# Reject malformed headers
<IfModule mod_headers.c>
RequestHeader unset X-Forwarded-For early
</IfModule>