155Nginx 运维基础入门--Nginx配置实战:访问控制及DDoS预防

Nginx配置实战:访问控制及DDoS预防

访问控制配置

基于各种原因,我们要进行访问控制。比如说,一般网站的后台都不能让外部访问,所以要添加 IP 限制,通常只允许公司的 IP 访问。访问控制就是指只有符合条件的 IP 才能访问到这个网站的某个区域。

相关指令

涉及模块:ngx_http_access_module
模块概述:允许限制某些 IP 地址的客户端访问。

对应指令:
allow
语法:

allow address | CIDR | unix: | all;

默认值: 无
作用域: http, server, location, limit_except```
允许某个 IP 或者某个 IP 段访问。如果指定 unix,那将允许 socket 的访问。
注意:unix 在 1.5.1 中新加入的功能,如果你的版本比这个低,请不要使用这个方法。

deny
语法:

deny address | CIDR | unix: | all;

默认值: 无
作用域:http, server, location, limit_except
禁止某个 IP 或者一个 IP 段访问。如果指定 unix,那将禁止 socket 的访问。
配置范例:

location / {
    deny  192.168.1.1;
    allow 192.168.1.0/24;
    allow 10.1.1.0/16;
    allow 2001:0db8::/32;
    deny  all;
}

规则按照顺序依次检测,直到匹配到第一条规则。
在这个例子里,IPv4 的网络中只有 10.1.1.0/16 和 192.168.1.0/24 允许访问,但 192.168.1.1 除外;对于 IPv6 的网络,只有 2001:0db8::/32 允许访问。

ngx_http_access_module 配置允许的地址能访问,禁止的地址被拒绝。

这只是很简单的访问控制,而在规则很多的情况下,使用 ngx_http_geo_module 模块变量更合适。

这里的 ngx_http_geo_module 模块大家下来可以了解 : ngx_http_geo_module

DDoS 预防配置

DDoS 的特点是分布式,针对带宽和服务攻击,也就是四层流量攻击和七层应用攻击,相应的防御瓶颈四层在带宽,七层的多在架构的吞吐量。

对于七层的应用攻击,我们还是可以做一些配置来防御的,使用 Nginx 的 http_limit_conn 和 http_limit_req 模块通过限制连接数和请求数能相对有效的防御。
ngx_http_limit_conn_module:可以限制单个 IP 的连接数
ngx_http_limit_req_module:可以限制单个 IP 每秒请求数
限制每秒请求数
ngx_http_limit_req_module 模块通过漏桶原理来限制单位时间内的请求数,一旦单位时间内请求数超过限制,就会返回 503 错误。配置需要在两个地方设置:
nginx.conf 的 http 段内定义触发条件,可以有多个条件
在 location 内定义达到触发条件时 nginx 所要执行的动作

http {
    limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
    ...
    server {
        ...
        location  ~ \.php$ {
            limit_req zone=one burst=5 nodelay;
               }
           }
     }

参数说明

image.png

限制 IP 连接数
上一章讲过,我们就直接写出来

http {
    limit_conn_zone $binary_remote_addr zone=addr:10m; //触发条件
    ...
    server {
        ...
        location /download/ {
            limit_conn addr 1;    // 限制同一时间内1个连接,超出的连接返回503
                }
           }
     }

白名单设置
http_limit_conn 和 http_limit_req 模块限制了单 IP 单位时间内的连接和请求数,但是如果 Nginx 前面有 lvs 或者 haproxy 之类的负载均衡或者反向代理,nginx 获取的都是来自负载均衡的连接或请求,这时不应该限制负载均衡的连接和请求,就需要 geo 和 map 模块设置白名单:

geo $whiteiplist  {
        default 1;
        10.11.15.161 0;
    }
map $whiteiplist  $limit {
        1 $binary_remote_addr;
        0 "";
    }
limit_req_zone $limit zone=one:10m rate=10r/s;
limit_conn_zone $limit zone=addr:10m;

geo 模块定义了一个默认值是 1 的变量 whiteiplist,当在 ip 在白名单中,变量 whiteiplist 的值为 0,反之为 1

下面是设置的逻辑关系解释:
如果在白名单中--> whiteiplist=0 --> limit="" --> 不会存储到 10m 的会话状态(one 或者 addr)中 --> 不受限制; 反之,不在白名单中 --> whiteiplist=1 -->limit=二进制远程地址 -->存储进 10m 的会话状态中 --> 受到限制。

安装所有测试所需的软件

安装 php7.0-fpm 和 apache2-utils

sudo apt-get update
sudo apt-get install apache2-utils
sudo apt-get install php7.0-fpm

安装好以后 分别启动 php 和 nginx。

sudo service nginx start
sudo service php7.0-fpm start

测试访问

写一个测试的 php 文件,修改 nginx 配置文件,使其能正常访问。
在 /var/www/html 目录下写一个 test.php,内容如下:

<?php
  phpinfo();
?>
image.png

image.png

如果显示 404 notfound 则是因为之前配置过端口号 9000,在访问时输入 localhost:9000/test.php 即可。后文同理。

修改配置

修改/etc/nginx/nginx.conf

http {

        ##
        # Basic Settings
        ##
        limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;  # 加入这行
        ....
        ....

修改 /etc/nginx/sites-available/default

        location ~ \.php$ {
            limit_req zone=one burst=5 nodelay;   # 加入这行
            root /var/www/html;
            fastcgi_pass unix:/run/php/php7.0-fpm.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
        }

测试

修改配置文件后,使用命令 ab 测试。

ab -n 10 -c 10  http://localhost/test.php

其中 -n 代表每次并发量,-c 代表总共发送的数量。这条命令表示 10 个请求一次并发出去。
测试结果:

This is ApacheBench, Version 2.3 <$Revision: 1706008 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient).....done


Server Software:        nginx/1.10.3
Server Hostname:        localhost
Server Port:            80

Document Path:          /test.php
Document Length:        16 bytes

Concurrency Level:      10
Time taken for tests:   0.051 seconds
Complete requests:      10
Failed requests:        0
Non-2xx responses:      10
Total transferred:      1690 bytes
HTML transferred:       160 bytes
Requests per second:    197.01 [#/sec] (mean)
Time per request:       50.760 [ms] (mean)
Time per request:       5.076 [ms] (mean, across all concurrent requests)
Transfer rate:          32.51 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1   1.7      0       5
Processing:    10   34  14.9     45      45
Waiting:       10   34  14.9     45      45
Total:         15   35  14.0     45      45

Percentage of the requests served within a certain time (ms)
  50%     45
  66%     45
  75%     45
  80%     45
  90%     45
  95%     45
  98%     45
  99%     45
 100%     45 (longest request)

然后我们查看 log,可以看出我们并发了 10 条请求,有 4 条访问失败。

sudo tail /var/log/nginx/error.log
2019/09/17 14:00:11 [error] 8446#8446: *23 limiting requests, excess: 6.000 by zone "one", client: 127.0.0.1, server: _, request: "GET /test.php HTTP/1.0", host: "localhost"
2019/09/17 14:00:11 [error] 8446#8446: *24 limiting requests, excess: 6.000 by zone "one", client: 127.0.0.1, server: _, request: "GET /test.php HTTP/1.0", host: "localhost"
2019/09/17 14:00:11 [error] 8446#8446: *25 limiting requests, excess: 6.000 by zone "one", client: 127.0.0.1, server: _, request: "GET /test.php HTTP/1.0", host: "localhost"
2019/09/17 14:00:11 [error] 8446#8446: *26 limiting requests, excess: 6.000 by zone "one", client: 127.0.0.1, server: _, request: "GET /test.php HTTP/1.0", host: "localhost"
........

挑战:访问控制

介绍
编写一个 Nginx 的 access 模块配置,要求如下:
准许 192.168.3.29/24 的机器访问
准许 10.1.20.6/16 这个网段的所有机器访问
准许 34.26.157.0/24 这个网段访问
除此之外的机器不准许访问

参考配置

在 /etc/nginx/nginx.conf 中加入如下配置:

http {
    ......
    server {
        location / {
            allow 192.168.3.29/24;
            allow 10.1.20.6/16;
            allow 34.26.157.0/24;
            deny all;
        }
    }
    ......
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容