Tuesday, April 10, 2012

nginx: Setup SSL Reverse Proxy (Load Balanced SSL Proxy)




Areverse proxy is a proxy server that is installed in a server network. Typically, reverse proxies are used in front of Web servers such as Apache, IIS, and Lighttpd. How do I setup nginx web server as SSL reverse proxy?

When you've multiple backend web servers, encryption / SSL acceleration can be done by a reverse proxy. Nginx can act as SSL acceleration software. It provided the following benefits:
  • Easy of use : Nginx is easy to setup and upgrade.
  • Security : Nginx provide an additional layer of defense as Apache is behind the proxy. It can protect against common web-based attacks too.
  • Load Distribution : nginx use very little memory and can distribute the load to several Apache servers. It can even rewrite urls on fly.
  • Caching : Nginx act as a reverse proxy which offload the Web servers by caching static content, such as images, css, js, static html pages and much more.
  • Compression : Nginx can optimize and compress the content to speed up the load time.
  • Our Sample Setup

    Internet--
    |
    ============= |---- apache1 (192.168.1.15)
    | ISP Router| |
    ============= |---- apache2 (192.168.1.16)
    | |
    | |---- db1 (192.168.1.17)
    | |eth0 -> 192.168.1.11 ----------/
    |-lb0==| /
    | |eth1 -> 202.54.1.1:443---/
    |
    | |eth0 -> 192.168.1.10 ----------\
    |-lb1==| / |---- apache1 (192.168.1.15)
    |eth1 -> 202.54.1.1:443---/ |
    |---- apache2 (192.168.1.16)
    |
    |---- db1 (192.168.1.17)
    • lb0 - Linux box directly connected to the Internet via eth1. This is master SSL load balancer.
    • lb1 - Linux box directly connected to the Internet via eth1. This is backup SSL load balancer. This will become active if master networking failed.
    • 202.54.1.1 A virtual IP address that moves between lb0 and lb1. It is managed by keepalived.
    • nginx - It is installed on lb0 and lb1.
    • SSL Certificate - You need to install ssl certificates on lb0 and lb1.
    For demonstration purpose I'm going to use Self-signed SSL certificate, but you can use real SSL certificate signed by CAs.
    +------+ +-------------+        +-------------------+
    |Client| <---> |SSL-Nginx:443| <----> |Apache-HTTP_mode:80|
    +------+ +-------------+ +-------------------+
    • You've the SSL connection between client and Nginx.
    • Then Nginx act as proxy server and makes unencrypted connection to Apache at port 80.
    • Nginx can cache all static file and other files.

    Generating Self-signed Certificate

    First, create required directories:
    # cd /usr/local/nginx/conf
    # mkdir ssl
    # cd ssl

    To create a private key, enter:
    # openssl genrsa -des3 -out nixcraft.in.key 1024
    Sample outputs:
    Fig.01: OpenSSL - Create a Private Key
    Fig.01: OpenSSL - Create a Private Key

    To create a CSR (Certificate Signing Request):
    # openssl req -new -key nixcraft.in.key -out nixcraft.in.csr
    Sample outputs:
    Fig.02: OpenSSL - Create a CSR (Certificate Signing Request)
    Fig.02: OpenSSL - Create a CSR (Certificate Signing Request)

    Please enter your domain name that you want to associate with the certificate. For example, for the Command Name I entered nixcraft.in as I'm going to use https://nixcraft.in/.

    How Do I Remove The Passphrase? (Optional)

    You can remove the passphrase so nginx can start on boot without entering the passphrase. Type the following commands
    # cp nixcraft.in.key nixcraft.in.key.bak
    # openssl rsa -in nixcraft.in.key.bak -out nixcraft.in.key

    Finally, you should see three files as follows (note I've created all files as vivek user and than moved lb0 and lb1 server /usr/local/ngnix/conf/ssl/ directory):
    # ls -l
    Sample outputs:
    Fig.03: All the files in ssl directory
    Fig.03: All the files in ssl directory

    # openssl x509 -req -days 365 -in nixcraft.in.csr -signkey nixcraft.in.key -out nixcraft.in.crt
    Sample outputs:
    Fig.04: Generating The Actual Self-signed  SSL Certificate
    Fig.04: Generating The Actual Self-signed SSL Certificate

    How Do I Copy SSL Certificates Files To lb1?

    You need to copy those files to lb1, enter:
    # ssh root@lb1 mkdir /usr/local/ngnix/conf/ssl
    # rsync -av /usr/local/ngnix/conf/ssl/* root@lb1:/usr/local/ngnix/conf/ssl/

    Configure Nginx As SSL Reverse Proxy (lb0 and lb1)

    Edit nginx.conf, enter (you need to edit files on both lb0 and lb1):
    # vi /usr/local/ngnix/conf/nginx.conf
    Edit / append as follows:
     
    server {
    ### server port and name ###
    listen 443 ssl;
    server_name nixcraft.in;
     
    ### SSL log files ###
    access_log logs/ssl-access.log;
    error_log logs/ssl-error.log;
     
    ### SSL cert files ###
    ssl_certificate ssl/nixcraft.in.crt;
    ssl_certificate_key ssl/nixcraft.in.key;
    ### Add SSL specific settings here ###
    keepalive_timeout 60;
     
    ### Limiting Ciphers ########################
    # Uncomment as per your setup
    #ssl_ciphers HIGH:!ADH;
    #ssl_perfer_server_ciphers on;
    #ssl_protocols SSLv3;
    ##############################################
    ### We want full access to SSL via backend ###
    location / {
    proxy_pass http://nixcraft;
    ### force timeouts if one of backend is died ##
    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
     
    ### Set headers ####
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     
    ### Most PHP, Python, Rails, Java App can use this header ###
    proxy_set_header X-Forwarded-Proto https;
     
    ### By default we don't want to redirect it ####
    proxy_redirect off;
    }
     
    Save and close the file. Reload nginx:
    # /usr/local/nginx/sbin/nginx -t
    # /usr/local/nginx/sbin/nginx -s reload

    Verify port is opened:
    # netstat -tulpn | grep :443

    How Do I Test And Debug SSL Certificates From The Shell Prompt?

    Use the openssl command as follows:
    $ openssl s_client -connect nixcraft.in:443

    How Do I Cache Common Files?

    Edit nginx.conf and add as follows to cache common files:
    location ~* \.(jpg|png|gif|jpeg|css|js|mp3|wav|swf|mov|doc|pdf|xls|ppt|docx|pptx|xlsx)$ {
    proxy_buffering on;
    proxy_cache_valid 200 120m;
    expires 864000;
    }
    Save and close the file. Reload nginx:
    # nginx -s reload

    No comments:

    Post a Comment