开发者

how to "allow from hostname" in nginx config

开发者 https://www.devze.com 2023-01-26 02:44 出处:网络
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:

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;
   }
0

精彩评论

暂无评论...
验证码 换一张
取 消