Exposing visitor IP to apache through varnish

In a previous post, i posted how you can put varnish on a virtual machine to cache content for your web server, But there was one small thing that we did not deal with, The IP address in the logs and that the website can see is simply that of the varnish server, not the visitor’s IP, and if you write PHP like me, I use the IP in everything, from securing logins to limiting page views to limiting comments. So, here is how we can work around this problem

First, the mission is as follows, Varnish needs to append something in the request header, that apache needs to consider the Visitor’s IP

To make apache do that, there is already a module (mod-remoteip) to do this

1- Tool to check the IP of the visitor

Create a PHP script to find out if what we are doing actually worked.

<?php
print "Your IP is: {$_SERVER['REMOTE_ADDR']} <br />\n\n";
$headers = apache_request_headers();
foreach($headers as $xheader => $xvalue)
{
print "$xheader : $xvalue <br />\n"; }
?>

and upload it to the website, when accessing this from the internet, you should see the IP as the IP of the varnish server, not your IP (Like it should)

1- Playing with cpanel

First, we must download mod_remoteip from the cpanel website (See here)

Once downloaded, we will upload it to the cpanel server at

/var/cpanel/easy/apache/custom_opt_mods/

Once done, we will now extract it as we would extract any tar.gz file

cd /var/cpanel/easy/apache/custom_opt_mods
tar -C /var/cpanel/easy/apache/custom_opt_mods -xvf custom_opt_mod-remoteip.tgz

Now, this mod should appear in easy apache when rebuilding apache, so go ahead, visit

Home ┬╗Software ┬╗EasyApache 3

and on the Exhaustive Options List you should be able to see mod_remoteip, be sure to check it.

Now, before coming to configure it, We need to inform Varnish to send us those headers. So add this at the very beginning of the Varnish sub vcl_recv section

NOTE: It seems that for the latest varnish (VCL 4), you no longer need this, if you add this, you will get the header as ( X-Forwarded-For : xxx.105.60.194, xxx.105.60.194) meaning the same IP twice

if (req.restarts == 0) {
  if (req.http.X-Forwarded-For) {
    set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
  } else {
    set req.http.X-Forwarded-For = client.ip;
  }
}

Now, we need to tell apache, what the extra header’s name is (X-Forwarded-For) and what servers this header should be honored for (the varnish server IPs, currently displaying in the script we wrote right after Your IP is:) So start by editing

/usr/local/apache/conf/includes/pre_virtualhost_global.conf

And add this, the IP here is the varnish server IP

<IfModule mod_remoteip.c>
   RemoteIPHeader X-Forwarded-For
   RemoteIPInternalProxy xxx.172.13.208
</IfModule>

Or, Probably the more suitable

/usr/local/apache/conf/includes/pre_virtualhost_global.conf

And add this, the IP here is the varnish server IP

<IfModule mod_remoteip.c>
   RemoteIPHeader X-Forwarded-For
   RemoteIPTrustedProxy xxx.172.13.0/24
   RemoteIPTrustedProxy xxx.172.14.0/24
   RemoteIPTrustedProxy xxx.172.19.0/24
</IfModule>

Now, visit Home >> Restart Services on your cpanel server, and restart apache

There you have it, refresh that PHP script, and your IP address should appear.

Now, the apache logs will still log the Varnish server IP, to fix that, you need to modify the log section in your apache config, changing %h with %a, like so

#LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined