Nginx - How to block all IPs except one - nginx

I'm a total Nginx newbie and I need some help. =]
I have a list of IPs contained within "$proxy_add_x_forwarded_for" which contains IPs separated by commas in this format: "IP, Next IP".
I'd like to return a 403 error code if MY IP is not within this comma separated list.
I thought the easiest way to do it would be to do a simple if statement to say: If $proxy_add_x_forwarded_for doesn't contain MY IP return 403.
Having tried this for ages I can't get anything to work, can anyone help me out? It sounds like this should be really easy.
Edit: Also I'm trying to set this up within the location block because there are other configurations using the Nginx and the IP restriction is only valid for this specific block.

Assuming that your IP address is 123.123.123.123, then the following statement will return 403 if your IP address is not present:
if ($proxy_add_x_forwarded_for !~ \b123\.123\.123\.123\b) { return 403; }
It uses the \b metacharacter to enforce word boundaries (which includes digits) so that the complete IP address is tested.
You can place the expression within a location block if you need to reduce its scope.
The if directive is documented here. See this caution on the use of the if directive. A useful resource for regular expressions is here.

Related

What server names are available when this is set up in the nginx config?

server_name src.wordpress-develop.dev *.src.wordpress-develop.dev ~^src\.wordpress-develop\.\d+\.\d+\.\d+\.\d+\.xip\.io$;
This line is taken from VVV - https://github.com/Varying-Vagrant-Vagrants/VVV
I just want to understand why such server_name is applied and what server names are available in this case.
First, the value of server name is a space separated list of expressions. Let's look at the expressions one by one.
src.wordpress-develop.dev
This sets up serving for that literal domain name. So "http://src.wordpress-develop.dev" in a browser
*.src.wordpress-develop.dev
This one sets up any wildcard subdomain of the domain indicated. So things that would match are foo.src.wordpress-develop.dev or foobar1234-5678.somethingelse.src.wordpress-develop.dev
Finaly the regex one:
~^src\.wordpress-develop\.\d+\.\d+\.\d+\.\d+\.xip\.io$;
The preceeding tilde (~) indicates that what follows is a regular expression. In this case, the regex is matching domains that start with src.wordpress-develop. (note that the .'s are escaped as \. so as not to invoke the regex wildcard character .).
These domains must then have 4 sets of any number of digits followed by a dot each. This looks alot like an IPv4 address so: src.wordpress-develop.205.15.198.6.
Finally, the regex indicates that the domain should end with xip.io, so a full domain that matches this rule is: src.wordpress-develop.205.15.198.6.xip.io. The semicolon at the end of this rule simply terminates the entire server_name expression.
See the docs here
As to why the authors of that software chose these, I can't tell you. In general, the server_name directive is used for Virtual Hosting.

how to match # character in a url in nginx through location directive

How do I match a # character in a url using location directive? I understand that we can use regex(PCRE), but their docs say that :
The location directive only tries to match from the first / after the hostname, to just before the first ? or #. (Within that range, it matches the unescaped url.)"
In short, How to match "example.com/#123456" using
location ~ [someregex] {
return 200 "matched";
}
or with any other alternative
Simple answer, you can't actually, because that part is never sent to the server to begin with, the only way to process this is to use Javascript, using location.hash
You can't because the ID hash isn't actually sent to the server, you might want to use GET variables like example.com?p=1234 if you intend to direct to a certain page or use location.hash if you wish to direct to a location on the page (which is its intended use)
Good luck!

Extract subdomain from url using regex

I've searched through all of the related topics here but none seems to answer my specific need. Here is the problem: Given a URL (sans protocol), I want to extract the subdomain portion, excluding www. The domain portion is always the same so I don't need to support all TLDs. Examples:
www.subdomain.domain.com should match subdomain
www.domain.com should match nothing
domain.com should match nothing
This is one of the many iterations I have tried:
[^(www\.)]\w+[^(\.domain\.com)]
Square brackets indicate character class and will remove all the order of otherwise special meaning of most characters.
You can try something like this instead:
((?:[^.](?<!www))+)\.domain\.com
regex101 demo
To return what you're looking for instead of retrieving it through submatches:
((?:[^.](?<!www))+)(?=\.domain\.com)
regexp101 revised

Why do the following rules conflict in NGINX?

I have these two rules :
location ~* ^.+\.(jpg|jpeg|gif|css|js|png)$ {
proxy_pass http://127.0.0.1:44843$request_uri;
}
location /pc {
proxy_pass http://127.0.0.1:12345$request_uri;
}
The URI :
/pc/asser/somefile.js
falls in teh second rule, why ?
is it a question of lower priority of the "location /pc" rule ?
Nginx documentation defines it:
Directives are processed in the following manner:
Exact string matches are processed first. If a match is found, nginx stops searching and fulfills the request.
Remaining literal string directives are processed next. If the "^~" argument is used, then ngnix stops here and fulfills the request. Otherwise, nginx continues to process location directives.
All location directives specified by regular expressions (with the ~ and ~* arguments) are processed. If a regular expression matches the request, nginx stops here and fulfills the request.
When there are no regular expressions, or no regular expressions match, the most specific literal string match is used.
So you should use regular expression for /pc too:
location ~ /pc/.* {
proxy_pass http://127.0.0.1:12345$request_uri;
}
At first nginx check locations defined using the prefix strings (prefix locations).
And only after, it checks locations defined using regular expressions, in the order of their appearance in a configuration file.
http://nginx.org/en/docs/http/ngx_http_core_module.html#location specifies the order in which nging location directives are looked at:
To find a location matching a given request, nginx first checks locations defined
using the prefix strings (prefix locations). Among them, the most specific one is
searched.
Basically the problem here is that prefix locations are always given priority over regex ones
So in your config, if both blocks match, it's the /pc prefix one that gets priority

How to make nginx-gridfs properly use the result of regex location match

In short, this doesn't work:
location ~* /grid/(.+)/ {
gridfs filestore field=filename type=string root_collection=storage.$1;
}
This is using https://github.com/mdirolf/nginx-gridfs
There are multiple problems with it. This is just an FYI, as I don't think it can be done with location regex, because of:
group is not processes, and $1 is being used verbatim as a "storage.$1" collection name
Somehow, probably in the C code, file name is picked up by stripping characters from the match, by removing exact number of characters that is specified in regex. Meaning, "/grid/(.+)/" is 10 characters long, and this is how many characters are stripped from the entire url (minus domain, obviously). I've tested this quite a bit (short from just going through C code), and this is what it's doing.
I'm assuming this can be still done with rewrite somehow or another nginx config.
As a last resort, I'll reach out to the project maintainer, but nginx's configuration is flexible enough, it seems, to work around the issues, as this works as advertized:
location ~* /grid/ABC/ {
gridfs filestore field=filename type=string root_collection=storage.ABC;
}

Resources