0

Nginx连接数限制配置教程:limit_conn防CC攻击与并发控制的完整实战

2026.05.24 | youres | 11次围观

为什么要限制Nginx连接数

服务器资源有限,如果不做连接数控制,一个恶意用户就能用大量并发连接把服务器资源占满,导致正常用户无法访问。CC攻击就是利用这个弱点——用大量连接请求拖垮服务器。Nginx的limit_conn模块就是专门解决这个问题的,它能按IP(或其他key)限制同时连接数,从源头控制并发。

limit_conn_zone指令:定义共享内存区

限制连接数之前,先用limit_conn_zone定义一个共享内存区域,用来记录每个key的连接计数。

语法:

limit_conn_zone  zone=名称:大小;

关键参数说明:

  • :作为限制依据的变量,最常用的是(二进制格式的客户端IP),比更省内存
  • zone=名称:大小:共享内存区名称和大小,10m大约可以记录16万个IP的连接状态

配置位置:http块内(不能放在server或location中)

http {
    limit_conn_zone  zone=connlimit:10m;
}

limit_conn指令:设置连接数上限

定义好共享内存区后,在server或location块中用limit_conn设置具体限制。

语法:

limit_conn zone名称 连接数;

完整示例:

http {
    limit_conn_zone  zone=connlimit:10m;

    server {
        listen 80;
        server_name example.com;

        # 每个IP最多20个并发连接
        limit_conn connlimit 20;

        location / {
            proxy_pass http://backend;
        }

        # 下载区域限制更严格
        location /download/ {
            limit_conn connlimit 5;
            root /data/files;
        }
    }
}

注意:location中的limit_conn会覆盖server层的设置,不是叠加。

limit_conn与limit_req的区别

很多人搞混这两个模块,简单区分:

  • limit_conn:限制同时在线的连接数,比如一个IP最多保持20个连接
  • limit_req:限制单位时间内的请求数,比如一个IP每秒最多10个请求

两者配合使用效果最好:limit_conn控制并发连接,limit_req控制请求速率。

http {
    limit_conn_zone  zone=connlimit:10m;
    limit_req_zone  zone=reqlimit:10m rate=10r/s;

    server {
        limit_conn connlimit 20;
        limit_req reqlimit burst=20 nodelay;
    }
}

自定义503错误页面

连接数超限时,Nginx默认返回503状态码。可以自定义错误页面,给用户更友好的提示:

limit_conn_status 503;

server {
    limit_conn connlimit 20;
    limit_conn_status 503;

    error_page 503 /503.html;
    location = /503.html {
        root /usr/share/nginx/html;
        internal;
    }
}

连接数限制日志记录

默认情况下,连接被限制时Nginx会在error日志中记录一条信息。日志级别可以通过limit_conn_log_level调整:

# 可选值:info | notice | warn | error(默认warn)
limit_conn_log_level warn;

建议保持默认的warn级别,避免info级别产生过多日志影响性能。

实际场景配置示例

场景一:普通网站防护

http {
    limit_conn_zone  zone=perip:10m;

    server {
        # 每个IP最多30个并发连接
        limit_conn perip 30;
    }
}

普通网站30个并发连接足够一个正常用户浏览,同时能挡住低强度CC攻击。

场景二:API接口严格限制

http {
    limit_conn_zone  zone=api:5m;

    server {
        location /api/ {
            # API接口每个IP最多5个并发
            limit_conn api 5;
        }
    }
}

API接口通常不需要太多并发,5个连接够用,也能有效防止接口被恶意刷调用。

场景三:基于server_name限制

http {
    # 按虚拟主机名限制,防止单个站点占用过多连接
    limit_conn_zone  zone=perserver:10m;

    server {
        # 每个server_name最多100个并发连接
        limit_conn perserver 100;
    }
}

适合多站点共享一台服务器的场景,防止单个站点占用过多的服务器资源。

常见问题与排查

1. 限制不生效

检查limit_conn_zone是否放在http块内,limit_conn是否放在正确的server/location中。还要确认变量在当前场景下可用(如果前面有代理,可能需要改用)。

2. 使用CDN后限制异常

CDN场景下所有请求来自CDN的IP,直接限制会误伤。需要在CDN配置中传递真实IP(如X-Forwarded-For),然后:

# 使用realip模块获取真实IP
set_real_ip_from 103.21.244.0/22;  # CDN IP段
real_ip_header X-Forwarded-For;

limit_conn_zone  zone=perip:10m;

3. 共享内存不够用

如果出现limit_conn_zone内存不足的警告,增大共享内存区大小。估算方法:每个记录占32字节(64位系统),10m约可存储16万条记录。如果网站同时在线IP超过这个数,调大到20m或更多。

配置最佳实践

  • 先用limit_conn设置一个较宽松的值(如50),观察日志,再逐步收紧
  • 结合limit_req一起用,连接数和请求速率双重防护
  • 生产环境务必配置limit_conn_status和自定义错误页面
  • CDN/反向代理场景配合ngx_http_realip_module获取真实IP
  • 共享内存区大小根据并发量合理设置,宁可稍大也不要太小
  • 定期检查error日志中被限制的记录,调整阈值

相关文章

版权声明

本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论
881文章数 0评论数
作者其它文章