zoukankan      html  css  js  c++  java
  • nginx笔记(五)

    对HTTP资源访问限制

    nginx限制范围,有可能是:

    • 对指定键值(比如每个IP)的连接数;
    • 对指定键值(比如每秒/分钟之间允许处理的请求数)的访问频率;
    • 连接的下载速率。

    一、连接数的限制

    1、用 limit_conn_zone 指令定义某个键,并且共享内存区域参数(工作进程会使用该区域作为共享该键值数)。第1参数是一表达式作为键,第二参数zone,用于指定zone名称和它的大小。

    limit_conn_zone $binary_remote_addr zone=addr:10m;

    2、用 limit_conn 指令 在 location{},server{},或 http{} 上下文中使用连接限制,该指令的第一参数为上方定义的共享内存区域的名称,第二参数定义该键的允许连接数。

    location /download/ {
         limit_conn addr 1;
    }

    上例限制了每个IP地址的连接数,因为 $binary_remote_addr 变量作为键。

    另一个常用的限制连接数是指定某个服务器 $server_name变量:

    http {
        limit_conn_zone $server_name zone=servers:10m;
    
        server {
            limit_conn servers 1000;
        }
    }

    二、限制访问频率

    访问频率限制常用于DDOS攻击防范,或防止上游服务器群组同一时间处理过多的访问。该方法基于 leaky bucket 算法:请求以各种速率到达存储桶,并以固定速率离开存储桶。

    使用频率限制前,需配置 limit_req_zone指令,有以下参数:

    key键:该参数用于区分各客户端,通常用变量表示;

    共享内存区:其名称和大小用于存储这些key键;

    频率:请求访问频率限制设定,单位为每秒请求(r/s) 或者每分钟请求(r/m)。

    limit_req_zone指令定义在http{}层级:

    http {
        #...
        limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
    }

    通过以上配置,共享内存区域 one 拥有 10MB 大小。该区保存 $binary_remote_addr变量值 即客户端IP。

    注意: $remote_addr 也是记录客户端IP地址,而$binary_remote_addr 保存客户端IP地址值的二进制位数,使用空间更小。

                共享区域的大小可通过以下计算得出:$binary_remote_addr 的 IPV4地址值为4字节,在64位系统占用128字节。因此,大约16,000个IP地址的状态信息占用该区域的1MB大小。

    如果NGINX需要添加新条目时存储空间已用尽,它将删除最旧的条目。如果释放的空间仍然不足以容纳新记录,则NGINX返回状态代码" 503 servcie Unavaliable"。状态码可以用 limit_req_status 指令重新定义。

    区域设置好后,就可以用 limit_req 指令在 server{}、location{}或 http{} 上下文中设定好。

    http {
        #...
    
        limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
    
        server {
            #...
    
            location /search/ {
                limit_req zone=one;
            }
        }
    }

    以上配置,nginx将不会处理多于每秒1个请求的 /search/位置访问。这些请求的处理以不超过指定的频率的方式延迟,如果请求数量超过指定的速率,NGINX将延迟处理此类请求,直到“存储桶”(共享存储区 one)已满。如果已满时仍有请求过来,则nginx回复 503 Service Unavailable 错误。

    三、测试请求频率限制

    在配置真实环境下的频率限制前,可以用 dry run 模式不限制请求处理,但会将过多请求的问题记录下来。dry run模式开启使用 limit_req_dry_run 指令:

    location /search/ {
                limit_req zone=one;
                limit_req_dry_run on;
            }

    日志中记录 dry_run标记:

    2019/09/03 10:28:45 [error] 142#142: *13246 limiting requests, dry run, excess: 1.000 by zone "one", client: 172.19.0.1, server: www.example.com, request: "GET / HTTP/1.0", host: "www.example.com:80"

    四、处理过多请求的选项

    由于流量趋向于突发性,因此在流量突发期间响应客户端请求返回错误不是最好的情况。

    NGINX对于过多请求可以被缓冲和处理。limit_req指令的burst参数设置等待以指定频率处理的过多请求的最大数量:

    http {
        #...
    
        limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
    
        server {
            #...
    
            location /search/ {
                limit_req zone=one burst=5;
            }
        }
    }

    以上配置,如果请求超出每秒1个,则超出的请求放入one区。one区已满则过多的请求排入队列,队列大小5个。队列中的请求处理将请不超出设定的总速率。超出burst限制,将会返回503。

    如果在流量突发期间不希望延迟请求,请添加nodelay参数:

    location /search/ {
                limit_req zone=one burst=5 nodelay;
            }

    另外,delay参数可以定义了延迟过多请求以符合定义的速率限制的时间点:

    location /search/ {
                limit_req zone=one burst=5 delay=3;
            }

    使用此配置时,前3个请求(延迟)将无延迟地传递,接下来的2个请求(突发-延迟)将以总速率不大于指定速率的方式延迟,进一步的请求将被拒绝,因为总突发大小已超过,往后的请求将被延迟。

    五、限制带宽

    限制每条连接的带宽使用,使用 limit_rate 指令:

    location /download/ {
        limit_rate 50k;
    }

    以上设置了访问 /download/的每个客户端在每个连接至多使用50K每秒的速率。不过,这里没有限制同一客户端同时开设多个连接。所以要做到下载速度不能超出指定值,那么同时也要限制连接数量:

    location /download/ {
        limit_conn addr 1;
        limit_rate 50k;
    }

        还可以限制客户端在下载一定数量的数据后才进行限制速度,请使用 limit_rate_after 指令。比如允许客户快速下载一定数量的数据(例如,文件标头-电影索引)后,开始限制下载其余数据的速率。

       以下示例合并使用了连接数和带宽限制。每个客户端地址允许的最大连接数设置为5个连接,这适合大多数常见情况,因为现代浏览器通常一次最多打开3个连接。同时,提供下载的位置仅允许一个连接:

    http {
        limit_conn_zone $binary_remote_address zone=addr:10m
    
        server {
            root /www/data;
            limit_conn addr 5;
    
            location / {
            }
    
            location /download/ {
                limit_conn       addr 1;
                limit_rate_after 1m;
                limit_rate       50k;
            }
        }
    }

        limit_rate 还可以设置 变量,进行动态控制带宽:

    map $ssl_protocol $response_rate {
        "TLSv1.1" 10k;
        "TLSv1.2" 100k;
        "TLSv1.3" 1000k;
    }
    
    server {
        listen 443 ssl;
        ssl_protocols       TLSv1.1 TLSv1.2 TLSv1.3;
        ssl_certificate     www.example.com.crt;
        ssl_certificate_key www.example.com.key;
    
        location / {
            limit_rate       $response_rate; # Limit bandwidth based on TLS version
            limit_rate_after 512;      # Apply limit after headers have been sent
            proxy_pass       http://my_backend;
        }
    }

    限制对代理TCP资源的访问

    一、限制IP地址

    allow和deny指令能分开对指定的IP地址或地址段允许或禁止访问。这两指令设置在stream或server上下文中。

    如果设置了一系列规则,则么匹配按顺序从头到尾,直到头一条匹配到为止。

    stream {
        #...
        server {
            listen 12345;
            deny   192.168.1.2;
            allow  192.168.1.1/24;
            allow  2001:0db8::/32;
            deny   all;
        }
    }

    上例中按顺序,192.168.1.1/24为允许访问,并排除192.168.1.2。而2001:0db8::/32的IPV6地址则被允许,并排除其他所有IP地址。

    二、限制TCP连接数

    nginx能限制单一IP同时建立的TCP连接数,这对防止DoS攻击很有效。

    首先,在 stream 上下文使用 limit_conn_zone 指令定义存储连接到一服务器的最大TCP连接数区域,和与其相关的键。

    stream {
        #...
        limit_conn_zone $binary_remote_addr zone=ip_addr:10m;
        #...
    }

    上例中,该键使用 $binary_remote_addr 变量定义。而共享存储区名为ip_addr,具有10MB大小。

    区域定义好后,再使用 limit_conn 指令限制连接。该指令第一参数为 limit_conn_zone 定义的区域名称,第二参数指明允许的各IP地址最大连接数。该指令可在stream 或 server上下文中定义。

    stream {
        #...
        limit_conn_zone $binary_remote_addr zone=ip_addr:10m;
    
        server {
            #...
            limit_conn ip_addr 1;
        }
    }

    当限制每个IP地址的连接数时,请注意网络地址转换(NAT)设备后面的多个主机共享相同的IP地址。

    三、限制带宽

    要设置下载、上传的TCP连接速度,可以用 proxy_download_rate 或 proxy_upload_rate 指令:

    server {
        #...
        proxy_download_rate 100k;
        proxy_upload_rate   50k;
    }

    上例设置了单个TCP连接拥有100K下载速率,和50K上传速率。

    如果需要限制每个客户端的速率,可以限制连接数为1:

    stream {
        #...
        limit_conn_zone $binary_remote_addr zone=ip_addr:10m;
    
        server {
            #...
            limit_conn ip_addr  1;
            proxy_download_rate 100k;
            proxy_upload_rate   50k;
        }
    }
  • 相关阅读:
    这个星期一好像有点无聊
    SQL、LINQ、Lambda三种方式比较
    [C#基础知识]Class和Struct的区别
    C#判断大批量的路径是否存在时,如何缩短判断时间
    批处理 for参数之token详解
    批处理Delims的基本知识
    读取txt文本中每一条路径(一行)并判断,路径不存在的保存在另一txt文本中
    批处理获取一些系统参数
    Cannot read configuration file due to insufficient permissions
    my97datepicker日期选择插件的用法
  • 原文地址:https://www.cnblogs.com/xiwang6428/p/12849277.html
Copyright © 2011-2022 走看看