waf防火墙可以拦截一些非法请求,毕竟谁都不能保证自己的代码没有bug.
参考文档:Compilation recipes for v3.x · SpiderLabs/ModSecurity Wiki · GitHub
本次安装环境:Centos8 Stream
本次使用为nginx 1.22.1版本
本次安装方式为动态库安装及加载
主要实现功能:仅允许境内访问,拦截自动跳转,频率访问限制
1.配置powertools源,并安装依赖环境
a.新增repo文件 /etc/yum.repos.d/powertools.repo 内容如下
vim /etc/yum.repos.d/powertools.repo
[powertools1]
name=Extra Packages for Enterprise Linux $releasever - $basearch
baseurl=https://mirrors.aliyun.com/centos/8-stream/PowerTools/x86_64/os/
enabled=1
gpgcheck=0
b.安装依赖环境
dnf install -y gcc-c++ flex bison yajl yajl-devel curl-devel curl GeoIP-devel doxygen zlib-devel lmdb lmdb-devel libxml2 libxml2-devel ssdeep ssdeep-devel lua lua-devel
2.安装ModSecurity
cd /opt/
git clone --depth 1 -b v3/master --single-branch https://github.com/SpiderLabs/ModSecurity
cd ModSecurity
git submodule init
git submodule update
./build.sh
./configure --with-lmdb # ip地域访问模块
make -j 4
make install
3.下载 ModSecurity-nginx 连接器
cd /opt/
git clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git
4.安装NGINX服务
centos8 stream 默认的nginx 是1.14版本,需要重置一下版本,安装目前最新版
dnf module reset nginx -y
dnf module enable nginx:1.22 -y
dnf remove nginx -y # 如果有老版本nginx,建议卸载安装最新版本
dnf install nginx -y
5.编译waf动态库
cd /opt/
wget http://nginx.org/download/nginx-1.22.1.tar.gz
tar zxvf nginx-1.22.1.tar.gz
cd nginx-1.22.1
sudo ./configure --with-compat --add-dynamic-module=../ModSecurity-nginx
sudo make modules
mkdir -pv /etc/nginx/modules
\cp objs/ngx_http_modsecurity_module.so /etc/nginx/modules/
6.配置NGINX
a.在nginx.conf 添加如下配置
load_module "/etc/nginx/modules/ngx_http_modsecurity_module.so";
b.配置规则
mkdir /etc/nginx/conf.d/modsecurity
cp /opt/ModSecurity/modsecurity.conf-recommended /etc/nginx/conf.d/modsecurity/modsecurity.conf
cp /opt/ModSecurity/unicode.mapping /etc/nginx/conf.d/modsecurity/unicode.mapping
cd /opt/
wget https://github.com/coreruleset/coreruleset/archive/v3.3.4.tar.gz
tar xvf v3.3.4.tar.gz
cd coreruleset-3.3.4/
cp -a rules /etc/nginx/conf.d/modsecurity/
cp crs-setup.conf.example /etc/nginx/conf.d/modsecurity/crs-setup.conf
c.启用waf拦截,在nginx.conf配置文件 http 块内加入配置【在http节点添加表示全局配置,在server节点添加表示为指定网站配置】
modsecurity on;
modsecurity_rules_file /etc/nginx/conf.d/modsecurity/modsecurity.conf;
d.编辑 modsecurity.conf
vim /etc/nginx/conf.d/modsecurity/modsecurity.conf
将下面字段修改如下
SecRuleEngine DetectionOnly 改为 SecRuleEngine On
同时添加以下内容:
Include /etc/nginx/conf.d/modsecurity/crs-setup.conf
Include /etc/nginx/conf.d/modsecurity/rules/*.conf
e.自定义规则
#可将自己写的规则放置于此两个文件中
cd /etc/nginx/conf.d/modsecurity/rules/
mv REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
mv RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf
7.拦截指定区域ip
a.该地理位置拦截需要用到 geoip 库,下载该ip库:https://download.csdn.net/download/ly1358152944/87575813
或者自己去官方下载: https://www.maxmind.com/en/accounts/387514/geoip/downloads
mkdir -pv /etc/nginx/conf.d/modsecurity/geoip/
# 并将下载好的文件解压,将文件 GeoLite2-Country.mmdb 放到该目录中
b.修改配置文件 /etc/nginx/conf.d/modsecurity/crs-setup.conf 在 713行左右,添加如下内容
SecGeoLookupDB /etc/nginx/conf.d/modsecurity/geoip/GeoLite2-Country.mmdb
c.配置自定义规则,修改文件 /etc/nginx/conf.d/modsecurity/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
#将以下规则,复制到文件中,规则id如与自己编写的规则ID冲突,直接更改即可:
SecRule REMOTE_ADDR "@geoLookup" "chain,id:22,deny,phase:1,log,msg:'Non-China IP address'"
SecRule GEO:COUNTRY_CODE "!@rx CN|HK|TW|MO"
上规则表示,仅允许中国的IP地址进行访问,其他国家的IP地址若访问网站,则直接阻断。
之所以同时使用CN、HK、TW、MO,是因为在ISO 3166-1标准中,CN仅代表中国内地,不包含港澳台,因此在此直接将港澳台的代码添加其中,如果只希望中国内地的IP地址进行访问,复制以下规则即可:
SecRule REMOTE_ADDR "@geoLookup" "chain,id:22,deny,phase:1,log,msg:'Non-CN IP address'"
SecRule GEO:COUNTRY_CODE "!@rx CN"
SecMarker "END-BEFORE-RULE-EXCLUSIONS" # 该配置为规则结束,应位于配置最底部
8.访问速率限制
【nginx 通过自带的limit 模块进行限制】Module ngx_http_limit_req_module
9.自动跳转页面
需要设置默认的拦截跳转规则,在 /etc/nginx/conf.d/modsecurity/crs-setup.conf 修改如下配置,大约100行左右
SecDefaultAction "phase:1,deny,log,noauditlog,status:302,redirect:http://cdn.hiheyin. com/intercept.html?url=%{REQUEST_URI}&intercept_domain=%{request_headers.host}"
SecDefaultAction "phase:2,deny,log,noauditlog,status:302,redirect:http://cdn.hiheyin. com/intercept.html?url=%{REQUEST_URI}&intercept_domain=%{request_headers.host}"
intercept.html 内容如下:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>访问被拦截</title>
<script type="text/javascript">
function getInterceptUrl() {
var url = getQueryString("url");
var domain = getQueryString("intercept_domain");
var tmpstr = "被拦截URL为:";
var div = document.getElementById("interceptdiv");
if (domain !== "") {
tmpstr += domain;
}
if (url !== "" && url !== "/") {
tmpstr += url;
}
if (domain !== "" || url !== "") {
var textnode = document.createTextNode(tmpstr);
div.appendChild(textnode);
}
}
function getQueryString(name) {
var result = window.location.search.match(new RegExp("[\?\&]" + name + "=([^\&]+)", "i"));
if (result == null || result.length < 1) {
return "";
}
return result[1];
}
</script>
<style type="text/css">
<!--
body {
margin: 0;
font-size: .7em;
font-family: Verdana, Arial, Helvetica, sans-serif;
background: #EEEEEE;
}
fieldset {
padding: 0 15px 10px 15px;
}
h1 {
font-size: 2.4em;
margin: 0;
color: #FFF;
}
h2 {
font-size: 2.4em;
margin: 0;
color: #CC0000;
}
h3 {
font-size: 1.7em;
margin: 10px 0 0 0;
color: #000000;
}
#header {
width: 96%;
margin: 0 0 0 0;
padding: 6px 2% 6px 2%;
font-family: "trebuchet MS", Verdana, sans-serif;
color: #FFF;
background-color: #555555;
}
#content {
margin: 0 0 0 2%;
position: relative;
}
.content-container {
background: #FFF;
width: 50%;
position: relative;
margin: 100px auto 0;
}
a {
text-decoration: none;
color: #009cd6
}
a:hover {
text-decoration: underline;
color: #ff0000
}
-->
</style>
</head>
<body onload="getInterceptUrl();">
<div id="content">
<div class="content-container">
<fieldset>
<br><br><br>
<h2>Warning:</h2>
<br>
<h3>当前的操作可能包含恶意代码,可能会对网站造成安全威胁,已被服务器防火墙拦截。</h3>
<br>
<br>
<div id="interceptdiv" style="color:#F00"></div>
</fieldset>
</div>
</div>
</body>
</html>
当访问带有异常参数的时候,会出现下面错误
在服务器的 /var/log/modsec_audit.log 可以查看详细拦截日志