如何在nginx配置中“允许来自主机名”

时间:2010-11-22 14:48:00

标签: nginx

我目前正在我的nginx.conf中执行此操作:

allow 1.2.3.4;
deny;

我真正想做的是:

allow my.domain.name;
deny;

即,我希望nginx在请求时对my.domain.name执行A记录查找,如果它与请求来自的IP匹配,则允许它。但是,我没有看到任何内置机制。在开始编写自定义内容之前,有人有本地方法吗?

4 个答案:

答案 0 :(得分:18)

ngx_http_rdns_module可以满足您的需求:http://wiki.nginx.org/HttpRdnsModulehttps://github.com/flant/nginx-http-rdns

摘要

此模块允许对传入连接进行反向DNS(rDNS)查找,并通过允许/拒绝规则提供对传入主机名的简单访问控制(类似于HttpAccessModule允许/拒绝指令;支持正则表达式)。模块使用标准解析器指令定义的DNS服务器。

实施例

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

    #...
}

答案 1 :(得分:5)

nginx的正式发布中没有这样的功能。因为它可能会大大降低性能。

第三方模块http://wiki.nginx.org/3rdPartyModules也不包含此功能。

答案 2 :(得分:0)

此答案是一种替代方案,可以让域解析超出nginx,但目标完全相同,可以解析nginx配置中包含的ip。

1)创建文件allowed-domain.list,其中包含您要授予访问权限的域:

jean-paul.mydomain.com
rufus.mydomain.com
robert.mydomain.com

2)创建一个bash脚本domain-resolver.sh来为您执行查找:

#!/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)对此脚本chmod +x domain-resolver.sh

授予正确的权限

4)添加一个cron作业,该作业将生成有效的nginx配置并重新启动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

这可以是一项@daily的工作,也可以使其每小时,每分钟,每秒钟运行一次……

5)更新您的nginx配置,以将此输出考虑在内:

include /pathtooutputdir/allowed-ips-from-domains.conf;
deny all;

您可以通过添加ip格式检查来改进此功能,如果不希望使用ipv6,可以将所有内容归为一个文件...

答案 3 :(得分:0)

你可以使用lua脚本。 您需要安装 nginx-mod-http-lua 和 lua-nginx-dns 模块。 nginx lua 脚本示例将是:

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