SSL Passthrough with Nginx - ssl

I have setup a Nginx Ingress to proxy traffic to a Kubernetes cluster I have setup with kubeadm. This seems to be working well.
On the host (where the Master node is setup) I have a number of other services running that are being proxied by another Nginx (publicly facing).
What I want to achieve is route all the traffic to a specific domain (pointing to the cluster) from the first Nginx (facing the public) to the Nginx running in the cluster.
Internet -----> Nginx Public -----> Nginx Ingress -----> Cluster
Nginx Ingress is listening on TLS/SSL traffic.
So I want to passthrough SSL traffic to it via the public Nginx.
I attempted it with the following which didnt seem to work.
upstream cluster {
server 10.109.70.33:443 max_fails=10 fail_timeout=10s;
}
server {
listen 80;
listen [::]:80;
listen 443;
listen [::]:443;
server_name *.dev-new.test.co;
access_log /var/log/nginx/cluster-access.log;
error_log /var/log/nginx/cluster-error.log;
location / {
proxy_pass https://cluster;
}
}

You need to add
proxy_set_header Host $host;
in your proxy_pass block. This is needed so the server knows which virtual host you are trying to look into

Related

SSL Certificate Invalid on back end Node App (Nginx Reverse Proxy)

So I'm having some issues with SSL certificates.
I have a react app running on port 80.
and a node backend running on port 443.
I have a domain pointing to the IP (xx.xx.xxx.xx) which directs to the react app. I'm using nginx to proxy the requests from frontend to backend as I have both on the same server.
Here is the nginx config:
server {
listen 80 ssl;
server_name xx.xx.xxx.xx;
ssl_client_certificate /etc/letsencrypt/live/domain.com/cert.pem;
ssl_certificate /etc/letsencrypt/live/domain.com/cert.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
root /home/ubuntu/build;
index index.html;
access_log /var/log/nginx/build.access.log;
error_log /var/log/nginx/build.error.log;
location / {
try_files $uri /index.html =404;
}
}
upstream backend {
server 127.0.0.1:443;
server 127.0.0.1:443 max_fails=1 fail_timeout=30s backup;
keepalive 64;
}
server {
listen 443 ssl;
server_name xx.xx.xxx.xx;
ssl_client_certificate /etc/letsencrypt/live/domain.com/cert.pem;
ssl_certificate /etc/letsencrypt/live/domain.com/cert.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
keepalive_timeout 10;
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
proxy_set_header Connection '';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
}
}
I'm receiving the following error when a request is made to the backend:
net::ERR_CERT_COMMON_NAME_INVALID
this is because the certificate is valid for 'domain.com' and not the IP that the backend is operating on (I know you must use a fully qualified domain for the cert).
My question is what can I do differently (with nginx) that will allow my requests to be made over https on a reverse proxy?
You're using the standard ports 80 and 443 differently. These ports are the entry points to your server and are not advised to be used as ports running inside reverse proxies.
When using reverse proxies, we map other ports to either port 80 or port 443 so the can be publicly accessible via HTTP or HTTPS respectively.
If we want to access everything by HTTPS, we will need to map both react and node apps to 443 via reverse proxy, and redirect all HTTP access going to HTTPS.
So as suggested steps to fix:
1) Use different ports, say 3000 for react and 3001 for node.
2) Configure your server block listening to port 80 to redirect to https like return 301 https://<yourdomainhere.com>
3) Remove ssl lines in your port 80 server block. Only use them inside server blocks listening to port 443
4) Modify your upstream {} block to use port 3001 for node app. Retain the use of proxy_pass http://backend;, it's fine as it is.
5) Add a new location block with proxy_pass http://localhost:3000; inside the server block that listens to port 443. You will now have two location blocks, one for react and one for node.
6) Define your server_name per block with yourdomainhere.com since IP addresses are generally not allowed to be issued with SSL certificates. I suggest using a different server block to redirect the IP address to your domain with HTTPS prefix
7) check for errors, then restart nginx.

How to make docker application use port 80 (http) instead of 443 (https)

I recently installed this web application on my Ubuntu server which runs Apache (SSL disabled).
It doesn't matter how much i try i can't get the application to use http. tried the -p flag. Then it exposes port 443 and binds something else. I hate browser warnings about SSL. I just want to use http with port 8080.
The application use nginx which only listens to 443. I want my application URL to look like http://localhost:8080 This application use Google OAuth for logins. I'm assuming it will work on http.
How to get it to work in http?
You must edit nginx.conf in order to use plain http (nginx will never speak http on a https port, only for some errors)
Change:
listen 443;
server_name localhost;
access_log /dev/stdout;
error_log /dev/stderr;
ssl on;
ssl_certificate /src/openseedbox/conf/host.cert;
ssl_certificate_key /src/openseedbox/conf/host.key;
To:
listen 8080;
server_name localhost;
access_log /dev/stdout;
error_log /dev/stderr;
Then after docker build, run with:
docker run -p 8080:8080 .......
Alternatively you can set your Apache as an HTTP virtual host that reverse-proxy to the secure HTTPS nginx. But I think it is easier to modify nginx config.
Approach #2
You can add another nginx container to act as reverse proxy, not sure if the application behind will break, but it acts as http "plainer":
docker-compose.yml
# Add this:
plain_nginx:
image: nginx
volumes:
- ./plain_nginx.conf:/etc/nginx/conf.d/default.conf
ports:
- 8080:80
links:
- openseedbox
plain_nginx.conf
server {
listen 80;
server_name _;
access_log /dev/stdout;
error_log /dev/stderr;
location / {
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_set_header X-Forwarded-Ssl on;
proxy_pass https://openseedbox;
}
}
Then do from ./docker/ directory in that repo:
docker-compose up
Then you have http://localhost:8080 acting as reverse proxy of the SSL stuff

How to point example.com/directory to another EC2 instance with SSL?

I have all my website files - example.com - on my EC2 server (Ubuntu and Apache) with SSL on EC2 instance 1. I want example.com/blog to go to another EC2 instance - EC2 instance 2. How can I do that with SSL?
I'm using Ubuntu and Apache and Route 53. thanks!
One easy way to do this is with CloudFront, described in this answer at Server Fault, where you can use path patterns to determine which URLs will be handed off to which server.
Another is an Application Load Balancer (ELB/2.0), which allows the instance to be selected based on path rules.
Both of these solutions support free SSL certificates from Amazon Certificate Manager.
Or, you can use ProxyPass in the Apache config on the main example.com web server to relay all requests matching specific paths oer to a different instance.
You cannot accomplish this with Route 53 alone, because DNS does not work at the path level. This is not a limitation in Route 53, it's a fundamental part of how DNS works.
You quickly and easily achieve this by using nginx reverse proxy. Your ssl will still be managed and offloaded on the ELB level. That is listener 443 =>> 80
1) install nginx
yum install nginx
2) add to nginx config
upstream server1 {
server 127.0.0.1:8080;
}
upstream server2 {
server server2_IP_address_here:8080;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://server1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
}
location /blog {
proxy_pass http://server1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
}
}

Configure proxy_pass for intermittent service

I'm using Nginx within a Doccker container to host my application
I'm trying to configure Nginx to proxy traffic to the /.well-known/ directory to another container that handles the letsencrypt process to setup & renew SSL certificates, but I don't need that container to be running all the time, only when attempting to renew the certificates.
My idea was to use proxy_pass for the directory specific traffic, through to the leysencrypt container, but as it's not always running, the Nginx process exits complaining that the upstream is not available.
Is there a way to configure Nginx not to check the status of the upstream for proxy_pass setting?
Here's the current config, if it's useful…
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
server_name domain.com;
root /var/www/html/web;
location / {
return 301 https://$host$request_uri;
}
location ^~ /.well-known/ {
proxy_pass http://letsencrypt/.well-known/;
}
}
I guess I could use an in app forwarding of files, but this feels clunky. I'd rather configure it within Nginx.
location ^~ /.well-known/ {
resolver 127.0.0.1;
set $upstream letsencrypt;
proxy_pass http://$upstream/.well-known/; # use variables to make nginx startable
}

NGINX subdomain and proxy_pass for Mumble

I currently have a NGINX configuration with many subdomains. I started a mumble-server on port 27845, it works if I try to access it on a Mumble client with <ip_adress>:27845.
I tried to use NGINX to provide a subdomain mumble.example.com on port 80, which use proxy_pass http://localhost:27845. But when I try to connect to mumble.example.com on my Mumble client, it says that :
This server is using an older encryption standard, and is no longer supported by modern versions of Mumble.
How can I use a valid SSL configuration for NGINX on the port 80 ? I can use solely ports 80 and 443, and 443 is used for OpenVPN.
Subdomain conf NGINX :
server {
server_name mumble.example.com;
ssl on;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
location / {
proxy_pass http://localhost:27845;
}
}
Nginx is an HTTP proxy, but mumble protocol is based on TCP/UDP, so I don't think Nginx can proxy for murmur service.