Nginx访问控制 #

一、访问控制概述 #

Nginx提供了多种访问控制机制:

  • IP地址限制
  • HTTP Basic认证
  • 请求方法限制
  • 请求频率限制
  • 基于变量的条件控制

二、IP访问控制 #

2.1 基本语法 #

nginx
location /admin/ {
    allow 192.168.1.0/24;
    allow 10.0.0.0/8;
    deny all;
}

2.2 allow和deny指令 #

nginx
allow address;
allow CIDR;
allow all;
deny address;
deny CIDR;
deny all;

2.3 规则匹配顺序 #

规则按配置顺序匹配,匹配成功即停止:

nginx
location / {
    allow 192.168.1.100;
    deny 192.168.1.0/24;
    allow 10.0.0.0/8;
    deny all;
}

上述配置中,192.168.1.100被允许,其他192.168.1.x被拒绝。

2.4 全局IP限制 #

nginx
server {
    listen 80;
    server_name example.com;
    
    allow 192.168.0.0/16;
    allow 10.0.0.0/8;
    deny all;
    
    location / {
        root /var/www/html;
    }
}

2.5 特定路径限制 #

nginx
server {
    listen 80;
    server_name example.com;
    
    location / {
        root /var/www/html;
    }
    
    location /admin/ {
        allow 192.168.1.0/24;
        deny all;
        
        root /var/www/html;
    }
    
    location /api/internal/ {
        allow 127.0.0.1;
        deny all;
        
        proxy_pass http://backend;
    }
}

2.6 基于地理位置限制 #

使用GeoIP模块:

nginx
http {
    geoip_country /usr/share/GeoIP/GeoIP.dat;
    
    map $geoip_country_code $allowed_country {
        default no;
        CN yes;
        US yes;
        JP yes;
    }
}

server {
    location / {
        if ($allowed_country = no) {
            return 403;
        }
        root /var/www/html;
    }
}

2.7 使用geo模块 #

nginx
http {
    geo $allowed_ip {
        default 0;
        192.168.1.0/24 1;
        10.0.0.0/8 1;
        172.16.0.0/12 1;
    }
}

server {
    location /admin/ {
        if ($allowed_ip = 0) {
            return 403;
        }
        root /var/www/html;
    }
}

三、HTTP Basic认证 #

3.1 创建密码文件 #

使用htpasswd工具:

bash
sudo apt install apache2-utils

sudo htpasswd -c /etc/nginx/.htpasswd admin

sudo htpasswd /etc/nginx/.htpasswd user2

3.2 基本配置 #

nginx
location /admin/ {
    auth_basic "Admin Area";
    auth_basic_user_file /etc/nginx/.htpasswd;
    
    root /var/www/html;
}

3.3 组合IP和密码认证 #

nginx
location /admin/ {
    satisfy any;
    
    allow 192.168.1.0/24;
    deny all;
    
    auth_basic "Admin Area";
    auth_basic_user_file /etc/nginx/.htpasswd;
    
    root /var/www/html;
}

3.4 satisfy指令 #

说明
all 必须满足所有条件
any 满足任一条件即可

3.5 密码文件格式 #

text
username:encrypted_password
user2:$apr1$xxx$yyy

3.6 多用户管理 #

nginx
location /admin/ {
    auth_basic "Admin Area";
    auth_basic_user_file /etc/nginx/.htpasswd.admin;
}

location /staff/ {
    auth_basic "Staff Area";
    auth_basic_user_file /etc/nginx/.htpasswd.staff;
}

四、请求方法限制 #

4.1 限制特定方法 #

nginx
location /api/ {
    limit_except GET HEAD POST {
        deny all;
    }
    
    proxy_pass http://backend;
}

4.2 只读API #

nginx
location /api/read/ {
    limit_except GET HEAD {
        deny all;
    }
    
    proxy_pass http://backend;
}

4.3 使用if判断 #

nginx
location /api/ {
    if ($request_method !~ ^(GET|POST|HEAD)$) {
        return 405;
    }
    
    proxy_pass http://backend;
}

五、请求频率限制 #

5.1 定义限制区域 #

nginx
http {
    limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
    limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
}

5.2 应用限制 #

nginx
server {
    location /api/ {
        limit_req zone=req_limit burst=20 nodelay;
        limit_conn conn_limit 10;
        
        proxy_pass http://backend;
    }
}

5.3 参数说明 #

参数 说明
zone 限制区域名称
rate 请求速率
burst 突发请求数
nodelay 不延迟处理突发请求

5.4 返回自定义状态码 #

nginx
limit_req_status 429;
limit_conn_status 429;

5.5 白名单配置 #

nginx
http {
    geo $limit_key {
        default $binary_remote_addr;
        127.0.0.1 "";
        192.168.1.0/24 "";
    }
    
    limit_req_zone $limit_key zone=req_limit:10m rate=10r/s;
}

server {
    location /api/ {
        limit_req zone=req_limit burst=20;
        proxy_pass http://backend;
    }
}

六、基于变量的访问控制 #

6.1 基于User-Agent #

nginx
location / {
    if ($http_user_agent ~* (bot|spider|crawler)) {
        return 403;
    }
    
    root /var/www/html;
}

6.2 基于Referer防盗链 #

nginx
location /images/ {
    valid_referers none blocked server_names *.example.com;
    
    if ($invalid_referer) {
        return 403;
    }
    
    root /var/www/images;
}

6.3 基于Cookie #

nginx
location /premium/ {
    if ($cookie_premium_user = "") {
        return 403;
    }
    
    root /var/www/premium;
}

6.4 基于请求头 #

nginx
location /api/ {
    if ($http_x_api_key = "") {
        return 401;
    }
    
    proxy_pass http://backend;
}

6.5 基于时间 #

nginx
location /maintenance/ {
    set $maintenance 0;
    
    if ($time_iso8601 ~ "T(0[0-5]):") {
        set $maintenance 1;
    }
    
    if ($maintenance = 1) {
        return 503 "System under maintenance";
    }
    
    root /var/www/html;
}

七、JWT验证 #

7.1 使用auth_request模块 #

nginx
server {
    location /api/ {
        auth_request /auth;
        auth_request_set $user $upstream_http_x_user;
        
        proxy_set_header X-User $user;
        proxy_pass http://backend;
    }
    
    location = /auth {
        internal;
        proxy_pass http://auth-service/validate;
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
        proxy_set_header X-Original-URI $request_uri;
    }
}

7.2 使用Lua验证JWT #

nginx
location /api/ {
    access_by_lua_block {
        local jwt = require "resty.jwt"
        local token = ngx.var.http_authorization
        
        if not token then
            ngx.exit(401)
        end
        
        local jwt_obj = jwt:verify("secret", token)
        if not jwt_obj.verified then
            ngx.exit(401)
        end
        
        ngx.req.set_header("X-User", jwt_obj.payload.sub)
    }
    
    proxy_pass http://backend;
}

八、OAuth2认证 #

8.1 使用oauth2-proxy #

nginx
server {
    listen 80;
    server_name app.example.com;
    
    location /oauth2/ {
        proxy_pass http://oauth2-proxy:4180;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
    
    location / {
        auth_request /oauth2/auth;
        error_page 401 = /oauth2/sign_in;
        
        proxy_pass http://backend;
    }
}

九、访问日志记录 #

9.1 记录被拒绝的请求 #

nginx
location /admin/ {
    allow 192.168.1.0/24;
    deny all;
    
    access_log /var/log/nginx/admin.access.log;
    error_log /var/log/nginx/admin.error.log;
    
    root /var/www/admin;
}

9.2 条件日志 #

nginx
map $status $loggable {
    ~^[23] 0;
    default 1;
}

server {
    access_log /var/log/nginx/access.log combined if=$loggable;
}

十、安全最佳实践 #

10.1 隐藏敏感信息 #

nginx
server_tokens off;
server_name_in_redirect off;
port_in_redirect off;

10.2 安全头配置 #

nginx
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Content-Security-Policy "default-src 'self'" always;

10.3 限制请求体大小 #

nginx
client_max_body_size 10m;
client_body_buffer_size 128k;

10.4 超时设置 #

nginx
client_body_timeout 12;
client_header_timeout 12;
send_timeout 10;

10.5 禁止访问敏感文件 #

nginx
location ~* /\.(git|svn|htaccess|htpasswd|env) {
    deny all;
    return 404;
}

location ~* \.(log|bak|sql|conf|ini|swp)$ {
    deny all;
    return 404;
}

十一、完整配置示例 #

nginx
http {
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
    limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
    
    geo $allowed_ip {
        default 0;
        192.168.0.0/16 1;
        10.0.0.0/8 1;
    }
    
    server {
        listen 80;
        server_name example.com;
        
        server_tokens off;
        
        location / {
            root /var/www/html;
            index index.html;
        }
        
        location /admin/ {
            satisfy any;
            
            allow 192.168.1.0/24;
            deny all;
            
            auth_basic "Admin Area";
            auth_basic_user_file /etc/nginx/.htpasswd;
            
            root /var/www/admin;
        }
        
        location /api/ {
            limit_req zone=api_limit burst=20 nodelay;
            limit_conn conn_limit 10;
            
            limit_except GET HEAD POST {
                deny all;
            }
            
            if ($http_user_agent ~* (bot|spider)) {
                return 403;
            }
            
            proxy_pass http://backend;
        }
        
        location /internal/ {
            if ($allowed_ip = 0) {
                return 403;
            }
            
            proxy_pass http://backend;
        }
        
        location ~* /\.(git|svn|htaccess|htpasswd|env) {
            deny all;
            return 404;
        }
        
        location ~* \.(log|bak|sql|conf|ini)$ {
            deny all;
            return 404;
        }
    }
}

十二、总结 #

本章我们学习了:

  1. IP访问控制:allow/deny指令
  2. Basic认证:密码文件和配置
  3. 请求方法限制:limit_except指令
  4. 请求频率限制:limit_req和limit_conn
  5. 变量控制:基于User-Agent、Referer、Cookie等
  6. JWT验证:auth_request和Lua方式
  7. 安全最佳实践:隐藏信息、安全头、敏感文件保护

掌握访问控制后,让我们进入下一章,学习日志管理!

最后更新:2026-03-27