From apache docs (https://httpd.apace.org/docs/2.4/mod/mod_remoteip.html) we implemented the following assignment on our server:
RemoteIPHeader X-Forwarded-For
to get a client’s IP rather than the ELB’s IP. However, we didn’t notice that the ELB also appends all other X-Forwarded-For
values to the left of that string. So this is not a secure way to get a client’s IP.
We’ve used LogFormat
with "%{X-Forwarded-For}i"
to verify the values being passed in are as documented.
192.168.0.0, 10.0.0.0
is what would come through if 192.168.0.0
were the header being passed and 10.0.0.0
were the client’s requesting machine. A standard request without the header would be:
10.0.0.0
Is there a way to extract the rightmost IP? I was thinking something like,
RemoteIPHeader ('(?:d{1,3}[.]){3}d{1,3}$', X-Forwarded-For,)[0]
but can’t find a function in apache to configure this. I could do this in PHP but then my logs will all have the wrong IPs logged.
I’ve tried:
SetEnvIf X-Forwarded-For '((?:d{1,3}[.]){3}d{1,3})$' ip_is=$1
RemoteIPHeader %{ip_is}
but this didn’t take affect.
Update:
Apache configuration runs with:
LogFormat "%{%Y-%m-%d %H:%M:%S}t %a %u %A %p %m %U %q %>s "%{User-agent}i" %T/%D "%{X-Forwarded-For}i"" w3c_extended
CustomLog /var/log/httpd/example.com/access.log w3c_extended
I currently receive either:
2021-02-27 14:29:06 10.0.21.150 - 10.0.20.222 443 GET /IPtest.php ?v=1 200 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36" 0/2822 "73.149.97.219"
or
2021-02-27 14:29:06 10.0.21.150 - 10.0.20.222 443 GET /IPtest.php ?v=1 200 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36" 0/2822 "10.0.21.150, 73.149.97.219"
I need to capture 73.149.97.219
in both scenarios.
2
Answers
I’m testing with apache 2.4 and remoteIP
You’ll also need to tell your apache what the internal IP address of your Load balancer (Reverse Proxy) is. There is no reliable easy way to determine that internal IP and it can by ‘any’ RFC1918 (private) IP address
So you’ll need to add those 3 subnets.
and then use %a for the logFormat
i’ve tested with
tested with curl
I got this problem in different context – apache was resolving hostnames from manipulated
X-Forwarded-For
header. E.g.X-Forwarded-For: mumblemuble.burpcollaborator.com, 1.1.1.1, anotherdomainapachewillresolve.com
My solution was to modify the
X-Forwarded-For
header to only include the IP address added by ELB, and discard IP addresses which ELB appended to the header.Instead of other reverse proxies, ELB appends existing
X-Forwarded-For
addresses and hostname before the client IP. For other reverse proxies you should modify regexp to discard everything after first comma.