Nginx访问控制
2015 年 02 月 17 日
nginx

    有时出于某些安全,权限等原因,我们需要对客户端访问进行控制,本文将记录如何 限制访问设置连接最大请求数, 或最大的下载速度等。

  • 限制访问

  • 访问控制可以通过允许或拒绝客户端IP地址或使用HTTP基本认证,我可以通过指令 allowdeny(类似于Linux的防火墙)。
  • location / {
        allow 192.168.1.1/24;
        allow 127.0.0.1;
        deny 192.168.1.2;
        deny all;
    }
            
  • 为了开启身份认证,可以使用auth_basic指令。 用户必须输入有效的用户名和密码才能访问站点。而用户名和密码应该列在 auth_basic_user_file指令设置的文件中。
  • server {
        ...
        auth_basic "closed website";
        auth_basic_user_file conf/htpasswd;
    }
            
  • auth_basic的off参数可以取消验证,比如对于一些公共资源,则可以取消验证。
  • server {
        ...
        auth_basic "closed website";
        auth_basic_user_file conf/htpasswd;
    
        location /public/ {
            auth_basic off;
        }
    }
            
  • 我们还需使用satisfy指令来组合来使用IP访问和Http验证。 其默认设置为all,即IP访问和HTTP验证同时通过时才允许用户访问,若设置为any,即IP访问和HTTP验证其一通过就允许用户访问。
  • location / {
        satisfy any;
    
        allow 192.168.1.0/24;
        deny  all;
    
        auth_basic           "closed site";
        auth_basic_user_file conf/htpasswd;
    }
            
  • 限制访问

  • 限制连接数

  • 首先我们使用limit_conn_zone来定义键和共享内存区的大小(工作者进程将使用该区共享键值对的计数信息)。 第一个参数为定义了键的计算表达式,第二个参数zone定义了区的名称和大小:
  • limit_conn_zone $binary_remote_address zone=addr:10m;
            
  • 然后我们使用limit_conn指令在 location, server, http上下文中作限制。
  • location /download/ {
        limit_conn addr 1;
    }
            
  • 我们也可以限制server_name的连接数
  • http {
        limit_conn_zone $server_name zone=servers:10m; #用server作为key
    
        server {
            ...
            limit_conn servers 1000;
        }
    }
            
  • 限制请求率

  • 类似limit_conn_zone,我们使用limit_req_zone指令设置请求率限制的内存共享区
  • limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; # 定义每秒请求数,或r/m每分钟请求数
            
  • limit_req_zone设置好后,则可用limit_req来限制请求率了
  • location /search/ {
        limit_req zone=one burst=5; # brust设置最大等待的请求,超过该值的请求将被返回503
    }
            
  • 也可以使用nodelay不延迟,这将使得超出limit_req的客户端立刻获得503
  • limit_req zone=one burst=5 nodelay;
            
  • 限制带宽

  • 我们可以limit_rate指令限制带宽
  • location /download/ {
        limit_rate 50k; # 每个连接只允许最大50kb/s的速度进行下载
    }
            
  • 如果还想限制一个客户端只能同时一个连接,则还需要加上limit_conn
  • location /download/ {
        limit_conn addr 1;
        limit_rate 50k;
    }

    我们还可以在后端服务器的响应头中设置X-Accel-Limit-Rate来作限制。

  • 当我们仅想当客户端下载了一些数据后,再开始限制下载速度,可以使用limit_rate_after命令
  • limit_rate_after 500k;
    limit_rate 20k;
            
  • 下面是一个较为完整的例子
  • http {
        limit_conn_zone $binary_remote_address zone=addr:10m
    
        server {
            root /www/data;
            limit_conn addr 5;  # 全局允许一个客户端5个连接
    
            location / {
            }
    
            location /download/ {
                limit_conn addr 1; # /download时, 只允许一个客户端1个连接
                limit_rate 50k;
            }
        }
    }
            

好人,一生平安。