Nginx - Rewrite rule under proxy failed - nginx

I have some issues with a "basic" rewriting rule under a proxy_pass location type :
location ~* /test1/network/v1/operator/ke3/dataUp {
rewrite ^(?<begin>/test1/network/v1/operator/ke3/dataUp)(?<parametersPart>.*)(?<mustDie>/dataUp)$ $parametersPart break;
proxy_pass http://server_preproduction;
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;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header Host $host;
}
I expect any calls sent to : .../test1/network/v1/operator/ke3/dataUp?param1=GHJ&param2=865/dataUp
To be equal to : .../test1/network/v1/operator/ke3/dataUp?param1=GHJ&param2=865
So I just want to parse the parameters section in order to remove any extra /dataUp from the original request.
But when I try to use any kind of regex to do so, nginx seems to return to the location / and use the default request...
I'm sure that the proper location is use, becanse when I use a rewrite like : rewrite ^(?<begin>/test1/network/v1/operator/ke3/dataUp)(?<parametersPart>.*)$ TEST$parametersPart break;
The log on the proxy server received : TEST?param1=GHJ&param2=865/dataUp
I do not add a / at the end of the proxy_pass because I want replace all the url.(but it's not mandatory ! I tried lot of combinations...)
If someone can save my day :p
Thanks !!

I find a way to manipulate the argument with a simple if statement...
if ($query_string ~ "^(?<argsok>/dataUp.*)(?<argsko>/dataUp)$") {
proxy_pass http://server_preproduction/$argsok;
}

Related

Dynamic proxy_pass based on location

I'm trying to create dynamic proxy_pass based on location (to be run in docker and redirect traffic to docker stacks hosting http, based on stack name)
Here's my current config. Ive got to the point of working redirect with static location (commented variants at the bottom with blue/green redirect properly and application is working fine). I got problem with dynamic location (~^/(?<ver>.*)/(?<rest>.*)?$) - there's issue with proper glueing of the target URL. When i go to https://myapp.com/blue/, nginx logs issue with dns resolution blue could not be resolved (3: Host not found), looks like it cuts everything after $<ver> in http://${ver}_${subdomain}/$rest. Im not an REGEX expert and i probably messed the location part, any suggestions?
server {
listen 80;
server_name ~^(?<subdomain>.+)\.(mydomain\.com|mydomain\.pl)$;
resolver 127.0.0.11 ipv6=off;
location ~^/(?<ver>.*)/(?<rest>.*)?$ {
set $target http://${ver}_${subdomain}/$rest;
proxy_pass $target;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# location ~ ^/blue/((?<rest>.*))?$ {
# set $exdomain http://blue_$subdomain/$rest;
# proxy_pass $exdomain;
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# }
# location ~ ^/green/((?<rest>.*))?$ {
# set $exdomain http://green_$subdomain/$rest;
# proxy_pass $exdomain;
# 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_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
send_timeout 90;
}
* in a regular expression is greedy, so $ver will capture everything until the last /, and not the next / as you intended.
One solution is to use the non-greedy variant *? (not to be confused with ?), for example:
location ~ ^/(?<ver>.*?)/(?<rest>.*)?$ { ... }
But a better solution is to use a character class that excludes /, for example:
location ~ ^/(?<ver>[^/]+)/(?<rest>.*)?$ { ... }
See this useful resource on regular expressions.

Nginx rewrite and proxy_pass explanation

I can see a following locations in nginx/okd configuration:
location /STFlow/ {
rewrite ^/STFlow(.*)$ $1 last;
#
# Are four lines below executed if rewrite has last option ???
# What's the point of them?
#
proxy_pass http://zuul-proxy:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $http_x_forwarded_for;
proxy_set_header X-Forwarded-For $http_x_forwarded_for;
}
location / {
add_header debug-header dbg5;
set $realip $remote_addr;
if ($http_x_forwarded_for ~ "^(\d+\.\d+\.\d+\.\d+)") {
set $realip $1;
}
proxy_pass http://zuul-proxy:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $http_x_forwarded_for;
proxy_set_header X-Forwarded-For $http_x_forwarded_for;
client_max_body_size 50M;
}
In location /STFlow/ are four lines below rewrite ^/STFlow(.*)$ $1 last; ever executed?
If so when?
What's the point of them?
If that rewrite rule had a break flag instead of last, it would remove the /STFlow prefix from /STFlow/some/path URI before passing it to the upstream, i. e. do the same as the second location block except of setting debug-header and $realip variable. But as far as I understand using the last flag makes that four lines never executed, further URI processing would be done inside the second location block.

RabbitMQ Management Over HTTPS and Nginx

I'm trying to access the RabbitMQ interface over HTTPS/SSL with nginx, and I can't figure out what I'm missing.
Here's my rabbitmq.conf file:
[
{ssl, [{versions, ['tlsv1.2', 'tlsv1.1']}]},
{rabbit, [
{reverse_dns_lookups, true},
{hipe_compile, true},
{tcp_listeners, [5672]},
{ssl_listeners, [5671]},
{ssl_options, [
{cacertfile, "/etc/ssl/certs/CA.pem"},
{certfile, "/etc/nginx/ssl/my_domain.crt"},
{keyfile, "/etc/nginx/ssl/my_domain.key"},
{versions, ['tlsv1.2', 'tlsv1.1']}
]}
]
},
{rabbitmq_management, [
{listener, [
{port, 15671},
{ssl, true},
{ssl_opts, [
{cacertfile, "/etc/ssl/certs/CA.pem"},
{certfile, "/etc/nginx/ssl/my_domain.crt"},
{keyfile, "/etc/nginx/ssl/my_domain.key"},
{versions, ['tlsv1.2', 'tlsv1.1']}
]}
]}
]}
].
All works ok when I restart rabbitmq-server
My nginx file looks like this:
location /rabbitmq/ {
if ($request_uri ~* "/rabbitmq/(.*)") {
proxy_pass https://example.com:15671/$1;
}
}
Now, I'm guessing there's something with the ngnix config not being able to resolve the HTTPS URL, as I'm getting 504 timeout errors when trying to browse:
https://example.com/rabbitmq/
Obviously, this is not the correct FQDN, but the SSL cert works fine without the /rabbitmq/
Has anyone been able to use the RabbitMQ Management web interface on an external connection over a FQDN and HTTPS?
Do I need to create a new "server" block in nginx config dedicated to the 15671 port?
Any help would be much appreciated!
I ended up reverting back to the default rabbitmq.config file, then modified my nginx config block to the below, based on another stackoverflow answer that I can't find right now.
location ~* /rabbitmq/api/(.*?)/(.*) {
proxy_pass http://127.0.0.1:15672/api/$1/%2F/$2?$query_string;
proxy_buffering off;
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;
}
location ~* /rabbitmq/(.*) {
rewrite ^/rabbitmq/(.*)$ /$1 break;
proxy_pass http://127.0.0.1:15672;
proxy_buffering off;
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;
}
Also, I had browser caching for JS files, which was causing issues and have disabled that.
I will try to re-enable SSL piece-by-piece but do have the example URL working for now:
https://example.com/rabbitmq/
I tried the following nginx.conf
location /rabbitmq/ {
proxy_pass http://rabbitmq/;
proxy_buffering off;
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;
}
However I couldn't get the details for a queue or exchange. I got 404 errors for api calls.
And there was a %2F in the url, it's url encoded /.
We need to keep the %2F in the API url and pass it to rabbitmq.
The following link describes how to keep the encoded url part and rewrite it.
Nginx pass_proxy subdirectory without url decoding
So my solution is:
location /rabbitmq/api/ {
rewrite ^ $request_uri;
rewrite ^/rabbitmq/api/(.*) /api/$1 break;
return 400;
proxy_pass http://rabbitmq$uri;
proxy_buffering off;
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;
}
location /rabbitmq/ {
proxy_pass http://rabbitmq/;
proxy_buffering off;
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;
}
This did the trick for me
location /rabbitmq {
proxy_pass http://localhost:15672/;
rewrite ^/rabbitmq/(.*)$ /$1 break;
}
I didn't have to use any other directives.
In case someone is looking for the solution for the Apache (2.4):
<VirtualHost *:443>
ServerName rabbitmq.your-domain.com
AllowEncodedSlashes NoDecode
... // rest of the settings
<Location "/">
Require all granted
ProxyPass http://localhost:15672/
ProxyPassReverse http://localhost:15672/
</Location>
<Location "/api">
Require all granted
ProxyPass http://localhost:15672/api nocanon
</Location>
</VirtualHost>
In fact, 2 elements are very important:
The 'AllowEncodedSlashes NoDecode' on VirtualHost level
The 'nocanon' parameter for ProxyPass on "/api" location
This worked for me and I did not need any other header settings. This is a variation on the answer by #user3142747:
location /rabbitmq/ {
# Strip off the "/rabbitmq" prefix
rewrite ^/rabbitmq/(.*) /$1 break;
# Do NOT suffix proxy_pass path with a trailing "/". This allows NGINX to pass the client request completely unchanged.
# - see http://mailman.nginx.org/pipermail/nginx/2009-November/016577.html
proxy_pass $scheme://localhost:15672;
}

nginx proxy_pass with url rewrite - preserve URL

I am trying to rewrite url for another domain, main agenda is keep the user in same URL[dev.gworks.mobi].
http://dev.gworks.mobi/openam/* -> http://frock.gworks.mobi:8080/openam/*
location /openam {
proxy_pass http://frock.gworks.mobi:8080/;
proxy_redirect off;
proxy_set_header Host $host;
}
it partially works
http://dev.gworks.mobi/openam/ -> http://frock.gworks.mobi:8080/ [it works]
http://dev.gworks.mobi/openam/XUI/#login/ -> http://frock.gworks.mobi:8080/openam/XUI/#login/[it does not work]
The reason is http://dev.gworks.mobi/openam/XUI/#login/ proxy to http://frock.gworks.mobi:8080//XUI/#login/ instead of http://frock.gworks.mobi:8080/openam/XUI/#login/. I'm trying rewrite URL but I'm not successful.
rewrite ^/openam/(.*)$ /$1 last;
can anyone help me to achieve my use case?
Below one is works
location /openam {
proxy_pass http://frock.gworks.mobi:8080/openam;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_buffering off;
}

reroute nginx request url

I have a reverse nginx proxy where I want to route all request that come in with :
http://dns.com/content/xyz <—to—> http://dns.com/content/1.0/xyz
I have an upstream :
upstream backend_api.content.com {
server localhost:8080 max_fails=5 fail_timeout=30;
keepalive 100;
}
and location :
#Content Service
location ~* ^/content/?(.*) {
set $proxy_pass "http://backend_api.content.com";
rewrite ^/content/1.0(/.*)$ /content/1.0$1 break;
proxy_pass $proxy_pass
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host "api.stg.xxx.com";
proxy_set_header X-3scale-proxy-secret-token $secret_token;
proxy_set_header Original-Host $http_host;
proxy_set_header Authorization $outbound_auth_header;
proxy_set_header Original-Uri $scheme://$http_host$uri;
post_action /out_of_band_oauth_authrep_action;
}
but it seems like anything with http://dns/content/xyz fails and only when I give http://dns/content/1.0/xyz does it work.
You seem to be capturing part of the URI on the location ~* ^/content/?(.*) statement, but do nothing with it.
You also have a rewrite ^/content/1.0(/.*)$ /content/1.0$1 break; statement that does nothing, it simply writes the same URI back.
A quick and dirty solution might be to use two rewrite statements like this:
rewrite ^/content/1.0(/.*)$ /content/1.0$1 break;
rewrite ^/content(/.*)$ /content/1.0$1 break;
Which means that anything that does not match the first (non-) rewrite will be processed by the second, and get a /1.0 inserted.
Personally, I do not like it, and would rather use two location blocks:
location /content/1.0 {
set $proxy_pass "http://backend_api.content.com";
proxy_pass $proxy_pass;
proxy_http_version 1.1;
proxy_set_header ...
...
}
location /content {
rewrite ^/content(/.*)$ /content/1.0$1 last;
}
But check the evaluation order of your other location blocks. Note that prefix location blocks and regular expression location blocks have different evaluation rules. See this document for details.

Resources