Using the Nginx Web Server as a Reverse Proxy: Multiple SSL Sites with a Single IP Address
Overview
Nginx (pronounced Engine X, or EX for short) is a Linux-based web server that now powers at least 6% of the world's web servers. It has gained popularity for its numerous features, including Server Naming Indication (SNI), which allows you to host multiple SSL websites on a single IP address. This feature saves the expense of extra IP addresses, SSL certs, and network interface cards. Another attractive quality is that the server is very fast—faster than Apache—as it doesn't create a new thread for each user request. Instead, EX synchronizes requests by using a limited amount of threads. It seems to work well even with high-volume traffic. The only downside is that if many users are downloading very large files at the same time, the server will slow considerably as new requests are being blocked until the pending requests finish.
EX has many similarities to the Apache web server, including the ability to add and remove modules. Unlike Apache, though, EX includes a powerful scripting language that includes conditional logic, making it powerful when doing advanced configuration directives that tell the web server how to behave. EX also can act as a reverse proxy for your existing network infrastructure if you aren't ready to get rid of your Apache and/or Tomcat servers. Try replacing your existing proxy with EX, and you should notice an improvement.
Installing EX
This article will show you how to install, configure, and run the EX web server using SNI and GeoIP (IP-to-location services), so that the server can create country zones in which only certain countries can access the server with a simple IF condition. The main reason for zone blocking is to prevent server spamming and denial-of-service attacks. You'll also learn how to configure the server as a reverse proxy.
How you install EX depends on the requirements of your business. Many modules can be configured for EX. In our example, the preconfiguration of EX should load several modules, including support for SNI and IP-to-location, but first we need to load some external libraries to make those modules work.
The Perl Compatible Regular Expression (PCRE) library is required for compiling EX (this example is for CentOS):
yum install pcre pcre-devel
The zlib library provides developers with compression algorithms. It's required for the use of gzip compression in various modules of Nginx.
yum install zlib zlib-devel
Next, we need to load the Maxmind IP-to-location database to support the GeoIP module. This database allows the server to map incoming requests to a location based on the request's IP number. The gz file also contains the C library needed by the module.
cd usr/local/src wget http://geolite.maxmind.com/download/geoip/api/c/GeoIP.tar.gz tar zxf GeoIP.tar.gz cd GeoIP-1.4.8 ./configure --prefix=/usr/local/geoip make make install
Once that's installed, we need to tell EX where to find the core library. If EX is unaware of the library's location, the server won't start, so this step is important. The ldconfig command creates the necessary links and cache to the most recent shared libraries found in the directories specified on the command line, in the file /etc/ld.so.conf, and in the trusted directories (/lib and /usr/lib). Edit the ld.so.conf to link the GeoIP library:
vim etc/ld.so.conf
Add the following line at the top:
/usr/local/geoip/lib/
Run the ldconfig command to link the library:
ldconfig
Now it's time to download EX:
wget http://nginx.org/download/nginx-1.3.7.tar.gz tar zxf nginx-1.3.7.tar.gz
The following modules are enabled to support SSL, SNI, GeoIP, Real-IP, and so on when preparing the installation configuration:
usr/local/src/nginx-1.3.7 ./configure --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-openssl="/usr/local/src/openssl-1.0.0i/" --with-openssl-opt="enable-tlsext" --with-http_secure_link_module --with-http_random_index_module --with-http_geoip_module --with-ld-opt="-Wl,-R,$HOME/apps/GeoIP/lib -L $HOME/apps/GeoIP/lib"
Finally, install EX with the make command.
make make install
The user and group switches tell the server to use the specified user/group when running processes. It's important to apply permissions to any necessary folders for the user with regard to getting access to external libraries.
The SSL module provides SSL services, including SNI support. The real-ip module tells the server to acquire the real IP address from the request header data.
After a successful installation, we need to configure the Nginx.conf file. Following is a sample .configuration file, complete with detailed comments. You can use this configuration to start with, as it has been tested and guaranteed to work with EX.
# Sets worker processes across CPUs (4 processors each w/ 4 cores totaling 16 cores) # Usually 2 processes per core will suffice, as most operating systems at this time only utilize 2 cores per processor. worker_processes 8; pid /usr/local/nginx/logs/nginxlocal.pid; # events module is used to define network-related directives, many of which are for performance events { # number of connections per worker process. 1024 represents 1 core. 4096 # would take advantage of up to 4 cores. The simultaneous connections to be # served could be as high as 16,384. worker_connections 4096; #scales the server to reduce spawning threads while synchronizing requests across limited available threads. use epoll; } #http block. Only one block allowed per conf. file http { #Uses the IP-to-location database downloaded from Maxmind #This module is configured to only allow traffic from the US geoip_country /usr/share/GeoIP/GeoIP.dat; map $geoip_country_code $allowed_country { default no; US yes; } #global to all server blocks #========================================================================== # Set log paths #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error_log /usr/local/nginx/logs/accesslocal.log; access_log /usr/local/nginx/logs/errorlocal.log; # Set data/file types #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; # Set proxy specifics and set variables (i.e., remote IP address) #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_max_temp_file_size 0; client_max_body_size 10m; client_body_buffer_size 128k; proxy_connect_timeout 90; proxy_send_timeout 90; proxy_read_timeout 90; proxy_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k; # Set SSL specifics #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ssl_session_timeout 5m; ssl_protocols TLSv1; #required by SNI ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; ssl on; # HTTPS server www.yourfirstdomain.com port 8080 #------------------------------------------------------------------------ server { listen 10.1.10.136:443 ssl; server_name test.example.com; #Set up your cert paths ssl_certificate_key /etc/httpd/ssl/apache/star_example_com.key; ssl_certificate /etc/httpd/ssl/apache/star_example_com.crt; #Prevent any access other than to the path specified below location / { deny all; } location /testing { if ($allowed_country = yes) { proxy_pass https://127.0.0.1:8080; } } } # HTTPS server test2.example.com port 8447 #------------------------------------------------------------------------ server { listen 10.1.10.136:443 ssl; server_name test2.example.com; ssl_certificate /etc/httpd/ssl/apache/star_example_com.crt; ssl_certificate_key /etc/httpd/ssl/apache/star_example_com.key; location / { deny all; } location /testing { if ($allowed_country = yes) { proxy_pass https://127.0.0.1:8447; } } } }
Notice that we're only using one IP address, two different domains, and the same SSL certificate for both domains. No need for multiple certs and/or domains, thus lowering costs associated with hosting.
This configuration accepts a request on the listening IP and forwards that request to an Apache server listening on the local server. The load on the Apache server has just decreased, and EX is now acting as the reverse proxy.
Running EX
If you want to alternate between running production and test configurations, this command will tell EX which configuration file to use when launching:
/usr/local/nginx/sbin/./nginx -c /usr/local/nginx/conf/nginx.conf
To reload EX, use this command:
nginx -s reload
Summary
By setting up the EX web server, you can use a single IP and one SSL certificate for multiple domains. You've also learned how EX can work in your existing network infrastructure as a reverse proxy, improving the response speed of your web pages, and now you can host multiple domains, each with different SSL certs, using a single IP address.