I'm currently doing this in my nginx.conf:
allow 1.2.3.4;
deny;
What I'd really like to do i开发者_运维技巧s this:
allow my.domain.name;
deny;
I.e., I want nginx to do an A record lookup on my.domain.name at the time of the request, and if it matches the IP that the request is coming from, then allow it. I don't see any built-in mechanism to do this however. Anybody have a native way to do this before I start coding something custom?
ngx_http_rdns_module does what you need: https://www.nginx.com/resources/wiki/modules/rdns/ (https://github.com/flant/nginx-http-rdns)
Summary
This module allows to make a reverse DNS (rDNS) lookup for incoming connection and provides simple access control of incoming hostname by allow/deny rules (similar to HttpAccessModule allow/deny directives; regular expressions are supported). Module works with the DNS server defined by the standard resolver directive.
Example
location / {
resolver 127.0.0.1;
rdns_deny badone\.example\.com;
if ($http_user_agent ~* FooAgent) {
rdns on;
}
if ($rdns_hostname ~* (foo\.example\.com)) {
set $myvar foo;
}
#...
}
This answer is an alternative which let resolution of domain out of nginx but targets the exact same goal, being able to have resolved ips included in nginx configuration.
1) Create a file allowed-domain.list
which contains the domains you want to grant access to :
jean-paul.mydomain.com
rufus.mydomain.com
robert.mydomain.com
2) Create a bash script domain-resolver.sh
which do the lookup for you :
#!/usr/bin/env bash
filename="$1"
while read -r line
do
ddns_record="$line"
if [[ ! -z $ddns_record ]]; then
resolved_ip=`getent ahosts $line | awk '{ print $1 ; exit }'`
if [[ ! -z $resolved_ip ]]; then
echo "allow $resolved_ip;# from $ddns_record"
fi
fi
done < "$filename"
3) Give the right permission to this script chmod +x domain-resolver.sh
4) Add a cron job which produces a valid nginx configuration and restarts nginx :
#!/usr/bin/env bash
/pathtoscript/domain-resolver.sh /pathtodomainlist/allowed-domain.list > /pathtooutputdir/allowed-ips-from-domains.conf
service nginx reload > /dev/null 2>&1
This can be a @daily
job or you can have it run every hour, minute, sec...
5) Update your nginx configuration to take this output into account :
include /pathtooutputdir/allowed-ips-from-domains.conf;
deny all;
You can improve this adding an ip format check, prevent ipv6 if you don't want it, group everything in a single file...
There is no such feature in official distribution of nginx. Beacause it may heavily reduce performance.
Third party modules http://wiki.nginx.org/3rdPartyModules also doesn't contain this feature.
You can use lua script. You need to install nginx-mod-http-lua and lua-nginx-dns modules. The example nginx lua script will be:
location /test/ {
access_by_lua_block {
local resolver = require "nginx.dns.resolver";
local r, err = resolver:new {
nameservers = { "8.8.8.8", "1.1.1.1" },
retrans = 5, -- timeout retransmits
timeout = 500, -- 500msec
no_random = true, -- always start from the first name server
};
if not r then
ngx.log(ngx.ERR, "failed to instantiate the DNS resolver: " .. err)
return
end
local answers, err, tries = r:query("my.domain.name", nil, {});
if not answers then
ngx.log(ngx.ERR, "failed to query the DNS server: " .. err)
return
end
if answers.errcode then
ngx.log(ngx.ERR, "server returned error code: " .. answers.errcode .. ": " .. answers.errstr)
return;
end
for i, ans in ipairs(answers) do
if ans.address == ngx.var.remote_addr then
return
end
end
ngx.log(ngx.ERR, "Not allow IP : " .. ngx.var.remote_addr);
ngx.exit(ngx.HTTP_FORBIDDEN);
}
}
you can add this to return not found for any domain that do not match with yours
if ($host !~* (yourhostname.com)) {
return 404;
}
精彩评论