网站系统安全配置(Nginx)防止网站被恶意GJ。网站如DDos,CC等。他们之间都原理都一样,即发送大量的请求数据到服务器。

  • Nginx主动防御方法
    Nginx中有 2 个模块用于控制访问用户连接的“数量”和“速度”。分别是
    HttpLimitZoneModule:限制同时并发连接数访问控制
    HttpLimitReqModule:限制访问数据,每秒最多多少次的请求
    以上两个模块配置比较容易影响系统业务的正常访问,每秒最多的访问次数,同时的并发访问控制,不能设置太死,要不然都杀无赦,统统将正常客户请求挡在外面。
  • Nginx普通配置
    http模块中配置

    # 用户的 IP 地址 $binary_remote_addr 作为 Key,每个 IP 地址最多有 50 个并发连接
    # 你想开几千个连接 刷死我? 超过 50 个连接,直接返回 503 错误给你,根本不处理你的请求了
    # limit single IP 50 concurrent control
    limit_conn_zone $binary_remote_addr zone=TotalConnLimitZone:20m ;
    limit_conn  TotalConnLimitZone  50;
    limit_conn_log_level notice;
    
    # 用户的 IP 地址 $binary_remote_addr 作为 Key,每个 IP 地址每秒处理 20 个请求
    # 你想用程序每秒几百次的刷我,没戏,再快了就不处理了,直接返回 503 错误给你
    # limit single IP/s 20 Request
    limit_req_zone $binary_remote_addr zone=ConnLimitZone:20m  rate=20r/s;
    limit_req_log_level notice;

    其中“limit_conn_zone $binary_remote_addr zone=TotalConnLimitZone:20m ;”表示定义一个名称为TotalConnLimitZone的存储区域,大小20M。 “limit_req_log_level notice;”为定义log级别。
    其中“limit_req_zone $binary_remote_addr zone=ConnLimitZone:20m rate=25r/s;”表示定义一个名称为ConnLimitZone的存储区域,ConnLimitZone内容为远程IP地址,ConnLimitZone大小20M,ConnLimitZone中的平均请求速率为每秒20个; “limit_req_log_level notice;”为定义log级别。
    以上配置应用于server模块

    ...
    location  /abc/ {
            limit_req zone=ConnLimitZone burst=5 nodelay;
            proxy_pass http://abc_pool/;
        }
    ...

    其中“zone=ConnLimitZone”设置使用哪个配置区域来做限制,与上面limit_req_zone的name对应;burst=5,burst爆发的意思,这个配置的意思是设置一个大小为5的缓冲区,当有大量请求(爆发)过来时,超过了访问频次限制的请求可以先放到这个缓冲区内,所以,总的每秒处理请求是上面的20 + 5个排队;nodelay,如果设置,超过访问频次并且缓冲区也满了,会直接返回503,如果没有设置,则所有请求会等待排队。

  • Nginx高级一点的配置
    上面是简单的服务器安全限制访问配置,是在比较简单的客户端浏览器 —–> 系统服务器的访问结构,中间是没有各种网络加速(CDN)的情况下配置。
    很多情况下,是普通用户浏览器 —–> 360网站卫士加速(CDN,360防CC,DOS) ——> 阿里云加速服务器(我们自己建的CDN,阿里云盾) ——> 源服务器(PHP 程序部署在这里,iptables,nginx 安全配置)。
    网站中间经历了好几层透明加速和安全过滤, 这种情况下,就不能用上面的“普通配置”。“源IP”地址不再是普通用户的IP,而是中间网络加速服务器的IP地址了。
    所以,要获取真实客户端IP,就需
    X-Forwarded-For : 用户IP,代理服务器IP...
    经过多层代理之后,用户的真实IP 在第一个位置,后面会跟一串中间代理服务器的IP地址,从这里取到用户真实的IP地址,针对这个IP 地址做限制就可以了。
    Nginx配置:

    #这里取得原始用户的IP地址
    map $http_x_forwarded_for  $clientRealIp {
        ""  $remote_addr;
        ~^(?P[0-9\.]+),?.*$  $firstAddr;
    }
    
    # limit single IP 50 concurrent control,这里的$binary_remote_addr变成$clientRealIp,$clientRealIp为Key
    limit_conn_zone $clientRealIp zone=TotalConnLimitZone:20m ;
    limit_conn  TotalConnLimitZone  50;
    limit_conn_log_level notice;
    
    # limit single IP/s 20 Request,这里的$binary_remote_addr变成$clientRealIp,$clientRealIp为Key
    limit_req_zone $clientRealIp zone=ConnLimitZone:20m  rate=20r/s;
    limit_req_log_level notice;
    
    # 具体服务器配置
    server {
      listen   80;
      location ~ \.php$ {
    
        limit_req zone=ConnLimitZone burst=5 nodelay;
    
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        include fastcgi_params;
    }   
    }
  • 测试
    Nginx配置怎么测试,使用Echo模块。查看本地的Nginx是否有此模块,输入nginx -V命令查看,如果没有,需额外下载该模块进行编译安装。
    这里直接展示nginx配置

    server {
    listen   80;
        server_name  www.aaa.com;
    
        ## 当用户访问 /nginx-test 的时候,我们输出 $clientRealIp 变量,看看这个变量, 用户源IP 地址
        location /nginx-test {
                echo $clientRealIp;
        }
    }

    访问网址接nginx-test,下载后用文本编译器打开,即可看到用户端通过多层CDN 之后,$clientRealIp仍然是有效的原始用户IP地址。