Reverse Proxy
- Apache server IP: 192.168.10.80
- Apache listening port: 80
- CMS: wordpress, see here for the LAMP with wordpress setup.
- Nginx server IP: 210.xxx.xxx.xxx
Edit /etc/nginx/nginx.conf, and make sure below line is uncommented:
include /etc/nginx/conf.d/*.conf;
Create a configuration
sudo vi /etc/nginx/conf.d/yourdomainname.com.conf
server { listen [::]:80; listen 80; server_name www.yourdomainname.com; root /var/www/html/yourdomainname.com/public; index index.php; location / { try_files $uri @apache; } location ~ ^/\.user\.ini { deny all; } location ~* \.(svg|svgz)$ { types {} default_type image/svg+xml; } location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { allow all; log_not_found off; access_log off; } location @apache { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $host; proxy_pass http://192.168.10.80:80; } location ~[^?]*/$ { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $host; proxy_pass http://192.168.10.80:80; } location ~ \.php$ { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $host; proxy_pass http://192.168.10.80:80; } location ~/\. { deny all; access_log off; log_not_found off; } }
Note the bold line “proxy_set_header X-Forwarded-Proto $scheme; ” is for http, if you want to use Nginx as the ssl termination point, you will need to modify this line.
Now you can logon your DNS service provider, and mapping your domain name to the Nginx server.
Open your website, and check the log on the apache server, the requester should be only from the Nginx server:
sudo tail -50 /var/log/httpd/access_log
The log should be something like below:
192.168.10.1 - - [07/Aug/2020:21:57:44 +1000] "GET / HTTP/1.0" 200 18261 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.2 Safari/605.1.15"
Note the requester’s IP is your Nginx Reverse proxy.
So you can add below line in /etc/httpd/conf/httpd.conf to restrict the requester’s IP.
Allow from 192.168.10.1/32
On the Nginx check the log for this request:
sudo tail -50 /var/log/nginx/access.log
You should see the request with the real IP address.
SSL terminator
Since Nginx has the capability of acting as a load balancer, you can give it additional work as well.
Essentially, the idea of an SSL termination that the request will come to the load balancer on a secure channel but will be sent to the other web servers without SSL. This way, your web server acts faster and eventually your requests go out to the clients in a secure manner as well.
Manual configure
First remove the first two listen lines in above configuration, and add below configure:
listen 443 ssl; ssl_certificate /path/to/cert_file; ssl_certificate_key /Path/to/private_key_file; #SSL options ssl_session_cache shared:le_nginx_SSL:10m; ssl_session_timeout 1440m; ssl_session_tickets off; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers off; ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHAC HA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
Then add below block to force the https redirect:
server { if ($host = www.yourdomainname.com) { return 301 https://$host$request_uri; } if ($host = yourdomainname.com) { return 301 https://$host$request_uri; } server_name www.yourdomainname.com yourdomainname.com; listen 80; return 404; }
Change the header into correct protocol:
Find the line proxy_set_header X-Forwarded-Proto $scheme; change the $scheme into https.
proxy_set_header X-Forwarded-Proto https;
Other considerations
You may want to force redirect from non-www to www, so you only need to request for one SSL certificate. Simply add below server block, and change the yourdomainname.com.au into your domain name
server { listen 80; server_name yourdomainname.com.au; return 301 http://www.yourdomainname.com.au$request_uri; }
Automatic configure with certbot
It’s always good to know what parameters are required for SSL termination, but certbot can do the job for us:
First install certbot
sudo yum install epel-release -y sudo yum install certbot -y
Second, create a cert for nginx:
sudo certbot --nginx
Select the website you want the reverse proxy to install ssl cert for.
Then you should see the congratulations message.
If you are using wordpress and found the website could not open now, which is due to the mix of http and https, don’t panic, see below fix .
Issue with wordpress
WordPress will not work due to mixed content (HTTP and HTTPS) – you won’t be able to login.
In order to fix this you first have to add this at the very start of your wp-config.php.
define('FORCE_SSL_ADMIN', true);
if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
$_SERVER['HTTPS']='on';
Then in the end of the file add the following, replacing “website.com” with your own URL.
define('WP_HOME','https://website.com'); define('WP_SITEURL','https://website.com');
Finally you have to add the following to your NGINX-config in the site’s location block on your reverse proxy.
proxy_set_header X-Forwarded-Proto https;
Buffer and cache
To enable buffer on Nginx:
server{
…
proxy_buffering on;
#Buffer for header data
proxy_buffer_size 16k;
#Response data from backend server
proxy_buffers 8 4k;
proxy_busy_buffers_size 16k;
…
}
Enable cache:
Only two directives are needed to enable basic caching: proxy_cache_path
and proxy_cache
. The proxy_cache_path
directive sets the path and configuration of the cache, and the proxy_cache
directive activates it. Note that these two directives need to be in one configuration file.
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g
inactive=60m use_temp_path=off;
server {
# ...
location / {
proxy_cache my_cache;
proxy_pass http://192.168.10.80;
}
}
A powerful feature of NGINX content cachingis that NGINX can be configured to deliver stale content from its cache when it can’t get fresh content from the origin servers. This can happen if all the origin servers for a cached resource are down or temporarily busy. Rather than relay the error to the client, NGINX delivers the stale version of the file from its cache. This provides an extra level of fault tolerance for the servers that NGINX is proxying, and ensures uptime in the case of server failures or traffic spikes. To enable this functionality, include the proxy_cache_use_stale
directive:
location
location @apache{
….
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
….
}
Reference