Nginx changes url to backend url - nginx

i have 2 backend servers listening on 80 and 443 ports:
a.example.com
b.example.com
when i get http://a.example.com at 80 port, backend internal nginx redirect it to 443 port: https://a.example.com, but when i get https port it is not redirect it, opening normally. I have not permissions to change backend nginx configurations.
So, and i have 1 load balancer nginx server, witch route requests to upstreams (backends):
upstream backends {
server 172.20.1.2:443; #a.example.com
server 172.20.2.2:443; #b.example.com
}
server {
listen 80;
server_name a.example.com;
location / {
proxy_pass https://backends;
proxy_set_header HOST a.example.com;
}
}
when i get response from second backend (b.example.com) my URL in browser is changes to https://b.example.com, but i requested https://a.example.com
Q: How i can get always https://a.example.com url from both backends? For example, when a.example.com backend not responding, lb request to second backend (b.example.com), but response url must be a.example.com
Thx!

for routing of https(443) url you need to listen on 443 in nginx also. Eg.
server {
listen 443 ssl;
server_name a.example.com;
ssl_certificate a.example.com.crt;
ssl_certificate_key a.example.com.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass https://backends;
proxy_set_header HOST a.example.com;
}
}
and for dynamic routing to any upstreams try this :
upstream backends {
least_conn;
server 172.20.1.2:443; #a.example.com
server 172.20.2.2:443; #b.example.com
}
Hope this will works for you.
Helpful Links :-
https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/

Related

Nginx Flask application

I've got a flask application, and trying to configure nginx for the app.
For now only '/' page is available, another pages got 500 server error.
I'm newly in nginx, could you tell me how to fix?
I'd recommend a reverse proxy configuration for something like this.
You Flask application will listen on localhost on port 8888 (for example)
And then Nginx would pass requests to that port internally
Below is a basic config for passing inbound http (port 80) requests to your flask application listening internally on port 8888
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:8888;
}
}
Serving the flask app is another question. uWSGI and Gunicorn are two great wsgi servers that flask will work great with.
EDIT: adding ssl config. (Change the paths to meet your needs)
server {
listen 443 ssl;
server_name www.example.com example.com;
ssl_certificate /etc/letsencrypt/live/example.com/cert.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://127.0.0.1:8888;
}
}

NGINX Incorrectly Forwarding Requests to Default Location

I have a React web application that I'm trying to deploy on an AWS EC2 instance and I'm using NGINX. I am trying to set it up so that all http requests get redirected to https. Right now it does appear to be redirecting all http requests to https, but NGINX is forwarding the request to the default path /usr/share/nginx/html/ instead of to the web application that I have running on localhost. I have read dozens of articles and have been trying to figure this out for days. Pointers would be much appreciated. Thanks in advance.
Here is my NGINX server configuration at /etc/nginx/sites-available/default:
server {
listen 80;
if ($http_x_forwarded_proto = "http") {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2 default_server;
listen 443 ssl http2 default_server;
ssl on;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1h;
location / {
proxy_pass http://127.0.0.1:3839;
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-Proto https;
}
}
Also, the application is running and accessible at the port specified in my location block. I can reach it on the machine with curl 127.0.0.1:3839 with no problems. I am able to see in /var/log/nginx/error.log that nginx is attempting to serve requests out of the /usr/share/nginx/html/ directory which is how I figured out that is the issue. I just have no idea why it's sending requests there instead of to the port on localhost that I specified in my location block. If I go to the root url for my application I get the "Welcome to NGINX" page. If I go to any subpath under my root url like example.com/login, then I get a 404 and error.log shows that it couldn't find resource /usr/share/nginx/html/login for example. Thanks :)
Update:
Inside of the listen 80 server block I added
location / {
proxy_pass http://127.0.0.1:3839;
}
and now it seems to be working correctly, but I have no idea why I would need to define a location block in the listen 80 server definition if requests in that block are just being redirected to be caught by the other server definition listening on 443. Any idea why this is working now?
I figured out the reason that location block in the http server definition worked. In AWS I accidentally had my load balancer forwarding all requests to port 80 on the EC2 instance. So even though my http server definition was redirecting to the https version of the site, those https requests were still ending up being handled by that same http server definition and since it didn't have a location block at all previously, that was causing it to fail. In the end, I removed the location block from the http server definition and then correctly updated my load balancer to forward https requests to port 443 on the EC2 instance and now everything works as expected.

NiFi Auth with Nginx reverse proxy

Is it possible to have NiFi with user authentication but with SSL termination on NGINX. I have NGINX running on port 443 and a proxy_pass passing to nifi at port 8080. I played around with these headers:
X-ProxyScheme - the scheme to use to connect to the proxy
X-ProxyHost - the host of the proxy
X-ProxyPort - the port the proxy is listening on
X-ProxyContextPath - the path configured to map to the NiFi instance
But it seems impossible to get NiFi to recognise it's on https connection behind the proxy. I updated my auth configuration however NiFi still throws an error:
IllegalStateException: User authentication/authorization is only supported when running over HTTPS.. Returning Conflict response.
java.lang.IllegalStateException: User authentication/authorization is only supported when running over HTTPS
Basically https to nginx than to http port for nifi.
Am not familiar with NiFi, but on RHEL with nginx the below gives me a reverse proxy with a HTTPS connection terminated in nginx and an onward HTTP connection with a /abc_end_point. Perhaps you can use this as a template?
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name _;
root /usr/share/nginx/html;
ssl_certificate "/etc/pki/tls/certs/abc.com.crt";
ssl_certificate_key "/etc/pki/tls/private/abc.com.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers PROFILE=SYSTEM;
ssl_prefer_server_ciphers on;
proxy_connect_timeout 7d;
proxy_send_timeout 7d;
proxy_read_timeout 7d;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
}
location /abc_end_point {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://localhost:9090/abc_end_point;
}
}
You are trying to setup Nifi with SSL offloading on the reverse proxy (nginx) - this kind of setup is not supported.
See: http://apache-nifi-users-list.2361937.n4.nabble.com/Nifi-and-SSL-offloading-td7790.html#a7799
I recommended to use TLS (HTTPS) also between reverse proxy and Nifi.

Configure nginx with support for multi subdomain and upstream

I have been trying to setup nginx as a proxy wherein request is routed to upstream based on subdomain. I hope example makes it more clear
upstream ubuntu {
server www.ubuntu.com:443;
}
upstream google {
server www.google.com:443;
}
server {
listen 443 ssl ;
ssl_certificate /etc/ssl/certs/client-certs/server.crt;
ssl_certificate_key /etc/ssl/certs/client-certs/server.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1.2;
resolver 127.0.0.1 ipv6=off;
# Make site accessible from http://localhost/
server_name ~^(.*)\.test\.com$;
location / {
proxy_pass https://$1;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
so if i request https://google.test.com it should go to https://www.google.com
With this current setup nginx returns me 404 for any of the site that i query. Though i can see that request goes to my queried upstream site(in this case google.com).
Not getting if am missing anything.

http and https redirect on nginx with port 80 closed

I have a project and use nginx to reverse proxy the request on the respectively port without having the port open. I also use Lets encrypt for ssl certification and everything works fine.
What I wanted to do was, to close port 80 and leave 443 open. I thought that ,
one more port close = a bit more security.
BUT, now the http to https redirect doesn't work (obviously I guess). Now the link only works if I type the prefix "https://" in front.
So I have two questions,
1) Is there a way to redirect the link to https without opening port 80?
2) How safe can we assume it is to leave port 80 open in order to make the redirection work, if the only app running is this one and only ports 443 and 22 are open?
my configuration file goes like this:
server {
listen 80;
server_name domain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name domain.com;
add_header Strict-Transport-Security "max-age=31536000";
ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
if ($scheme != "https") {
return 301 https://$host$request_uri;
}
location / {
proxy_pass http://127.0.0.1:PORT;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
No you can't forward trafffic from one port when it's closed on your server itself.
If possible and you have advanced network management you might be able to redirect traffic from 80 to 443 before it reaches your server.
For instance in Digital Ocean you have the ability under networks to add a loadbalancer and setup a redirect from port 80 to 443. That way you can leave port 80 closed on your server.

Resources