Nginx配置可以过滤什么?

恶意IP(黑/白名单)
首先,Nginx可以过滤恶意IP,你可以加入下面的配置,譬如恶意IP地址为8.215.34.190
、42.59.101.116
,那我们可以直接
location / {
deny 8.215.34.190;
deny 42.59.101.116;
}
然后上面的IP就不能访问我们的/
路径了(如果你想局部封禁IP,比如一些路径不让这些IP访问,则可以将/
修改为指定路径,譬如/admin
后台地址)
location /admin {
deny 8.215.34.190;
deny 42.59.101.116;
}
同样道理,如果你的网站如果只想让特定的人访问,譬如你的好朋友,它的IP地址为218.102.244.244
我们现在只想让他访问,可以这样设置
location / {
allow 218.102.244.244;
}
你可以简单把上述的场景理解为是黑、白名单,但是这样看起来并不是很舒服,那么有没有方法能够简化上面的情况,当然有!你可以在其中引入文件,譬如
include /www/wwwroot/blockip.conf
然后,我们把blockip.conf
文件里填上恶意IP就行了
deny 8.215.34.190;deny 42.59.101.116;
有人可能会问,我太懒了,能不能让它自动判断把日志里请求频繁的自动添加进来?
当然可以,这里主要分为2种情况:
- 实时检测
- 异步检测(定时读取日志然后添加)
我们先来讲异步检测的方式吧,我们可以创建一个脚本,这里详细步骤我们都做了注释,我们先获取www.anquanclub.cn.log
日志中最近5万条数据,然后过滤掉常见的爬虫,然后将请求次数超过1000的加入黑名单
下面的脚本我放在了/www/wwwroot/blockip.sh
#!/bin/bash
#取最近5w条数据
tail -n 50000 /www/wwwlogs/www.iculture.cc.log \
#过滤需要的信息行ip等
|awk '{print $1,$12}' \
#过滤爬虫
|grep -i -v -E "google|yahoo|baidu|msnbot|FeedSky|sogou|360|bing|soso|403|admin" \
#统计
|awk '{print $1}'|sort|uniq -c|sort -rn \
#超过1000加入黑名单
|awk '{if($1>1000)print "deny "$2";"}' > /www/wwwroot/blockip.conf
然后,我们可以设置计划任务,让它定时运行,你可以直接crontab -e
里添加
*/30 * * * * . /etc/profile;/bin/sh /www/wwwroot/blockip.sh
当然,宝塔里也可以直接添加
很多人会说,这样会误封怎么办,问题不大,热心网友又给大家加了脚本,我们在定期把黑名单IP注释掉,简直太秀了
#!/bin/bash
sed -i 's/^/#&/g' /usr/local/nginx/conf/
blockip.conf #把nginx封锁配置文件中的内容注释掉
service nginx reload #重置nginx服务,这样就做到了解锁IP
当然,如果你想实时检测,还可以通过其他方式,详细的话我们在这期不进行介绍。
感兴趣的可以自行浏览《基于Nginx+Lua自建Web应用防火墙》
恶意请求UA
我们上次说过了,有些恶意攻击者会构造一些恶意的请求头,譬如IE浏览器的
MSIE 9.0
那我们怎么去拦截呢?我们依旧可以通过Nginx配置完成拦截
if ($http_user_agent ~* MSIE 9.0) { <strong>return</strong> 403;}
我们在这里给大家顺便科普一下,nginx里的一些配置上的细节语法,比方说,我把上面的代码改成
if ($http_user_agent ~ MSIE 9.0) { <strong>return</strong> 403;}
代码去掉~*
后面的*
会发生什么?如果去掉了,表示大小写敏感,那么现在的规则可以识别MSIE 9.0
但不能识别Msie 9.0
或者msie 9.0
了,其他的一些语法特征可以参考我们下面总结的表
key | value |
---|---|
语法: | if (条件) { ... } |
默认值: | — |
上下文: | server , location |
条件语法补充
- 变量名;如果变量值为空或者是以“
0
”开始的字符串,则条件为假; - 使用“
=
”和“!=
”运算符比较变量和字符串; - 使用“
~
”(大小写敏感)和“~*
”(大小写不敏感)运算符匹配变量和正则表达式。正则表达式可以包含匹配组,匹配结果后续可以使用变量$1
..$9
引用。如果正则表达式中包含字符“}
”或者“;
”,整个表达式应该被包含在单引号或双引号的引用中。 - 使用“
-f
”和“!-f
”运算符检查文件是否存在; - 使用“
-d
”和“!-d
”运算符检查目录是否存在; - 使用“
-e
”和“!-e
”运算符检查文件、目录或符号链接是否存在; - 使用“
-x
”和“!-x
”运算符检查可执行文件;
恶意请求来路(Referer)
这里先科普一下什么是请求来路:譬如说我们从首页
,点击干货分享
按钮跳转到干货分享
案例一:如何通过Nginx缓解恶意短信接口盗用
我们这里分析一下完整的请求过程,恶意攻击者先对/wp-admin/admin-ajax.php
接口地址发POST请求,然后我们检测到恶意攻击者cookie是空的,没有填
而恶意的请求里,通常在Referer里包含接口地址(接口怎么可能是来路地址?)再或者就是明细很假的,譬如http://www.baidu.com
(百度后面都不带任何参数就访问我们的网站,一看也是工具伪造的恶意流量)
那我们的规则可以设置如下,这时,我们需要将~
改成=
,只有Referer:https://www.baidu.com/
时会返回404
<strong>if</strong> ($http_referer = "https://www.baidu.com/") { <strong>return</strong> 404;
案例一:如何通过Nginx缓解恶意短信接口盗用
我们这里分析一下完整的请求过程,恶意攻击者先对/wp-admin/admin-ajax.php
接口地址发POST请求,然后我们检测到恶意攻击者cookie是空的,没有填

但是,这时我们遇到一个问题,每个我们都能表示出来,nginx好像默认没有逻辑连接符!
我们现在需求是
if ($request_uri ~* /wp-admin/admin-ajax.php && $request_method ~* POST && $cookie_PHPSESSID = '') { <strong>return</strong> 403;}
我们这时,可以通过设置flag来完成
#禁止空cookies请求短信接口
set $flag 0;
if ($request_uri ~* /wp-admin/admin-ajax.php) {
set $flag "${flag}1";
}
if ($request_method ~* POST) {
set $flag "${flag}1";
}
if ($cookie_PHPSESSID = '') {
set $flag "${flag}1";
}
if ($flag = '0111') {
return 403;
}
整个代码的思路就是如果请求/wp-admin/admin-ajax.php
接口了,flag后面加个1,默认是0,现在就是01了
如果是POST请求,flag后面再添个1,现在就是011了
最后,如果cookies中PHPSESSID
为空,那么flag后面再添1,那么现在就是0111了,如果flag为0111时,那么这时禁止访问。这个方法看起来是不是也很不错呢!
案例二:如何通过Nginx拦截爬虫爬取特定接口
有些爬虫会爬取我们的一些接口信息,我们可以通过Nginx配置进行有效拦截
if ($http_user_agent ~* "qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo! Slurp|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot|ia_archiver|Tomato Bot") {
return 403;
}
但是上述方法会让爬虫无法正常访问网站的内容,那么如何加工一下呢?还是参考我们之前的那个逻辑,譬如我们用户信息的接口地址是/api/userinfo
,那么我们不让爬虫访问这个地址就行了
#禁止爬虫爬取用户信息数据
set $flag 0;
if ($request_uri ~* /api/userinfo) {
set $flag "${flag}1";
}
if ($http_user_agent ~* "qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo! Slurp|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot|ia_archiver|Tomato Bot") {
set $flag "${flag}1";
}
if ($flag = '011') {
return 403;
}
还有很多有趣的欢迎你去研究
常见的字段,我们也给大家做了总结
字段名称 | 字段解释 |
$arg_name | 请求行中的name参数 |
$args | 请求行中参数字符串 |
$cookie_name | 名为name的cookie值 |
$document_uri | 同 $uri |
$http_name | 任意请求头的值 |
$host | “Host”请求头的值 |
$query_string | 与$args相同 |
$realpath_root | 按root指令或alias指令算出的当前请求的绝对路径 |
$remote_addr | 客户端IP地址 |
$remote_port | 客户端端口 |
$remote_user | 为基本用户认证提供的用户名 |
$request | 完整的原始请求行 |
$request_body | 请求正文 |
$request_body_file | 请求正文的临时文件名 |
$request_completion | 请求完成时返回“OK”,否则返回空字符串 |
$request_filename | 基于root指令或alias指令,以及请求URI,得到的当前请求的文件路径 |
$request_method | HTTP方法,通常为“GET”或者“POST” |
$request_time | 请求处理的时间,从客户端接收到第一个字节开始计算 |
$request_uri | 完整的原始请求行(带参数) |
$scheme | 请求协议类型,为“http”或“https” |
$status | 响应状态码 |
$uri | 当前请求规范化以后的URI |
$content_length | “Content-Length” 请求头字段 |
$content_type | “Content-Type” 请求头字段 |
$limit_rate | 用于设置响应的速度限制,详见 limit_rate |
请登录后查看评论内容