Sometimes you need to limit access of a web directory to a specific set of IP addresses. Normally this is pretty straightforward with the <Directory>, <Location>, or <LocationMatch> directives in Apache’s config file.
For instance, if I wanted to limit access to a single IP address 10.0.0.1, my config might look like this:
<LocationMatch "/protected*/"> Order Deny,Allow Deny from all Allow from 10.0.0.1 </LocationMatch>
But when your Apache server is behind Amazon’s Elastic Load Balancer, it get’s a little trickier. From Apache’s perspective, all requests are coming from the ELB’s IP address. Thankfully, Amazon includes a HTTP Header X-Forwarded-For with the IP address of the original host. This makes it possible to detect and restrict access to a directory by IP with a few little Apache config changes.
The example above with the addition of an Apache directive called SetEnvIf results in the same behavior and works both standalone or behind any load balancer that supports the X-Forwarded-For header.
SetEnvIf X-Forwarded-For 10.0.0.1 my-whitelisted-ip <LocationMatch "/protected*/"> Order Deny,Allow Deny from all Allow from env=my-whitelisted-ip Allow from 10.0.0.1 </LocationMatch>
The addition of the SetEnvIf directive tells Apache to set an environment variable called my-whitelisted-ip if the X-Forwarded-For header matches my pattern, in this case 10.0.0.1. Inside the LocationMatch directive, I’m using the ‘Allow from’ directive to only let the request through if that environment variable exists. You can add multiple SetEnvIf directives to set the same environment variable to perform more complex checks.
As a side note, ELB’s can also mess with the logging of client IP’s. You can use the X-Forwarded-For header to solve this problem as well, here’s a good blog post explaining how to accomplish that.