nginx upstream does not be recognized by proxy_pass - nginx

I want my nginx to pass different uri's to different backends,so I thought I do that:
server {
listen 8090;
access_log /var/log/nginx/nginx_access.log combined;
error_log /var/log/nginx/nginx_error.log debug;
location /bar {
proxy_pass http://backend2;
}
location /foo {
proxy_pass http://backend2;
}
location / {
proxy_pass http://backend1;
}
}
upstream backend1 {
server 10.33.12.41:8080;
server 127.0.0.1:8080 max_fails=3;
}
upstream backend2 {
server 10.33.12.41:8080;
server 10.33.12.43:8080;
}
If I call wget http://mynginxserver:8090/ i get the following:
wget http://mynginxserver:8090/
--2015-09-18 11:58:21-- http://mynginxserver:8090/
Connecting to mynginxserver:8090... connected.
HTTP request sent, awaiting response... 302 Found
Location: http://backend1/
[following]
--2015-09-18 11:58:21-- http://backend1/
Resolving backend1 (backend1)... failed: Temporary failure in name resolution.
wget: unable to resolve host address ‘backend1’
Why does it try to resolve backend1? I don't get it. Please help ;)
Regards,
Snooops

My Fault:
1st it should have been postet here: serverfault.com
and 2nd its already solved here:
https://serverfault.com/questions/590044/nginx-proxy-pass-config

Related

ngx_http_upstream_check_module checking multiple servers

I'm trying to set up multiple cluster checks in open shift using the free ngx_http_upstream_check_module
https://github.com/alibaba/tengine/blob/master/docs/modules/ngx_http_upstream_check_module.md
http status check request comes only when you explicitly specify Host in the check_http_send section
config example
upstream FPK {
server Host1:80;
server Host2:80;
check interval=3000 rise=2 fall=5 timeout=5000 type=http;
check_http_send "GET /healthz/ready HTTP/1.1\r\nHOST:Host1\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
server {
listen 8090;
location /healthz/ready {
proxy_pass http://FPK;
}
location /nstatus {
check_status;
access_log off;
allow all;
}
}
In this example, the check passes, but only on 1 host, I tried to add a host through a variable, but it seems that this module does not support variables and i get error
2022/09/12 09:17:13 [error] 4123691#0: check protocol http error with peer:Host:80
How to pass multiple hosts in the check_http_send section? Thanks in advance for any help

how to split traffic from same url path to 2 different upstreams?

i have these upstreams declared:
upstream upstream_1 {
server some_container_1:8000;
}
upstream upstream_2 {
server some_container_2:8001;
}
and this server:
server {
listen 7000;
server_name localhost;
location /path {
uwsgi_pass upstream_1;
}
}
where both some_container_1 and some_container_2 are based on same image (thus offer the same apis on the same paths) but differ on env vars and other non related stuff. i want to fork 1% of all traffic from localhost:7000/path to be delivered 'as is' to upstream_2 and 99% to remain on upstream_1. both cases should keep the request as received, altering neither path nor headers
with split_clients i can fork which path will be set before forwarding the request to a single upstream, which is not my case.
here the fork is done inside an upstream between servers, not inside a location splitting between upstreams, as i need.
can i define an upstream of upstreams like
upstream compound_upstream_1 {
upstream upstream_1 weight=99;
upstream upstream_2;
}
to use it on
server {
listen 7000;
server_name localhost;
location /path {
uwsgi_pass compound_upstream_1;
}
is it possible to do this with nginx? considering so, which way should be the standard to accomplish this?
I don't understand, what stops you from using server names in the upstream block directly?
upstream compound_upstream_1 {
server some_container_1:8000 weight=99;
server some_container_2:8001;
}
server {
listen 7000;
server_name localhost;
location /path {
uwsgi_pass compound_upstream_1;
}
}
Or maybe I misunderstand your question?
It might be possible to accomplish this using a load balancer: https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/
I'm not sure what the weights would be for your '1%' scenario but you can toy with it and adjust it to your liking.

How to drop path in rewrite and proxy pass the args in nginx

Example request - http://localhost/iframe?ip=192.168.0.237
I want to proxy pass the request to the value of IP and remove the path and args after localhost/ .
Ideally the proxy_pass should point to 192.168.0.237 and the URL should be http://localhost/.
localhost /iframe {
rewrite ^/(iframe/.*)$ http://localhost/ permanent;
proxy_pass $arg_ip;
}
I'm not sure whether rewrite is the proper way to address this problem.
I would use the argument ip and a rewrite to remove the iframe location
server {
listen 8085;
location /iframe {
rewrite ^/iframe(.*)$ /$1 break;
proxy_pass http://$arg_ip;
}
}
server {
listen 8080;
location / { return 200 "$host$uri"; }
}
Security Notice
I just have a feeling you should whilelist the upstream servers accepted as arguments. If not this will be a wildcard proxy to every single http-server reachable in the network. This is a easy to use SSRF attack vector. So please add some extra layer of security.
SSRF Explained:
Let's say we use this configuration without any further security. Given the folowing NGINX config:
server {
listen 8085;
location /iframe {
rewrite ^/iframe(.*)$ /$1 break;
proxy_pass http://$arg_ip;
}
}
# Server for iframe service
server {
listen 8080;
root /usr/share/nginx/;
location / { return 200 "$host$uri\n"; }
}
# Private Server Section here!
server {
listen 8086;
allow 127.0.0.1;
deny all;
.....
location / {
index welcome.html;
}
}
Trying to reach the secret server directly
curl -v EXTERNALIP:8086
will fail with HTTP 403.
The NGINX will just allow connections form localhost/127.0.0.1 as defined in the allow/deny directives.
But lets try the iframe with the ip argument.
$# curl localhost:8085/iframe?ip=127.0.0.1:8086
Welcome to our very secure server! Internals only!
It prints the content of the secret server. Whitlisting a proxy-pass like this is never a good idea regardless its working or not.

NGINX: Same Hash for multiple upstreams

I've multiple upstreams with same 2 servers in different ports for different apps, but I would need it to keep a consistent connection to the server.
Example:
upstream APP {
ip_hash;
server 10.10.10.1:1111;
server 10.10.10.2:1111;
}
upstream APP_HTTP {
ip_hash;
server 10.10.10.1:2222;
server 10.10.10.2:2222;
}
upstream APP_WS {
ip_hash;
server 10.10.10.1:3333;
server 10.10.10.2:3333;
}
....
location /APP {
proxy_pass http://APP;
}
location /APP_HTTP {
proxy_pass http://APP_HTTP;
}
location /APP_WS {
proxy_pass http://APP_WS;
}
So if a user is redirected at APP starting point to server 10.10.10.1, I need to guarantee that for APP_HTTP and APP_WS goes as well to 10.10.10.1.
Is it possible? How?
IP_Hash seems to not be working as I would expect.
Thanks
Best regards

Nginx location part not being replaced in proxy_pass when using variable

I have a service listening on myservice.mycompany.local
We're proxifying request like this
server {
listen 80;
location /myservice/ {
proxy_pass http://myservice.mycompany.local/;
}
}
it all works fine requests on public.mycompany.com/myservice/api/1/ping are correctly transformed into request to http://myservice.mycompany.local/api/1/ping as there is the trailing /
but now if we try to use a variable
server {
listen 80;
set $MY_SERVICE "myservice.mycompany.local";
location /acm/ {
proxy_pass http://$MY_SERVICE/;
}
}
the local service will only receive a requests to / with the URI part being lost
I've been able to reproduce this "problem" with several version of nginx
1.8.1-1~wheezy
1.4.6-1ubuntu3.5
I'm able also to reproduce it locally by replacing the proxified service by a simple nc -l 127.0.0.2 8080 and using it as the value of my variable, so it really seems to be something happening inside nginx
And this behaviour is not covered in http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
You may have discovered an undocumented feature, but you can always use a rewrite ... break instead of proxy_pass aliasing:
server {
listen 80;
set $MY_SERVICE "myservice.mycompany.local";
location /acm {
rewrite ^/acm(/.*)$ $1 break;
proxy_pass http://$MY_SERVICE;
}
}

Resources