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.