Nginx: How to escape argument value for proxy_pass - nginx

We have such a location configuration:
location ~ ^/suggest/(?<search>.+) {
proxy_pass https://internal.host/v1/products?suggest=$search;
}
The problem is that internal.host receives $search as is, which means that anyone from the outside can pass &another_param=value as a value of $search and thus gain unauthorized access to the remote endpoint.
The question is: how to escape the argument value?

location ~ ^/app/(.*)$ {
proxy_pass http://192.169.154.102:9999/some_dir/$1;
}
This examples results in:
test.com/app/request/xxxxx => http://192.168.154.102:9999/some_dir/xxxxx
Not that the example needs to be adjusted to fit your needs.
Please review this link for more information on proxy_pass(ing) with arguments. Additionally your web application/script that takes in the arguments should perform a check on the parameters given. Before anything is done with the parameters, perform checks and/or filtering of the parameter passed! Please also do some checks, if the above method does limit the parameter, which it should - but please check.
Example from: Nginx proxy_pass: examples for how does nginx proxy_pass map the request.

Related

How to get lua variables back into nginx variables

I have a lua script that uses lua-resty to call another service via co-sockets.
Now I would like to use the information from this call to route the request in nginx.
nginx includes the lua script in access_by_lua*
which sets the var like this:
ngx.var.blocked = '1'
and routes in the location like this:
if ( $blocked ) {
proxy_pass http://haproxy-9001;
break;
}
the problem is now that nginx does not pick up the variable change (in this phase).
if I include the lua script in set_by_lua* phase then the variable passing works but I dont have access to the co-sockets in this phase.
Any idea how to get the variable out of lua land into the nginx variable in the access_by_lua, rewrite_by_lua or content_by_lua phase so that I can use the co-socket api to make a http call?
if nginx directive is implemented by https://nginx.ru/en/docs/http/ngx_http_rewrite_module.html.
Obviously it works on rewrite phase, so your changes at access phase doesn't work.
Just don't use if. Below is snippet from one of my nginx config:
proxy_pass $scheme://$upstream$uri$is_args$args;
Just set $upstream variable at access phase and it will work at content phase (proxy_pass).
Maybe you could capture location with that proxy instead of variable, it works in access_by_lua scope
https://github.com/openresty/lua-nginx-module#ngxlocationcapture

Proxy a request - get a parameter from URL, add a header and update request URL using Nginx

I am looking for a way to do the following using Nginx:
Intercept a request
Read URL, parse it and read a value from it.
Add that value as a new request header
Update the URL (remove a particular value)
Forward the request to another server
e.g
Request URL - http://<<nginx>>/test/001.xml/25
Final URL - http://<<server>>/test/001.xml with header (x-replica: 25)
I have a nginx server setup with a upstream for the actual server. I was wondering how do I setup Nginx to achieve this ?
Since the data exists within the request URI itself (available by the $uri variable in nginx), you can parse that using the nginx lua module. nginx will need to be compiled with lua for this to work, see: openresty's nginx lua module.
From there you can use the set_by_lua_block or set_by_lua_file directive given $uri as a parameter.
In configuration this would look something like:
location / {
...
set_by_lua_file $var_to_set /path/to/script.lua $uri;
# $var_to_set would contain the result of the script from this point
proxy_set_header X-Replica $var_to_set;
...
}
In script.lua we can access the $uri variable from in the ngx.arg list (see these docs):
function parse_uri( uri )
parsed_uri = uri
-- Parse logic here
return parsed_uri
end
return parse_uri( ngx.arg[1] )
Similarly, you can modify this function or create another to make a variable with the updated $uri.

Ignore certain urls from logging in nginx

Im trying to ignore certain urls on my host (as they get requested very often from sync clients and I'm not scared of of any exposure/volunability here)
Typical urls look like;
/cloud/remote.php/caldav/calendars/xxxx#xxxx.com/personlig/
/cloud/remote.php/caldav/calendars/xxxx#xxxx.com/contact_birthdays/
/cloud/remote.php/carddav/xxxx#xxxx.com/
/cloud/remote.php/webdav/xxxx#xxxx.com/
What I'd idealy want to achive is ignore anything after /cloud/remote.php/ or /carddav/ or /caldav/ or /webdav/ a s these belong to sync clients and gets logged seperatedly
I've played around with
location = /cloud/remote.php/ {
access_log off;
}
location = /caldav/calendars/ {
access_log off;
}
But it didnt yield what I expected so I now turn to you guys!
Any suggestions on how I can tackle this?
Use regexps, not equal expression, e.g. for /cloud/remote.php/*:
location ~ ^/cloud/remote.php/(caldav|webdav|carddav)(.*)$ {
access_log off;
}
As for regexps priority, manual says:
"The first matching expression stops the search and nginx will use this location. If no regular expression matches a request, then nginx uses the most specific prefix location found earlier."
How nginx processes a request

Nginx how to pass a parameter to proxy server?

I have a very simple problem but I am new to nginx so I may be missing some obvious solution.
So I have a location defined in nginx
/example/$id
I would like to pass $id to parametrized route on my proxy server like so
http://server.com/example/$id
This gives me unknown id variable on nginx reload. So my question is how can I pass a parameter from nginx to my proxy server.
Assuming all the rest are correctly set, you can just create a location with a regex and pass the captured variable to your proxy.
location ~ ^/example/(.+)$ {
proxy_pass http://server.com/example/$1;
}
If your $id is numeric only, the regex could be more restrictive
location ~ ^/example/(\d+)$ {
proxy_pass http://server.com/example/$1;
}
Note that you can't just use a variable without declaring it first. Declaring $id is not necessary, it is captured inside the parentheses of the regex and passed to $1

how to avoid nginx to replace %20 by whitespace when using as a proxy (proxy_pass) ?

I am using a nginx as a proxy for an apache server.
Here is my config:
location ~ ^/subsite/(.*)$ {
proxy_pass http://127.0.0.1/subsite/$1?$query_string;
}
the problem is that if I send a request with %20 like mywebsite.com/subsite/variable/value/title/Access%20denied/another/example
the %20 is replaced by a whitespace, and apache don't care about all the end of the request after Access /title/Access
Any Idea ?
I was able to solve a similar issue -- we have an api that requires the search terms to be part of the URL path. Passing the output directly to the proxy_pass directive caused it to throw a 502 even though the request was properly url encoded.
Here's the solution we came up with:
location ~ /api/search(/.*) {
set $query $1;
proxy_pass http://127.0.0.1:3003$query;
}
The "set" directive seems to keep the url encoding intact (or re-encodes from what the regex is passing back in $1).

Resources