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
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
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.
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
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
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).