reverse proxy with nginx ssl passthrough - nginx

I have several ISS Webservers hosting multiple web applications on each IIS server.
The do have a public certificate on each system.
Every IIS has an unique IP.
All IIS Server are placed in the same DMZ
I have setup an nginx System in another DMZ.
My goal is, to have nginx handle all the requests to the IIS from the Internet and JUST passthrough all the SSL and certificates checking to the IIS. So as it was before nginx. I don't want to have nginx break up the certificates, or offloads them etc.
Before I try to rumble with nginx reverse proxy to get it done (since I'm not very familiar with nginx), my question would be, if this is possible?
Believe me I've googled times and times and could not find something which answers my question(s)
Or maybe I'm too dumb google correctly. I've searched even for passthrough, or reverse proxy, offloading.
So far I've gathered, nginx needs probably some extra mods. Since I have a "apt-get" Installation, I don't even know how to add them.

nevermind I found the solution:
Issue:
Several Webservers with various applications on each are running behind a FW and responding only on Port 443
The Webservers have a wildcard Certificate, they are IIS Webservers(whoooho very brave), have public IP addresses on each
It is requested, that all webserver should not be exposed to the Internet and moved to a DMZ
Since IP4 addresses are short these days, it is not possible get more IPs addresses
Nginx should only passthrough the requests. No Certificate break, decrypt, re-encrypt between webserver and reverse proxy or whatsoever.
Solution:
All websservers should be moved to a internal DMZ
A single nginx reverse proxy should handle all requests based on the webservers DNS entries and map them. This will make the public IP4 address needs obsolete
All webservers would get a private IP
A wild certificate would be just fine to handle all aliases for DNS forwarding.
Steps to be done:
1. A single nginx RP should be placed on the external-DMZ.
2. Configure nginx:
- Install nginx on a fully patched debian with apt-get install nginx. At this Point
you'll get Version 1.14 for nginx. Of course you may compile it too
If you have installed nginx by the apt-get way, it will be configured with the following modules, which you will need later: ngx_stream_ssl_preread, ngx_stream_map, and stream. Don't worry, they are already in the package. You may check with nginx -V
4. external DNS Configuration:
- all DNS request from the Internet should point the nginx.
E.g webserver1.domain.com --> nginx
webserver2.domain.com --> nginx
webserver3.domain.com --> nginx
5. Configuration nginx reverse-proxy
CD to /etc/nginx/modules-enabled
vi a filename of your choice (e.g. passtru)
Content of this file:
enter code here
stream {
map $ssl_preread_server_name $name {
webserver01.domain.com webserver01_backend;
webserver02.domain.com webserver02_backend;
}
upstream support_backend {
server 192.168.0.1:443; # or DNS Name
}
upstream intranet_backend {
server 192.168.0.2:443; # or DNS Name
}
log_format basic '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time "$upstream_addr" '
'"$upstream_bytes_sent" "$upstream_bytes_received"
"$upstream_connect_time"';
access_log /var/log/nginx/access.log basic;
error_log /var/log/nginx/error.log;
server {
listen 443;
proxy_pass $name; # Pass allrequests to the above defined variable container $name
ssl_preread on;
}
}
6. Unlink the default virtual webserver
rm /etc/nginx/sites-enabled/default
7. Redirect all http traffic to https:
create a file vi /etc/nginx/conf.d/redirect.conf
add following code
enter code here
server {
listen 80;
return 301 https://$host$request_uri;
}
test nginx -t
reload systemctl reload nginx
Open up a browser and check the /var/log/nginx/access.log while calling the webservers
Finish

Related

Setting up Jenkins with Nginx reverse proxy

I have a Jenkins environment setup, running off a EC2 instance and trying to get port 80 mapped to port 8080.
A suggestion made (and the way most of the configurations I've seen recommended) uses Nginx to do a reverse proxy.
I have installed Nginx on the server, and added to sites-available the following:
server {
listen 80;
server_name jenkins.acue.io;
location / {
include /etc/nginx/proxy_params;
proxy_pass http://localhost:8080;
proxy_read_timeout 60s;
# Fix the "It appears that your reverse proxy set up is broken" error.
# Make sure the domain name is correct
proxy_redirect http://localhost:8080 https://jenkins.acue.io;
}
}
I hit the IP address of the jenkins environment, it shows me the Ngnix welcome screen and Jenkins still loads against port 8080 not port 80.
Do I need to specific the current URL (I've not pointed the jenkins.acue.io sub-domain yet to the EC2 instance where I have specified localhost? I've tried it but no joy).
Few things to note.
You need to add jenkins.acue.io to your Host entries and point it to the instance where you are running NginX. Then use the FQDN to access Jenkins. Also there is a typo in your proxy_redirect where you have added https URL instead of http://jenkins.acue.io fix that as well. Other than that your NginX configurations look fine.
If you keep on getting the NginX welcome page even though you are accessing through the FQDN, that means your configurations are not being picked up by NginX. Try creating a new file like jenkins.conf and add it to /etc/nginx/conf.d. Then do a sudo systemctl restart nginx

NGINX + Dockerized Gunicorn - How secure & efficient is my webserver setup?

I’m working on an ios app that needs to communicate with a server. As part of that communication, the app sends a private cookie that must be transferred **securely**.
After a ton of research and frustration, I’ve successfully managed to setup my webserver in the following manner:
My entire setup is running on an AWS EC2 machine running linux.
My routes are defined with FastAPI
The webserver is deployed with GUNICORN launching multiple uvicorn workers, as recommended by the official uvicorn docs:
gunicorn -w 4 -k uvicorn.workers.UvicornWorker example:app
The webserver is launched on port 8080 using a docker container:
Dockerfile
... docker setup ...
EXPOSE 8080
CMD ["gunicorn", "-b", "0.0.0.0:8080", "-w", "2", "-k", "uvicorn.workers.UvicornWorker", "main:app"]
My webserver runs behind a NGINX reverse proxy. The proxy listens on port 80 and 443 and redirects the requests to my webserver (that sits on port 8080).
My NGINX .conf file is very minimal and looks like that:
server {
server_name example.*;
location / {
proxy_pass http://127.0.0.1:8080/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
NGINX is using certbot generated certificates to only support HTTPS communication.
The certificates were generated using python-certbot-nginx, with the following command:
sudo certbot --nginx -d example.club -d www.example.club
Finally, to ensure that no one surpasses my PROXY and sends requests directly to my webserver, I’ve configured my machine to only allow communication to port 8080 from the machine’s IP address.
Port 80 and port 443 are obviosuly open to any IP address.
Since I’m a newbie to webservers in general and webserver deployment in particular, I would like to know: how efficient and secure is this setup?
Do you have recommendation or other stuff I should implement to make sure no private data leaks out, while also being to handle requests load?
Thanks!
Without knowing the exact configuration in detail, here some things to think about. At all the setup seems about right.
I’ve configured my machine to only allow communication to port 8080 from the machine’s IP address. -> Have you really used the external IP of the machine, or are you using a localhost/127.0.0.1 value there? For proxy pass on 127.0.0.1 it is okay to only allow connections over the loopback adapter.
I don't know the ssl params you use for the nginx. There is a lot which you can configure. Try https://www.ssllabs.com/ssltest/ to see if the config is good enough. A++ or A+ is nearly impossible to reach without giving lots of restrictions for your user base. But A is definitely a good point, which you want to reach.
You might want to set up an http -> https forwarding for everything except the path certbot needs. And then set the HSTS Header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
Hope this helps a little bit. But as I said. At all, I don't the a security breach there. The entrypoints I see are your nginx, certbot and your dockerized webapp. You have to trust nginx and certbot. You might want to make sure, that you automatically install security updates for those, maybe with unattended-upgrades to not "forget" them. Same is for docker, and all the rest of the os-based software which comes from your package manager.
Greetings

Nginx load balancer SSL certs

I'm totally new to NGINX. I would like to use the free version (not nginx plus) to load balance (reverse proxy) between 3 servers and the connection must be SSL / 443.
Do i put the SSL certificate on the NGINX load balancer server or do I put 3 x SSL certs on the 3 web servers individually? I've heard mixed reviews. I'm looking for best performance.
Additional info: i'm using a wildcard SSL cert and the web other web servers are IIS with IP_Hash to keep sessions on the same web servers.
Open your configuration file again for edit.
sudo nano /etc/nginx/conf.d/load-balancer.conf
Then add the following server segment to the end of the file.
server {
listen 443 ssl;
server_name domain_name;
ssl_certificate /etc/letsencrypt/live/domain_name/cert.pem;
ssl_certificate_key /etc/letsencrypt/live/domain_name/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
location / {
proxy_pass http://backend;
}
}
Then save the file, exit the editor and restart nginx again.
sudo systemctl restart nginx
With the HTTPS-enabled you also have the option to enforce encryption to all connections to your load balancer
server {
listen 80;
server_name domain_name;
return 301 https://$server_name$request_uri;
#location / {
# proxy_pass http://backend;
#}
}
Save the file again after you have made the changes. Then restart nginx.
sudo systemctl restart nginx
This question was asked already in the StackExchange network, but I'm going to try and answer your question anyway.
The performance impact should be noticeable, but it really depends on what you're running.
One thing to consider using multiple certificates, is that once the request hits the load balancer, it stays secure inside the datacenter/network.
This is useful, in cases where you don't own the hardware and don't have physical access to the machines/datacenter. This is because there are probably multiple people running servers and applications in a shared space and you can't know for sure if someone in that network is snooping around and watching the traffic. You just can't be sure that's not going to happen.
Using only one certificate (for the load balancer) is called 'SSL Offloading' and you can and should find out more about it here:
https://security.stackexchange.com/questions/30403/should-ssl-be-terminated-at-a-load-balancer
https://security.stackexchange.com/questions/79672/in-detail-how-does-ssl-offloading-acceleration-termination-work
SSL performance implications
https://serverfault.com/questions/112547/does-using-ssl-cause-a-significant-performance-hit

Nginx reverse proxy not working to Shiny Server hosted on AWS Lightsail Instance

I am new to nginx and am trying to configure a reverse proxy to a Shiny Server (Open) that I have successfully implemented on an AWS Lightsail Instance. I am desperate at this point and would appreciate any advice. Here are the pertinent configuration arrangements.
Note that I have a purchased a custom domain from GoDaddy. Assume this is named mydomain.com.au. However, I have changed the name servers to point to Netlify as I deployed my website through the blogdown R package in Netlify.
Lightsail Instance Details
This has a Shiny Server installed and a static IP address assigned. Assume 123.45.67.89 from this point onwards. The firewall details are provided below:
Lightsail instance firewall details
I can successfully access the Shiny Server via http://123.45.67.89:3838 and associated Shiny apps I've deployed. I have a DNS Zone record added in order to link mydomain.com.au to my Shiny Server on the Lightsail instance - see details below:
Record Type: A
Subdomain: shiny.mydomain.com.au
Resolves to: 123.45.67.89 (i.e. static IP address)
Netlify details
I have a DNS record added in Netlify for mydomain.com.au which points to the Lightsail instance static IP address. Below are the details (I'm not sure whether I need a DNS record in Netlify and Lightsail though). Note this this is SSL/TLS certificate enabled and cannot be disabled (it will automatically revert to "https://" even when "http://" is specified).
Name: shiny.mydomain.com.au
TTL: 3600 seconds
Type: A
Value: 123.45.67.89
nginx details
Below are the relevant details of the /etc/nginx/sites-enabled/default file which I modified based on the instructions from this post. The $http_upgrade and $connection_upgrade is stored in the /etc/nginx/nginx.conf file. There is no SSL/TLS certificate from certbot added and I'm not sure whether this is an issue.
server {
listen [::]:80 default_server;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name shiny.mydomain.com.au;
# Reverse proxy to port 3838
location / {
proxy_pass http://localhost:3838/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 20d;
proxy_buffering off;
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
# try_files $uri $uri/ =404;
}
The nginx configuration test appears to be successful:
sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
The following firewall profiles (from sudo ufw status) are set up - Nginx HTTP, OpenSSH, 3838 and 80. nginx is active and running too with no issues according to sudo service nginx status.
What works?
http://123.45.67.89:3838/ successfully opens the Shiny Server index page.
https://shiny.mydomain.com.au:3838/ successfully opens the Shiny Server index page.
Other information?
Visiting https://shiny.mydomain.com.au:3838 will automatically attempt https://123.45.67.89:443 which ultimately fails and times out. The redirection to 123.45.67.89 appears to work but it does not forward to the 3838 port. Firefox Network monitoring indicates that the Server is nginx.
What might be happening?
At this point (and I am very new to web administration), I think this might be an issue with Netlify forcing HTTPS which cannot be redirect to the Shiny Server port (HTTP?). However, visiting https://shiny.mydomain.com.au:3838 successfully redirects to the Shiny Server index page. I just can't understand why nginx isn't successfully forwarding to the 3838 port without specifying it in the URL based on the default configuration file.
What is the problem?
Loading shiny.mydomain.com.au does not successfully load the Shiny Server index page. It will eventually time out and no page is loaded ("The connection has timed out"). Checking the network monitoring information in Firefox indicates that tries to access 123.45.67.89 but not 123.45.67.89:3838 (i.e. the Shiny Server). It doesn't appear that it is redirecting at all according to the /etc/nginx/sites-enabled/default file.
I have tried changing localhost to 127.0.0.1 to no avail. I have tried following Dean Attali's post and another recent post on setting up Shiny Server too but still no success.
Can someone please help me out on how to get nginx as a reverse proxy to work?
I'm really running out of ideas here. Thanks.

How to test nginx subdomains on localhost

I want to test nginx subdomains before uploading config to the server. Can i test it on localhost? I try
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://localhost:8080;
}
}
server {
listen 80;
server_name sub.localhost;
location / {
proxy_pass http://localhost:8080/sub;
}
}
And it does not work. Shoulld i change my hosts file in order to make it work? Also, after uploading site to the server should i change DNS records and add sub.mydomain.com?
Yes, add '127.0.0.1 sub.localhost' to your hosts file. That sub has to be resolved somehow. That should work.
Then once you're ready to go to the net, yes, add an a or cname record for the subdomain sub.
When I use proxy_pass I also include the proxy.conf from nginx.
http://wiki.nginx.org/HttpProxyModule
In Linux based OS just to edit as sudo /etc/hosts file and change 127.0.0.1 localhost to 127.0.0.1 *.localhost.
So at /etc/nginx/sites-enabled/<environment>/<your_project_name> edit server_name key as <subdomain>.localhost.
Reload nginx and networking service.
$ sudo service nginx reload
$ sudo service networking reload
And then try http://<subdomain>.localhost at url bar.
It works for me.
UPDATE
In my opinion, a better solution is creating a virtual server that only responds if subdomain doesn’t exist, at /etc/nginx/sites-enabled/development/default, as default server (remember that you can define only one server as default).
server {
listen 80 default_server;
root /var/www/html/errors/404;
server_name *.localhost *.<host-name>;
location / {
index subdomain.html;
}
}
Make sure that in nginx.conf (generally at /etc/nginx/nginx.conf) contain include /etc/nginx/sites-enabled/**/*; to this virtual server work. If not, put it and then run $ sudo service nginx reload.
In this case isn't necessary put *.localhost in /etc/hosts, but only localhost.
For your public webserver with its own domain name, you just need to add a Canonical name using a CNAME record in your DNS configuration:
CNAME * example.com.
Once this is done, set your nginx setting
server_name *.example.com example.com;
In your local setup you can keep the same configuration for nginx but unless you have a local DNS setup, you will have to edit your /etc/hosts file and add each subdomain manually. wildcards don't work in the /etc/hosts file.
127.0.0.1 abc.example.com def.example.com ghi.example.com
It is generally recommended to use .local as the namespace for your local domains.
With an Nginx configuration like shown by the OP, all that is needed is to configure the local DNS resolution. I run Linux containers on a VM with a local DHCP IP but test them on Windows 10 browsers.
The DNS configuration can be done by editing "C:\Windows\System32\drivers\etc\hosts" as Administrator.
192.168.100.50 sub.example.local
192.168.100.50 example.local
Of course, use 127.0.0.1 or other appropriate IP as needed.

Resources