Nginx sub_filter for headers - nginx

I want to use nginx proxy_pass before different applications which run on their own port.
so i.e. I have
server {
listen 443 ssl;
ssl on;
ssl_certificate /etc/ssl/certs/self-signed.crt;
ssl_certificate_key /etc/ssl/private/self-signed.key;
proxy_intercept_errors on;
location /app1/ {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
proxy_http_version 1.1;
proxy_redirect off;
proxy_pass http://localhost:1111;
}
location /app2/ {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
proxy_http_version 1.1;
proxy_redirect off;
proxy_pass http://localhost:2222;
}
}
However the problem is the applications itself have redirects in them which causes the /app1/ or /app2/ to disappear.
i.e. a 302 get /page1 will become https://example.com/page1 instead of https://example.com/app1/page1
So basically whenever someone is at a /app1/* page to always prefix /app1/.
and it would be really great if this doesn't happen when this is actually the full domain name so it's possible to load resources from a /app2/ url in a /app1/ page
Is there a way I can fix with Nginx config or can I only fix this in the application itself?
EDIT:
I found that Nginx has a function called sub_filter.
This replaced strings in the body of the response.
so:
app returns: 200 "hello world!"
//nginx
sub_filter "world" "moon";
then the browser will display "hello moon!"
However I also need to do this for 302 redirects.
Is there a "sub_filter equivalent" for headers?
EDIT2:
As Ivan suggested probably proxy redirect should do the trick, but it's not changing anything.
my nginx code is:
location /app1/ {
proxy_set_header Accept-Encoding ""; # no compression allowed or next won't work
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
proxy_http_version 1.1;
proxy_redirect off;
proxy_buffering off;
proxy_read_timeout 3600;
proxy_connect_timeout 3600;
fastcgi_read_timeout 3600s;
proxy_pass http://localhost:5000/;
proxy_redirect http://localhost:5000/ /app1/; #also tried full domain
}
As for the app I'm testing this with a simple Flask app like this:
#app.route('/')
def hello_world():
return redirect("http://localhost:5000/testing", code=302)
and the browser response headers are:
HTTP/1.1 302 FOUND
Server: nginx/1.14.0 (Ubuntu)
Date: Wed, 06 Nov 2019 15:56:24 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Location: http://localhost:5000/testing

Use proxy_redirect directive for your case:
proxy_redirect / /app1/;
and
proxy_redirect / /app2/;
Remove any proxy_redirect off; directive because it cancels the effect of all proxy_redirect directives on the same level.

Related

Use nginx location blocks with Shinyproxy

I recently successfully deployed a ShinyProxy + app using SSL with nginx and certbot in the following manner:
Dockerize ShinyProxy + app and launch on port 127.0.0.1:5001.
Create Nginx config and proxy_pass to 127.0.0.1:5001.
Secure using certbot.
This is the successful nginx.conf location section:
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-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_redirect off;
proxy_read_timeout 90s;
proxy_pass http://127.0.0.1:5001;
}
This nicely redirects me to https://app.myweb.com/login as I have set up a CNAME. Important to note, {ShinyProxy} redirects to the login at the end automatically. On successful login the url redirects to https://app.myweb.com/app/website.
What I really struggle with is the following: adding a location block or as I understand it, include my upstream block into my downstream (correct my terms if I am wrong). So, have my url go from https://app.myweb.com/login to https://app.myweb.com/dashboard/login using the following configuration in nginx:
location /dashboard/ { # THIS IS WHAT I WANT TO ADD
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 $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_redirect off;
proxy_read_timeout 90s;
proxy_pass http://127.0.0.1:5001;
}
All that happens is, if I type https://app.myweb.com/dashboard/ it doesn't go to https://app.myweb.com/dashboard/login as I would expect, but redirects back to https://app.myweb.com/login which 404's.
Any advice on what I am doing wrong?

How to proxy pass two applications running on / on two different ports

this is my nginx configuration file
server {
listen 80;
server_name 0.0.0.0;
client_max_body_size 10000M;
location / {
auth_basic "Restricted Content";
auth_basic_user_file /etc/apache2/.htpasswd;
proxy_pass http://localhost:8888;
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 $scheme;
proxy_set_header X-Real-Scheme $scheme;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 120s;
proxy_next_upstream error;
}
location /source {
auth_basic "Restricted Content";
auth_basic_user_file /etc/apache2/.htpasswd;
proxy_pass http://localhost:5050/source;
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 $scheme;
proxy_set_header X-Real-Scheme $scheme;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 120s;
proxy_next_upstream error;
}
}
I am able to route first application running on port 8888 but for second application running on port 5050 i am not able to route through nginx. i am using /source as a prefix but it's not working. Second application also starts with / in our application. Please request guidance in this on the above issue.
/ matches before /source so you never reach /source and therefore can't be routed. switching the order of the location directive should be enough.

NGINX : proxy_pass with regex and rewrite

i have this NGINX location in my default.conf
location /api-gateway/ {
proxy_http_version 1.1;
proxy_connect_timeout 75s;
proxy_read_timeout 100s;
client_max_body_size 100m;
proxy_set_header Host test.domain.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_buffers 16 8k;
proxy_buffer_size 4k;
proxy_max_temp_file_size 0;
rewrite ^/api-gateway/(.*)$ $1 break;
proxy_pass http://ingress-srv; # ingress-srv is an upstream
}
here is an example of the request that is coming to my NGINX server: http://demo.domain.com/api-gateway/service/v1/metrics
i need to do the below
remove the /api-gateway/ from the original url and then,
rewrite/send the requests to ingress-srv upstream without
changing the URL (no redirect)
change the header from demo.domain.com to test.domain.com which i believe i have done it correctly
i can not make it work ..
Instead of
proxy_pass http://ingress-srv; # ingress-srv is an upstream
try doing (notice the slash):
proxy_pass http://ingress-srv/; # ingress-srv is an upstream
You can take out the rewrite directive.
As Oscar Wilde said "I was working on nginx.conf all the morning, and took out a comma. In the afternoon I put it back again."

nginx net::ERR_INCOMPLETE_CHUNKED_ENCODING

I am trying to hit a URL on nginx which be proxied to Netty, for a particular URL I am getting net::ERR_INCOMPLETE_CHUNKED_ENCODING on chrome and on Safari some times it works and some times not.
Here is the configuration:
location /service-order-api {
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host:$server_port;
proxy_pass http://service_order_api;
#proxy_read_timeout 120;
proxy_set_header X-Real-IP $remote_addr;
#proxy_buffer_size 2k;
#proxy_buffers 8 24k;
proxy_redirect off;
#proxy_buffering off;
chunked_transfer_encoding on;
}
Try setting this option for your server:
proxy_buffering off;
Don't know the reason, but this solved my case.

mod-security allowing only one set-cookie

Has anyone run into the problem of mod-security only allowing one set-cookie through a proxy request response? We are using nginx with mod-security and seeing all but the last set-cookie be removed by nginx on the response from our application server. We are applying the mod-security in the location section
location ~* ^/(test|securitytest|$) {
ModSecurityEnabled on;
ModSecurityConfig modsecurity.conf;
create_full_put_path on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://app;
proxy_read_timeout 10;
proxy_redirect off;
}
there was a bug in modsecurity+nginx that was dropping all except one cookie for each request. It was fixed, have a look at:
https://github.com/SpiderLabs/ModSecurity/issues/154

Resources