插件窝 干货文章 Nginx反向代理中基于关键词和黑名单的ACL配置

Nginx反向代理中基于关键词和黑名单的ACL配置

Nginx blacklist server http 499    来源:    2025-04-20

Nginx反向代理中基于关键词和黑名单的ACL配置

在Nginx反向代理中实现基于关键词和黑名单的访问控制(ACL)可以有效过滤恶意请求、限制特定内容访问或实现安全策略。以下是几种实现方式:

1. 基于关键词的过滤配置

使用ngx_http_rewrite_module模块

server {
    listen 80;
    server_name example.com;

    location / {
        if ($request_uri ~* (malicious|blocked|spam)) {
            return 403;
            # 或者重定向到其他页面
            # return 301 http://example.com/blocked.html;
        }

        proxy_pass http://backend;
    }
}

使用map指令创建关键词列表

map $request_uri $is_blocked {
    default 0;
    ~*(malicious|blocked|spam|hack) 1;
}

server {
    listen 80;
    server_name example.com;

    location / {
        if ($is_blocked) {
            return 403;
        }

        proxy_pass http://backend;
    }
}

2. 基于IP黑名单的配置

使用deny指令

geo $blocked_ip {
    default 0;
    192.168.1.100 1;
    10.0.0.0/8 1;
    # 可以从文件加载
    include /etc/nginx/conf.d/ip-blacklist.conf;
}

server {
    listen 80;
    server_name example.com;

    location / {
        if ($blocked_ip) {
            return 403;
        }

        proxy_pass http://backend;
    }
}

结合GeoIP模块

http {
    geoip_country /usr/share/GeoIP/GeoIP.dat;

    map $geoip_country_code $allowed_country {
        default yes;
        CN no;  # 阻止中国IP
        RU no;  # 阻止俄罗斯IP
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            if ($allowed_country = no) {
                return 403;
            }

            proxy_pass http://backend;
        }
    }
}

3. 基于User-Agent的过滤

map $http_user_agent $bad_agent {
    default 0;
    ~*(wget|curl|scan|bot|spider) 1;
}

server {
    listen 80;
    server_name example.com;

    location / {
        if ($bad_agent) {
            return 403;
        }

        proxy_pass http://backend;
    }
}

4. 高级组合ACL配置

# 定义黑名单变量
map $remote_addr $ip_blacklist {
    default 0;
    include /etc/nginx/conf.d/ip-blacklist.map;
}

map $http_user_agent $bad_agent {
    default 0;
    include /etc/nginx/conf.d/ua-blacklist.map;
}

map $request_uri $bad_keywords {
    default 0;
    include /etc/nginx/conf.d/keyword-blacklist.map;
}

server {
    listen 80;
    server_name example.com;

    # 统一访问控制
    if ($ip_blacklist) {
        return 403;
    }

    if ($bad_agent) {
        return 403;
    }

    if ($bad_keywords) {
        return 403;
    }

    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # 记录被阻止的请求
    location = /log_blocked {
        internal;
        access_log /var/log/nginx/blocked.log combined;
        return 204;
    }
}

5. 使用Lua脚本实现动态ACL(需要OpenResty)

http {
    lua_shared_dict ip_blacklist 10m;

    init_by_lua_block {
        -- 初始化时加载黑名单
        local blacklist = {
            "192.168.1.100",
            "10.0.0.0/8"
        }
        local dict = ngx.shared.ip_blacklist
        for _, ip in ipairs(blacklist) do
            dict:set(ip, true)
        end
    }

    server {
        listen 80;
        server_name example.com;

        access_by_lua_block {
            local ip = ngx.var.remote_addr
            local dict = ngx.shared.ip_blacklist
            if dict:get(ip) then
                ngx.exit(ngx.HTTP_FORBIDDEN)
            end
        }

        location / {
            proxy_pass http://backend;
        }
    }
}

最佳实践建议

  1. 性能考虑:频繁的正则表达式匹配会影响性能,尽量使用map指令预编译规则

  2. 维护性:将黑名单规则放在单独的文件中,便于管理更新

    include /etc/nginx/conf.d/blacklist/*.conf;
    
  3. 日志记录:记录被阻止的请求以便分析

    log_format blocked '$remote_addr - $remote_user [$time_local] '
                     '"$request" $status "$http_referer" '
                     '"$http_user_agent" "$http_x_forwarded_for"';
    
    access_log /var/log/nginx/blocked.log blocked;
    
  4. 动态更新:考虑使用API或定时任务更新黑名单,避免频繁重载Nginx

  5. 分层防护:结合防火墙、WAF等多层防护机制

以上配置可以根据实际需求组合使用,构建适合您业务场景的访问控制策略。