Register for the iXsystems Community to get an ad-free experience and exclusive discounts in our eBay Store.

HOW-TO: Set up NGINX to reverse proxy your jails w/ Certbot

ZodiacUHD

Member
Joined
Aug 28, 2015
Messages
197
Disclaimer:
-I'm making this guide simply to help other people, i just put together multiple guides found on the internet (which i'll post below). This is meant to be as easy as it gets for a newbie to get NGINX to reverse proxy using https.


-What is a reverese proxy: https://en.wikipedia.org/wiki/Reverse_proxy
-Using certbot with nginx: https://hypatiasoftware.org/2016/07/06/httpsssl-made-easy-with-certbot/
-Thank you for the guide, not only i used it, i stole the template to write this one: https://forums.freenas.org/index.php?threads/how-to-nextcloud-10-w-apache-php-and-mariadb.46111/
-Certbot instructions: https://certbot.eff.org/all-instructions/#freebsd-nginx


The Goal:

The ultimate goal is to have one domain and redirect the requests simply using "mydomain.com/cloud ; mydomain.com/couchpotato ; /sickrage; etc. "
In order to do so, we will have to get NGINX up and running, use certbot to obtain a certificate, set up nginx to use this certificate, set up nginx to redirect to the appropriate jails. Keep in mind that having a reverse proxy allow you to have some kind of "shield" before jails using simple http, and gives all those jails (in our case but those could ultimately be other servers) anonymity.

Getting Started -
General Assumptions:

  • You know how the get a domain
  • You are using FreeNAS 9.10.2-RELEASE with FreeBSD Jail Template "------"
  • Your FreeNAS is connected to the internet, and your jails are properly configured.
  • You know how to use nano.
Specifics:
My Build:
ASRock E3C224
Xeon e3-1231v3
16GB Crucial (2x8gb) ECC DDR3-1600
x6 3TB Western Digital Red


Let's Begin

Creating the Jail

Create Jail
Jails > Add Jail

  • Jail Name: nginx_reverse
  • Template: "------"
  • IPv4 Address: 192.168.1.99
  • Leave all else default


SSH to your Jail
Open bitvise/putty or whatever you're using to SSH to you Freenas machine:
  1. Let's find our Jail
    jls
  2. Select the Jail we created earlier
    jexec n. of the jail tcsh
Install the pkg we need
  1. Get it ready with everything we need
    pkg update && pkg upgrade
  2. Install nano, NGINX, git and python
    pkg install nano nginx git python
Get Certbot and get you certs
  1. Clone Certbot
    git clone https://github.com/certbot/certbot.git
  2. Now let's obtain our Certificate, Certbot will automatically install any system dependencies and create a Python Virtual Environment to manage any Python packages it requires. Remeber that nothing has to be using ports 80 and 443 during the next step and that they have to be open for our jail!
    cd certbot
    ./letsencrypt-auto --debug certonly --standalone -d example.com -d www.example.com change those to your domain and/or delete the one you're not using, for example i didn't need www.example.com , so i just deleted -d www.example.com.
Generate your own strong and unique Diffie-Hellman (DH) Key
  1. cd /usr/local/etc/ssl/
  2. openssl dhparam -out dhparams.pem 4096
Create ssl_common.conf
  1. We are going to store all our security settings in this file. I am no expert and i find the following settings to simply work. I'll be more than happy to edit the whole guide, if necessary, to adapt it to a more clean and secure way.
    cd /usr/local/etc/nginx/
    nano ssl_common.conf
  2. Simply copy and paste all the following but remember to modify the domain name!
    Code:
    # Thanks to https://cipherli.st/ for providing a great reference! Please check out their site
    # to make sure your SSL Configuration is up to date with current standards! Be aware that in this
    # example we use a slightly liberal cipherlist to allow for older browsers on older devices, Eg.
    # IE8, android 2.4, etc
    # Enable Perfect Forward Secrecy (PFS)
    ssl_prefer_server_ciphers on;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    # Disable SSLv2 and SSLv3 (BEAST and POODLE attacks)
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    # Enable our strong DH Key
    ssl_dhparam /usr/local/etc/ssl/dhparams.pem;
    # Cipher-list for PFS.
    ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
    ssl_ecdh_curve secp384r1;
    # Requires nginx >= 1.1.0
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;
    # Requires nginx >= 1.5.9
    ssl_stapling on;
    # Requires nginx >= 1.3.7
    ssl_stapling_verify on;
    # Requires nginx => 1.3.7
    resolver 8.8.8.8 4.4.4.4 valid=300s;
    resolver_timeout 5s;
    # HSTS Support
    add_header Strict-Transport-Security "max-age=63072000;includeSubdomains; preload";
    # These headers can break applications, be careful!
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    
Setup NGINX
  1. We need to enter the conf file of NGINX and set it up to use all of this.
    nano nginx.conf
  2. Modify the bit after http to look something like this ( we are going to setup the "proxy_setup.conf" after this step ). Always remember to change the domain name.
    Code:
    listen 443 ssl;
    		server_name  example.com;
    		include ssl_common.conf;
    		include proxy_setup.conf;
    
  3. Create the proxy_setup.conf
    nano proxy_setup.conf
  4. Here it is very easy for you to understand what you have to do, i'm going to post examples but those are not going to work with you. You will have to switch the bits to what are your actual Jails local IPs and what you want the proxy_pass to be.
Code:
	 location /sabnzbd {
	 proxy_pass http://192.168.192.200:8080;
	 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;
	 }

	 location /sonarr {
	 proxy_pass http://192.168.192.202:8989;
	 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;
	 }

	 location /couchpotato {
	 proxy_pass http://192.168.192.201:5050;
	 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;
	 }

	 location /headphones {
	 proxy_pass http://192.168.192.203:8181;
	 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;
	 }



Check that everything is working

  1. service nginx onestart
  2. Now everything should be up and running. Check if it is, going to example.com/sonarr. You should see https being used.
  3. service nginx onestop

  4. sysrc nginx_enable=YES

  5. service nginx start

EXTRA
Keep in mind you will have to tweak a few things in sickrage (for example) to make it work. In my case changing the webroot or the base URL did the trick just fine since NGINX was "breaking" the URLs without that set.
Another advice: when changing the proxy setup file, use the command service nginx reload, this way you will avoid downtime in case you made mistakes, since nginx won't load the new file but keep using the old (and working) one.

Renew your certificate
  1. -OPTIONAL- I don't like using vi as an editor, therefore i'm going to switch to nano for crontab as well
    setenv VISUAL /usr/local/bin/nano
  2. crontab -e
  3. Code:
    30 1 * * 1 ./certbot/letsencrypt-auto renew --pre-hook "service nginx stop" --post-hook "service nginx start"



Test SSL Labs, you should now see an A+!
 
Last edited:

Jailer

Not strong, but bad
Joined
Sep 12, 2014
Messages
4,366
Certbot is available as a package from the repository. It's not the latest version but it does work and will be easier to maintain and update. pkg install py27-certbot
 

Tony Self

Member
Joined
Jan 30, 2017
Messages
112
The Goal:

The ultimate goal is to have one domain and redirect the requests simply using "mydomain.com/cloud ; mydomain.com/couchpotato ; /sickrage; etc. "
In order to do so, we will have to get NGINX up and running, use certbot to obtain a certificate, set up nginx to use this certificate, set up nginx to redirect to the appropriate jails. Keep in mind that having a reverse proxy allow you to have some kind of "shield" before jails using simple http, and gives all those jails (in our case but those could ultimately be other servers) anonymity.

||
||
||
||

EXTRA
Keep in mind you will have to tweak a few things in sickrage (for example) to make it work. In my case changing the webroot or the base URL did the trick just fine since NGINX was "breaking" the URLs without that set.
Another advice: when changing the proxy setup file, use the command service nginx reload, this way you will avoid downtime in case you made mistakes, since nginx won't load the new file but keep using the old (and working) one.

Test SSL Labs, you should now see an A+!
Thanks for this great "How to". I found it fairly easy to follow and apart from a couple of hiccups, firstly my new domain not registering correctly to start with and a few hard carriage returns in the ssl_common.conf template, I got the essentials of nginx up and running. I can access SABNZBD and Transmission without a problem, but as you indicated above, you had to do some tweaking to get Sickrage working and I am running into similar problems. I am getting a text menu up, but if I select any options it fails. I am assuming that this is the webfoot or the Base URL issue you mention. I am tearing my hair out trying to get Sickrage to work, but I don't really know where to start. I can see that the Sickrage is using relative paths to display the graphics and call the Java Script files, but I am at a complete loss to find what the base URL is. Can you or someone else give us some pointers on how to tweak the proxy_setup.conf file for Sickrage.

Secondly, I want to be able to access the FreeNAS WebGUI remotely. I have tried putting an entry in the proxy_setup.conf file pointing to the appropriate IP address, but that does not seem to work. Is access with Nginx possible or am I just wasting my time trying.

I am wanting to be able to access various devices around my home via Nginx, like ip cameras and older NAS boxes. I presume this will be possible.

Thanks for any further assistance you can give

Tony Self
 

ZodiacUHD

Member
Joined
Aug 28, 2015
Messages
197
Thanks for this great "How to". I found it fairly easy to follow and apart from a couple of hiccups, firstly my new domain not registering correctly to start with and a few hard carriage returns in the ssl_common.conf template, I got the essentials of nginx up and running. I can access SABNZBD and Transmission without a problem, but as you indicated above, you had to do some tweaking to get Sickrage working and I am running into similar problems. I am getting a text menu up, but if I select any options it fails. I am assuming that this is the webfoot or the Base URL issue you mention. I am tearing my hair out trying to get Sickrage to work, but I don't really know where to start. I can see that the Sickrage is using relative paths to display the graphics and call the Java Script files, but I am at a complete loss to find what the base URL is. Can you or someone else give us some pointers on how to tweak the proxy_setup.conf file for Sickrage.

Secondly, I want to be able to access the FreeNAS WebGUI remotely. I have tried putting an entry in the proxy_setup.conf file pointing to the appropriate IP address, but that does not seem to work. Is access with Nginx possible or am I just wasting my time trying.

I am wanting to be able to access various devices around my home via Nginx, like ip cameras and older NAS boxes. I presume this will be possible.

Thanks for any further assistance you can give

Tony Self
Hey there Tony, thanks for the feedback.

1) In order for Sikrage to work properly you need to access the jail via SSH and open
Code:
/var/db/sickrage/config.ini
. There you will find a line called "web_root". Simply modify it to look like this:
Code:
web_root  = /sickrage
. Also, change
Code:
 handle_reverse_proxy = 0 
to
Code:
handle_reverse_proxy = 1 
.

2) I strongly reccomend you NOT to open your FreeNas GUI to the internet. the reasons are all over the forum. It should still be possible but honestly, i wouldn't know how. I'm currently facing a few problems myself in nextcloud or others setups getting "ERR_TOO_MANY_REDIRECTS".
 

Tony Self

Member
Joined
Jan 30, 2017
Messages
112
Thanks Zodiac. I had already got as far as adding the web_root entry, but not the handle_reverse_proxy. Unfortunately I was having problems accessing the forum earlier today so I hadn't seen your reply. In the meantime I had found robles "How to" for setting up OpenVPN in a Jail. I have been working on this today and have got it successfully working. The benefit is I have to have the client certificates installed on my client devices - laptop, iPad, etc, so this is more secure than the Nginx solution allowing me to securely open the FreeNAS WebGui remotely.

Still a great Nginx guide and added to my information pool.

Tony
 

Phil G

Neophyte
Joined
Mar 7, 2017
Messages
4
I am trying to get uTorrent working with NGINX and have a bit of trouble trying to get it to work. Also, Sickrage reference utorrent in an iframe and I would also like to figure out how to get this functionality working for remote users.

My attempt at getting utorrent setup in the proxy_setup.conf file is below.

Code:
location /utorrent {
	proxy_pass http://my_domain:8080/gui;
	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;
	}

I tried to find the utorrent config file to change the web root location from /gui/web/index.html to /utorrent/gui/web/index.html but cannot find it within the utorrent installation for linux mint. Any help would be greatly appreciated.

UPDATE: Nevermind ... got it to work but had to use the "/gui" directory. It seems there is no way to change to web root for Utorrent. I am pasting what worked for me.

Code:
location /gui {

	proxy_pass http://my_domain:8080;
	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;
	}
 
Last edited:

tdunks

Newbie
Joined
May 12, 2017
Messages
1
Is there a way to change it to listen on 80 and 443 and then redirect all traffic to 443(ssl)? I have been unable to figure this out (i am brand new to nginx)
 

Jailer

Not strong, but bad
Joined
Sep 12, 2014
Messages
4,366
Is there a way to change it to listen on 80 and 443 and then redirect all traffic to 443(ssl)? I have been unable to figure this out (i am brand new to nginx)
You need to add a rewrite to https.

Code:
server {
		listen	   80;
		server_name  yourdomain.com www.yourdomain.com;
		return		 301 https://yourdomain.com$request_uri;
	}
 

noobi3

Junior Member
Joined
May 2, 2014
Messages
24
I keep getting
404 Not Found
nginx


How do i troubleshoot the issue I got nginx running on the jail

I have a PFsense Router running

I opened the port 443 of the jail

I added /sonarr in the sonarr setting
 

ZodiacUHD

Member
Joined
Aug 28, 2015
Messages
197
I'm not sure what you mean: The "404" error makes me believe that sonarr itself is not set up for the redirect. Similar to the examples i gave about sickrage, you need to set up a base url in order for this to work.
 

noobi3

Junior Member
Joined
May 2, 2014
Messages
24
I'm not sure what you mean: The "404" error makes me believe that sonarr itself is not set up for the redirect. Similar to the examples i gave about sickrage, you need to set up a base url in order for this to work.
I have set up sonarr reverse proxy as shown in pic

When I browse the sonarr page my URL is : http://192.168.1.23:8989/sonarr/



My domain is running on my PFsense using DynamicDNS i use duckdns.
 
Last edited:

noobi3

Junior Member
Joined
May 2, 2014
Messages
24
I see, so if you try to go on https://yourdomain.whatever you actually see the nginx landing page, correct?
When I go to http://mydomain.whatever i get this


A little progress I went and disabled the DNS Rebound protection for PFsense and now when i go to http://mydomain.whatever I see my Pfsense Router Login page

I do not see the NGINX landing page.It seems that my portforwarded Jail for NGINX did not translate to my domain

When I go yo http://mydomain.whatever/sonarr I get this


I do not know if its my PFsense or Freenas causing the issues
 
Last edited:

ZodiacUHD

Member
Joined
Aug 28, 2015
Messages
197
Judging by what i see, i suppose it might be your router. Just try to google about it and it should show you a listing of pfsense related topics. I'm sorry i cannot help you more than this but i never had to face anything like that before.
 

delfrogo

Neophyte
Joined
Jul 17, 2015
Messages
4
Thank you ZodiacUHD, I followed almost everything with your help. I did make a few changes to improve my security according to the website https://securityheaders.io/. I went from a D to an A following another guide from here .

I added the following line to hide the version of nginx to the world:
Code:
 server_tokens off;

I also added the following to prevent some common attacks:
Code:
add_header X-Xss-Protection "1; mode=block" always;
		add_header X-Content-Type-Options "nosniff" always;
		add_header Strict-Transport-Security "max-age=2592000; includeSubdomains" always;
		add_header X-Frame-Options "SAMEORIGIN" always;
		proxy_hide_header X-Powered-By;
		add_header 'Referrer-Policy' 'no-referrer';
		add_header Content-Security-Policy "frame-ancestors EXAMPLE.COM;";



Here is an example of my config.

Code:
#user  nobody;
worker_processes  1;

# This default error log path is compiled-in to make sure configuration parsing
# errors are logged somewhere, especially during unattended boot when stderr
# isn't normally logged anywhere. This path will be touched on every nginx
# start regardless of error log location configured here. See
# https://trac.nginx.org/nginx/ticket/147 for more info.
#
#error_log  /var/log/nginx/error.log;
#

#pid		logs/nginx.pid;


events {
	worker_connections  1024;
}


http {
	include	   mime.types;
	default_type  application/octet-stream;
	server_tokens off;

	#log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
	#				  '$status $body_bytes_sent "$http_referer" '
	#				  '"$http_user_agent" "$http_x_forwarded_for"';

	#access_log  logs/access.log  main;

	sendfile		on;
	#tcp_nopush	 on;

	#keepalive_timeout  0;
	keepalive_timeout  65;

	#gzip  on;

## Default Listening ##

	server {
		listen 80 default_server;
		listen [::]:80 default_server;
		server_name EXAMPLE.COM www.EXAMPLE.COM;
		  return 301 https://$host$request_uri;
}

##EMBY Server##

	server {
		listen [::]:443 ssl;
		listen 443 ssl;
		server_name  EXAMPLE.COM;
		include ssl_common.conf;
		include proxy_setup.conf;
		#charset koi8-r;

		add_header X-Xss-Protection "1; mode=block" always;
		add_header X-Content-Type-Options "nosniff" always;
		add_header Strict-Transport-Security "max-age=2592000; includeSubdomains" always;
		add_header X-Frame-Options "SAMEORIGIN" always;
		proxy_hide_header X-Powered-By;
		add_header 'Referrer-Policy' 'no-referrer';
		add_header Content-Security-Policy "frame-ancestors EXAMPLE.COM;";

		#access_log  logs/host.access.log  main;

		location / {
			root   /usr/local/www/nginx;
			index  index.html index.htm;
		}

		#error_page  404			  /404.html;

		# redirect server error pages to the static page /50x.html
		#
		error_page   500 502 503 504  /50x.html;
		location = /50x.html {
			root   /usr/local/www/nginx-dist;
		}
	}

}









 

q_fleuren

Member
Joined
Jun 3, 2015
Messages
57
Hi there,

So i've build a proxy using this guide, however ssl labs is giving me an F rating
Main cause:
Openssl padding OpenSSL Padding Oracle vuln. (CVE-2016-2107)

Any way to fix this?
 

ZodiacUHD

Member
Joined
Aug 28, 2015
Messages
197
Hi there,

So i've build a proxy using this guide, however ssl labs is giving me an F rating
Main cause:
Openssl padding OpenSSL Padding Oracle vuln. (CVE-2016-2107)

Any way to fix this?
I don't really know how to help you, i'm sorry. I still get an A+ on ssllabs with this config...
 

q_fleuren

Member
Joined
Jun 3, 2015
Messages
57
I don't really know how to help you, i'm sorry. I still get an A+ on ssllabs with this config...
Could the proxied app be the cause?

The only changes that i made that im aware of was the /proxyapp part
as i didnt need it and nextcloud doesnt like it without modding nextcloud.
 
Top