Nginx upstream with http & https - http

I have some problem about nginx with http and https bypass, In upstream block
upstream block:
upstream bypass{
server 192.168.99.1:80; #http
server 192.168.99.2:443 backup; #https
}
When http 80 have a problem (server down, etc), I want to redirect to https 443,
This block does not work for me.
location block:
location / {
proxy_pass https://bypass;
proxy_redirect off;
}
How can I resolve this?

This works well: Create server config section for each backend on different port and forward to both ports internally without ssl.
In this example, you can see how the first server acts as main server with cached content (available via https) and if cache content is not available, use the second server (via http).
(using nginx 1.19.6, just for reference)
upstream backends {
server 127.0.0.1:8082;
server 127.0.0.1:8081 backup;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
# ssl certs etc here
location / {
proxy_pass http://backends;
proxy_next_upstream error timeout http_404 http_403;
}
access_log /var/log/nginx/access.log upstreamlog;
}
server {
listen 8081;
location / {
add_header X-Cache MISS;
proxy_pass http://server1;
proxy_set_header Host server1;
}
}
server {
listen 8082;
location / {
add_header X-Cache HIT;
proxy_pass https://server2;
proxy_set_header Host server2;
}
}

Taking a shot in the dark. Assuming you were having issues mixing HTTP and HTTPS in the upstream, you could try this in the location block:
location {
try_files #bypass-http #bypass-https =404;
location #bypass-http {
proxy_pass http://bypass;
proxy_redirect off;
}
location #bypass-https {
proxy_pass https://bypass;
proxy_redirect off;
}
}
And if that didn't work, split the bypass upstream block into bypass1 and bypass2 and reference them accordingly in their corresponding location blocks:
upstream bypass1{
server 192.168.99.1:80; #http
}
upstream bypass2{
server 192.168.99.2:443; #https
}
location {
try_files #bypass-http #bypass-https =404;
location #bypass-http {
proxy_pass http://bypass1;
proxy_redirect off;
}
location #bypass-https {
proxy_pass https://bypass2;
proxy_redirect off;
}
}
A third option would be reference them both on port 80, and ensure the second upstream server redirects HTTP requests to HTTPS.

Related

NGINX as reverse proxy for http and ssh

I'm trying to set up NGINX as a reverse proxy for HTTP and SSL.
Here is a configuration in /etc/nginx/conf.d/default.conf:
upstream sample-client {
server sample-client:3006;
}
upstream sample-server {
server sample-server:3000;
}
upstream ssh {
server sample-server:22;
}
server {
listen 80;
location / {
proxy_pass http://sample-client;
}
location /api {
rewrite /api/(.*) /$1 break;
proxy_pass http://sample-server;
client_max_body_size 100M;
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_send_timeout 300;
}
error_page 405 =200 #405;
location #405 {
root /usr/share/nginx/html;
proxy_pass http://sample-client;
}
}
server {
listen 22;
proxy_pass ssh;
}
But it throws the next error:
nginx: [emerg] "proxy_pass" directive is not allowed here in /etc/nginx/conf.d/default.conf:60
What's going wrong?
proxy_pass directive should be inside location block
described in https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/
To pass a request to an HTTP proxied server, the
proxy_pass directive is specified inside a
location .
this means that the second server location must include a location block
probably similar to
location / {
proxy_pass ssh;
}

Nginx proxy pass directive: Invalid port in upstream error

I am doing load balancing with Nginx. Here is my config
upstream web_backend {
least_conn;
server localhost:8001 max_fails=3 fail_timeout=60s;
server localhost:8002 max_fails=3 fail_timeout=60s;
}
server {
listen 8545;
server_name _;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://web_backend;
}
}
server {
listen 8001;
server_name localhost;
location / {
proxy_pass https://some_other_url/v3/cxnmcdinwrtyf93vcwdiyfx8q6xqwxv9qg7c93fgcb;
}
}
server {
listen 8002;
server_name localhost;
location / {
proxy_pass 'https://chipdunk-dude:gorgeous-serpents-clubbed-orphans#nd-657-555-555-777.dogify.com';
}
}
as you can see the url at port 8002 is weird (dont even know what this kind of urls are called)
because it has ":" in the url, Nginx gives me this error
nginx: [emerg] invalid port in upstream "chipdunk-dude:gorgeous-serpents-clubbed-orphans#nd-657-555-555-777.dogify.com" in /etc/nginx/sites-enabled/default:60
The url at port 8001 works fine.
Everything before the # is userinfo which should be encoded by the browser and included as a separate request header according to RFC 7617.
Nginx is not a browser and cannot do it for you.
You could probably convert that into Base64 and use a proxy_set_header to set the Authorization header.
For example:
proxy_set_header Authorization "Basic Y2hpcGR1bmstZHVkZTpnb3JnZW91cy1zZXJwZW50cy1jbHViYmVkLW9ycGhhbnM=";
proxy_pass https://nd-657...;

why nginx proxy_pass upstream would not work but proxy_pass https url works

1.conf
server {
listen 7070;
server_name localhost;
location / {
proxy_redirect off;
proxy_pass https://baidu;
}
}
upstream baidu {
server www.baidu.com;
}
2.conf
server {
listen 7070;
server_name localhost;
location / {
proxy_redirect off;
proxy_pass https://www.baidu.com;
}
}
why 2.conf works, but 1.conf can't proxy pass to https://baidu.com ?
it gets 502 Bad Gateway errors
If you are using SSL, you have to add port 443 to your server in your upstream directive:
https://docs.nginx.com/nginx/admin-guide/security-controls/securing-http-traffic-upstream/
server {
listen 7070;
server_name localhost;
location / {
proxy_redirect off;
proxy_pass https://baidu;
}
}
upstream baidu {
server www.baidu.com:443;
}

Two Play deployments servers on the one physical server

I want to have two Play Framework deployments on the same server and configure nginx to redirect the locations accordingly.
I have this configuration:
server {
listen 80;
server_name localhost;
client_max_body_size 20M;
location /site2 {
proxy_pass http://localhost:8000/;
}
location / {
proxy_pass http://localhost:9000/;
}
}
But it does not work.
What I want is:
When I use: http://ip/ or http://ip/something the Play deployment at port 9000 should respond.
When I use: http://ip/site2/ or http://ip/site2/something the Play deployment at port 8000 should respond.
First, please check that you have access to each app directly:
ip:8000
ip:9000
Next please add proxy_redirect directive:
server {
listen 80;
server_name localhost;
location /site2 {
proxy_pass http://localhost:8000/;
proxy_redirect http://localhost/site2/ http://localhost:8000/;
}
location / {
proxy_pass http://localhost:9000/;
proxy_redirect http://localhost/ http://localhost:9000/;
}
}

Nginx server name issue

In my Nginx configuration, I would like to keep one service to be accessible with http, while all the others should be accessed through https, and forced to ssl when trying to connect with http. This is my config:
server{
server_name localhost;
listen 80;
proxy_http_version 1.1;
location /services/ {
proxy_pass http://localhost:47440/;
}
listen / {
rewrite ^ https://$server_name$request_uri? permanent;
}
server{
server_name localhost_ssl;
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/mycert.crt;
ssl_certificate_key /etc/nginx/ssl/mycert.key;
proxy_http_version 1.1;
location /db/ {
proxy_pass http://localhost_ssl:8084/;
}
}
My problem is that when trying to reload I get this error:
host not found in upstream "localhost_ssl" in /etc/nginx/nginx.conf:46
Any idea of why this happens?
It seems your DNS resolver is failing for some reason.
Try adding:
options single-request
to /etc/resolv.conf
This causes IPv6/v4 lookups to be done sequentially.
You got this error because nginx can't find the host "localhost_ssl". Indeed it doesn't exist unless you specify it with upstream directive (or in the hosts file I think).
You should set it to proxy_pass http://localhost:8084/; assuming your service is really listening on 127.0.0.1:8084.
Furthermore you may want to replace listen / { with location / {.
UPDATE : If you access your server with your IP (you don't have a domain name), then you can remove server_name directive :
server {
listen 80;
proxy_http_version 1.1;
location /services {
proxy_pass http://localhost:47440/;
proxy_set_header Host $host;
}
location / {
return 301 https://$host$request_uri?; # Replace $server_name by $host
}
server {
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/mycert.crt;
ssl_certificate_key /etc/nginx/ssl/mycert.key;
proxy_http_version 1.1;
location /db {
proxy_pass http://localhost:8084/;
proxy_set_header Host $host;
}
}
That config redirects requests received on port 80 to 443 if they don't match location /services. Requests received on port 443 are proxied if they match location /db.
But is this what you really want to achieve ? I mean a request on port 443 for /test would not match any location as there is only /db.

Resources