In this post I hope to show how to configure nginx as a reverse proxy to a back-end CentOS 5 server running Apache.

When you add an nginx reverse proxy layer on top of Apache, Apache thinks that all connections originate from the server running nginx. This creates a couple annoying problems:

  • Every entry in the Apache access logs appears to come from the IP of the nginx server
  • Securing sessions by checking that a user’s IP address hasn’t changed becomes more difficult.
    • This is especially true when using open source software. OS packages usually look for the client’s IP in the REMOTE_ADDR variable.

To resolve these issues, we’ll use the Apache mod_rpaf module to populate the REMOTE_ADDR using a special HTTP header inserted by nginx. A typical request would work as follows:

  • 1.2.3.4 sends HTTP request to nginx server
  • nginx determines that it needs to proxy pass the request to a back-end Apache server (e.g. by looking at the content-type or virtual host).
  • nginx adds an HTTP header “X-Forwarded-For” with the client’s real IP
  • nginx forwards (proxy_pass) the request to back-end Apache server
  • mod_rpaf in Apache detects that the request is coming from the nginx IP, then substitutes REMOTE_ADDR with the contents of X-Forwarded-For
  • Apache handles request as normal. Applications do not need to be aware of the reverse proxy.

To install mod_rpaf on the CentOS 5 box:

wget http://stderr.net/apache/rpaf/download/mod_rpaf-0.6.tar.gz
tar zxvf mod_rpaf-0.6.tar.gz
cd mod_rpaf-0.6

# Patch Makefile so it looks for 'apxs' instead of 'apxs2' (required
# when compiling under CentOS 5):
sed -ie 's/apxs2/apxs/' Makefile

make rpaf-2.0
make install-2.0

Create /etc/httpd/conf.d/rpaf.conf:

# Path to mod_rpaf-2.0.so, relative to /etc/httpd/
LoadModule rpaf_module modules/mod_rpaf-2.0.so

RPAFenable On
RPAFsethostname On

# Define our reverse proxy IP.  Only substitute client IP in
# when we receive a request from this IP.
RPAFproxy_ips 192.168.0.1

# The header where the real client IP address is stored.
RPAFheader X-Forwarded-For

Configure nginx to reverse proxy our CNAME IP address to the back-end container. We won’t go into installing nginx here, instead I’ve included the relevant configuration section in /etc/nginx/nginx.conf. This configuration says to reverse proxy all requests to the virtual host ‘myvirtualhost.com’:

server {
listen 80;
server_name myvirtualhost.com;

location / {
proxy_pass http://192.168.0.56;
proxy_redirect default;

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

After restarting Apache & nginx, you should be able to successfully connect to your back-end Apache via the nginx reverse proxy layer. Inspecting the Apache environment will show a couple new headers, but other than that requests look the same as if clients were connecting directly without the proxy.

, , , ,