插件窝 干货文章 Nginx反向代理中基于请求方法和请求头的ACL配置

Nginx反向代理中基于请求方法和请求头的ACL配置

HTTP 请求 method return 103    来源:    2025-04-19

Nginx反向代理中基于请求方法和请求头的ACL配置

在Nginx反向代理配置中,基于HTTP请求方法和请求头实现访问控制(ACL)是常见的需求。下面我将详细介绍如何配置这些规则。

基于HTTP请求方法的ACL配置

允许/拒绝特定HTTP方法

location /api/ {
    # 只允许GET和POST方法
    if ($request_method !~ ^(GET|POST)$ ) {
        return 405; # Method Not Allowed
    }

    proxy_pass http://backend;
}

更复杂的HTTP方法控制

location /admin/ {
    # 拒绝TRACE和TRACK方法
    if ($request_method ~ ^(TRACE|TRACK)$ ) {
        return 403;
    }

    # PUT/DELETE方法需要额外验证
    if ($request_method ~ ^(PUT|DELETE)$ ) {
        # 这里可以添加额外的验证逻辑
        # 例如检查特定请求头
        set $allow_method N;
        if ($http_x_api_key = "your-secret-key") {
            set $allow_method Y;
        }

        if ($allow_method = N) {
            return 403;
        }
    }

    proxy_pass http://backend;
}

基于请求头的ACL配置

检查特定请求头

location /secure/ {
    # 检查是否存在Authorization头
    if ($http_authorization = "") {
        return 401; # Unauthorized
    }

    # 检查特定的自定义头
    if ($http_x_custom_header != "expected-value") {
        return 403;
    }

    proxy_pass http://backend;
}

基于User-Agent的过滤

location / {
    # 阻止已知的恶意User-Agent
    if ($http_user_agent ~* (wget|curl|libwww-perl|nikto|sqlmap) ) {
        return 403;
    }

    # 只允许特定浏览器的访问
    if ($http_user_agent !~* (chrome|firefox|safari) ) {
        return 403;
    }

    proxy_pass http://backend;
}

组合多个条件的ACL

location /admin-api/ {
    # 组合多个条件
    set $deny_access N;

    # 条件1: 方法不是POST
    if ($request_method != POST) {
        set $deny_access "${deny_access}1";
    }

    # 条件2: 缺少X-API-Key头
    if ($http_x_api_key = "") {
        set $deny_access "${deny_access}2";
    }

    # 条件3: Content-Type不是application/json
    if ($http_content_type != "application/json") {
        set $deny_access "${deny_access}3";
    }

    # 如果任一条件满足(字符串包含1,2或3)
    if ($deny_access ~ [123]) {
        return 403;
    }

    proxy_pass http://backend;
}

使用map指令实现更复杂的ACL

# 定义允许的User-Agent映射
map $http_user_agent $allowed_agent {
    default 0;
    "~*chrome" 1;
    "~*firefox" 1;
    "~*safari" 1;
}

# 定义允许的方法映射
map $request_method $allowed_method {
    default 0;
    "GET" 1;
    "POST" 1;
    "OPTIONS" 1;
}

server {
    location / {
        # 使用map变量进行判断
        if ($allowed_agent = 0) {
            return 403 "Forbidden User-Agent";
        }

        if ($allowed_method = 0) {
            return 405 "Method Not Allowed";
        }

        proxy_pass http://backend;
    }
}

最佳实践建议

  1. 避免过度使用if指令:Nginx中的if指令有性能开销,特别是在location块中

  2. 优先使用map指令:对于复杂的条件判断,map指令通常更高效

  3. 考虑使用auth_request:对于复杂的授权逻辑,可以使用auth_request指令委托给专门的认证服务

  4. 合理使用return:根据场景返回适当的HTTP状态码(403 Forbidden, 401 Unauthorized, 405 Method Not Allowed等)

  5. 记录拒绝的请求:考虑添加访问日志记录被拒绝的请求,便于安全审计

log_format blocked '$remote_addr - $remote_user [$time_local] '
                  '"$request" $status "$http_user_agent"';

server {
    location / {
        if ($deny_access ~ [123]) {
            access_log /var/log/nginx/blocked.log blocked;
            return 403;
        }
    }
}

通过以上配置,您可以灵活地实现基于HTTP请求方法和请求头的访问控制,保护您的反向代理服务。