Skip to main content

Using rpaf Apache module to preserve client IP

Suppose you have two web servers on your network, public Server A and private Server B. Maybe you want to publish some sections of your private server on internet using Apache proxy module. In this example, “users” path on www.server_a.com is redirected to www.server_b.com/users , because Server A is in the same private network as Server B is, Server A knows how to reach Server B and redirects the web requests to it. The problem here is that Server B will always have the IP of Server A in all requests (192.168.20.50).

Server A
Public IP: 85.164.26.20
Private IP: 192.168.20.50

 ProxyRequests Off
 ProxyPreserveHost On
 ProxyPass /users http://www.server_b.com/users
 ProxyPassReverse /users http://www.server_b.com/users

Server B
Private IP: 192.168.20.51

To solve this problem you can use rpaf module for Apache2. Explanation from the author:

“It changes the remote address of the client visible to other Apache modules when two conditions are satisfied. First condition is that the remote client is actually a proxy that is defined in httpd.conf. Secondly if there is an incoming X-Forwarded-For header and the proxy is in it's list of known proxies it takes the last IP from the incoming X-Forwarded-For header and changes the remote address of the client in the request structure.”

In this case rpaf translates the remote address 192.168.20.50 to real client address sent in X-Forwarded-For header.

1- Install rpaf module on Server B

# apt-get install libapache2-mod-rpaf

2- Configure your virtualhost in Server B to use rpaf module:

RPAFenable On
RPAFsethostname On
RPAFproxy_ips 192.168.20.50

3- Restart apache

# apachect restart

Now, you will see the real client IP in your apache access logs.

Apache2 mpm worker + fastcgi + php5-fpm on debian

Install required packages:

# apt-get install libapache2-mod-fastcgi apache2-mpm-worker php5-fpm

To install php5-fpm on debian squeeze you can add dotdeb repository to your sources.list

deb http://packages.dotdeb.org stable all
deb-src http://packages.dotdeb.org stable all

Then run:

# wget -O- "http://www.dotdeb.org/dotdeb.gpg" | apt-key add -
# apt-get update

Configure php5-fpm pool in /etc/php5/fpm/pool.d/, www.conf by default, but you can change the name and set a new one based on virtual host.

user = user
group = group
listen = /var/run/php5-fpm.sock
listen.owner = user
listen.group = group
pm = dynamic
pm.max_children = 150
pm.start_servers = 30
pm.min_spare_servers = 15
pm.max_spare_servers = 40
pm.max_requests = 1000

You can also set a sock file name identifying the pool name. I am using only one pool in the server, so I leave it as default.
Configure Apc in /etc/php5/fpm/conf.d/20-apc

extension=apc.so
apc.enabled=1
apc.stat=0
apc.mmap_file_mask = /tmp/apc-XXXXXX
apc.enable_cli = 0
apc.max_file_size = 2M
apc.stat_ctime = 0
apc.shm_size = 128M
apc.canonicalize=0

Restart php5-fpm with the new configuration:

/etc/init.d/php5-fpm restart

Now, configure apache to be able to pass php requests to php5-fpm server:

Enable actions module if it isn’t enabled yet

# a2enmod actions

Configure fastcgi, edit file /etc/apache2/mods-enabled/fastcgi.conf

<IfModule mod_fastcgi.c>
  AddHandler fastcgi-script .fcgi
  #FastCgiWrapper /usr/lib/apache2/suexec
  FastCgiIpcDir /var/lib/apache2/fastcgi

  Alias /php5.fcgi /var/lib/apache2/fastcgi/php5.fcgi
  FastCGIExternalServer /var/lib/apache2/fastcgi/php5.fcgi -flush -socket /var/run/php5-fpm.sock
  # application/x-httpd-php                        phtml pht php
  # application/x-httpd-php3                       php3
  # application/x-httpd-php4                       php4
  # application/x-httpd-php5                       php
  <FilesMatch ".+\.ph(p[345]?|t|tml)$">
    SetHandler application/x-httpd-php
  </FilesMatch>
  Action application/x-httpd-php /php5.fcgi
  <Directory "/var/lib/apache2/fastcgi">
    Order deny,allow
    Deny from all
    <Files "php5.fcgi">
      Order allow,deny
      Allow from all
    </Files>
  </Directory>

</IfModule>

If you have several virtualhosts, each one with diferents pools, you can especifly the FastCGIExternalServer directive in each virtualhost configuration.

Create file /var/lib/apache2/fastcgi/php5.fcgi

# touch /var/lib/apache2/fastcgi/php5.fcgi

Restart apache:

# apachectl restart

And now test if your php files are served correctly by apache.