VPS主机部署Web应用防火墙Ngx_lua_waf抵抗CC攻击,保护数据安全

自然 2019年3月13日20:26:13 评论

越来越多的人使用VPS主机建站,但是与虚拟主机或者管理型的服务器相比,个人VPS主机基本上是无管理型的,即主机商只负责VPS主机的网络畅通,至于技术上的问题都得靠自己来解决。网站经常会受到一些自动化工具的扫描、注入、溢出挂马等等的情况。

VPS主机部署Web应用防火墙Ngx_lua_waf抵抗CC攻击,保护数据安全

商用虚拟主机有专门的运维工程师做好安全防范工作,正如上面所说VPS等等的虚拟云机是没有什么专门人员辅助运维的,这需要我们自己来进行操作,今天给他家介绍一款非常不错的Nginx(openresty)WEB应用防火墙模块ngx_lua_waf。ngx_lua_waf一个基于ngx_lua的web应用防火墙,代码非常的简单,开发者的初衷是方便使用,在高性能的同时保留其轻量级的特点。

Ngx_lua_waf的主要作用

  1. 防止sql注入,本地包含,部分溢出,fuzzing测试,xss,SSRF等web攻击
  2. 防止svn/备份之类文件泄漏
  3. 防止ApacheBench之类压力测试工具的攻击
  4. 屏蔽常见的扫描黑客工具,扫描器
  5. 屏蔽异常的网络请求
  6. 屏蔽图片附件类目录php执行权限
  7. 防止webshell上传

这里我们可以看出Ngx_lua_waf的功能还是相当丰富的,可以有效的拒绝大部分扫描攻击,对于防止网站被挂马有着非常显著的作用。

安装要求

Ngx_lua_waf的作者推荐使用lujit2.1做lua的支持,ngx_lua如果是0.9.2以上版本,建议正则过滤函数改为ngx.re.find,匹配效率会提高三倍左右。我们的Nginx只需要编译lua支持就可以部署这款WEB应用防火墙,为我们的服务器添加一道安全门。

使用说明

我们假设nginx安装路径为:/usr/local/nginx/conf/

我们只需要把ngx_lua_waf下载到conf目录下,解压命名为waf即可,在nginx.conf的http段添加,或者单独写作一个conf文件,使用include引用到nginx.conf中亦可。

  1. lua_package_path "/usr/local/nginx/conf/waf/?.lua";
  2. lua_shared_dict limit 10m;
  3. init_by_lua_file  /usr/local/nginx/conf/waf/init.lua;
  4. access_by_lua_file /usr/local/nginx/conf/waf/waf.lua;

配置config.lua里的waf规则目录(一般在waf/conf/目录下)

  1. RulePath = "/usr/local/nginx/conf/waf/wafconf/"

然后我们按照调试准则,先运行nginx -t检测一下配置是否正确,如果提示成功加载我们再重启nginx即可。

配置文件详细说明:

  1. RulePath = "/usr/local/nginx/conf/waf/wafconf/"
  2.     --规则存放目录
  3.     attacklog = "off"
  4.     --是否开启攻击信息记录,需要配置logdir
  5.     logdir = "/usr/local/nginx/logs/hack/"
  6.     --log存储目录,该目录需要用户自己新建,切需要nginx用户的可写权限
  7.     UrlDeny="on"
  8.     --是否拦截url访问
  9.     Redirect="on"
  10.     --是否拦截后重定向
  11.     CookieMatch = "on"
  12.     --是否拦截cookie攻击
  13.     postMatch = "on"
  14.     --是否拦截post攻击
  15.     whiteModule = "on"
  16.     --是否开启URL白名单
  17.     black_fileExt={"php","jsp"}
  18.     --填写不允许上传文件后缀类型
  19.     ipWhitelist={"127.0.0.1"}
  20.     --ip白名单,多个ip用逗号分隔
  21.     ipBlocklist={"1.0.0.1"}
  22.     --ip黑名单,多个ip用逗号分隔
  23.     CCDeny="on"
  24.     --是否开启拦截cc攻击(需要nginx.conf的http段增加lua_shared_dict limit 10m;)
  25.     CCrate = "100/60"
  26.     --设置cc攻击频率,单位为秒.
  27.     --默认1分钟同一个IP只能请求同一个地址100次
  28.     html=[[Please go away~~]]
  29.     --警告内容,可在中括号内自定义
  30.     备注:不要乱动双引号,区分大小写

检查规则是否生效

部署完毕可以尝试如下命令:

  1. curl http://xxxx/test.php?id=../etc/passwd
  2. 返回"Please go away~~"字样,说明规则生效。

注意:默认,本机在白名单不过滤,可自行调整config.lua配置

分享自然正在使用的规则

自然把配置单独存储为一个waf.conf文件,在nginx.conf中使用include的方式加载。

waf.conf文件代码如下:

  1. lua_shared_dict limit 20m;
  2. lua_package_path "/usr/local/nginx/conf/waf/?.lua;;";
  3. init_by_lua_file "/usr/local/nginx/conf/waf/init.lua";
  4. access_by_lua_file "/usr/local/nginx/conf/waf/access.lua";

waf文件夹下的config.lua配置如下:

  1. --WAF config file,enable = "on",disable = "off"
  2. --waf status
  3. config_waf_enable = "on"
  4. --log dir
  5. config_log_dir = "/data/wwwlogs"
  6. --rule setting
  7. config_rule_dir = "/usr/local/nginx/conf/waf/wafconf"
  8. --enable/disable white url
  9. config_white_url_check = "on"
  10. --enable/disable white ip
  11. config_white_ip_check = "on"
  12. --enable/disable block ip
  13. config_black_ip_check = "on"
  14. --enable/disable url filtering
  15. config_url_check = "on"
  16. --enalbe/disable url args filtering
  17. config_url_args_check = "on"
  18. --enable/disable user agent filtering
  19. config_user_agent_check = "on"
  20. --enable/disable cookie deny filtering
  21. config_cookie_check = "on"
  22. --enable/disable cc filtering
  23. config_cc_check = "on"
  24. --cc rate the xxx of xxx seconds
  25. config_cc_rate = "60/60"
  26. --enable/disable post filtering
  27. config_post_check = "on"
  28. --config waf output redirect/html
  29. config_waf_output = "html"
  30. --if config_waf_output ,setting url
  31. config_waf_redirect_url = "/captcha"
  32. config_waf_captcha_html=[[
  33. <html>
  34.     <head>
  35.         <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  36.         <title data-sw-translate>Please enter verification code - OneinStack WAF</title>
  37.         <style> body { font-family: Tahoma, Verdana, Arial, sans-serif; }
  38.                         .head_title{margin-top:100px; font-family:"微软雅黑"; font-size:50px; font-weight:lighter;}
  39.                         p{font-family:"微软雅黑"; font-size:16px; font-weight:lighter; color:#666666;}
  40.                         .btn{ float:left;margin-left:15px; margin-top:5px; width:85px; height:30px; background:#56c458;font-family:"微软雅黑"; font-size:16px; color:#FFFFFF; border:0;}
  41.                         .inp_s{ float:left; margin-left:15px; margin-top:5px; width:200px; height:30px;}
  42.                         .yz{float:left; width:160px; height:40px;}
  43.                         .fors{ margin:0 auto;width:500px; height:40px;}
  44.                 .form {width: 500px; margin: 2em auto;}
  45.         </style>
  46.     </head>
  47.     <body>
  48.         <div align="center">
  49.                         <p><h1 class="head_title" data-sw-translate>Sorry...</h1></p>
  50.                         <p data-sw-translate>Your query looks similar to an automated request from computer software. In order to protect our users, please forgive us for temporarily not processing your request.</p>
  51.                         <p data-sw-translate>To continue accessing the webpage, please enter the characters shown below:</p>
  52.                 <div class="form">
  53.                     <img id="captcha-img" class="yz" src="https://oneinstack.com/restapi/v1/captchas/038fb48d9f8170e9a7c67aee79106a31" alt="Captcha image"><input id="captcha-input" class="inp_s" type="text" name="response" /><input id="captcha-submit" class="btn" type="submit" data-sw-translate value="Submit" />
  54.                 </div>
  55.         </div>
  56.     <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
  57.     <script>
  58.         var url = 'https://oneinstack.com/restapi/v1/captchas'
  59.         // 获取验证码 hash
  60.         $.post(url).then((res) => {
  61.                 const {errno, errmsg, data} = JSON.parse(res)
  62.                 if (errno) {
  63.                         return alert(errmsg)
  64.                 }
  65.                 // 更新验证码图片
  66.                 document.querySelector('#captcha-img').src = `${url}/${data}`
  67.                 // 提交验证码
  68.                 document.querySelector('#captcha-submit').addEventListener('click', e => {
  69.                         $.post(`${url}/check`, {
  70.                                 key: data,
  71.                                 code: document.querySelector('#captcha-input').value,
  72.                         }).then(res => {
  73.                                 const {errno, errmsg, data} = JSON.parse(res)
  74.                                 if (errno) {
  75.                                         return location.reload()
  76.                                 }
  77.                                 var targetUrl = new URLSearchParams(location.search).get('continue')
  78.                                 targetUrl = atob(targetUrl)
  79.                                 location.href = targetUrl
  80.                         })
  81.                 })
  82.         })
  83.         window.SwaggerTranslator = {
  84.             _words: [],
  85.             translate: function () {
  86.                 var $this = this;
  87.                 $('[data-sw-translate]').each(function () {
  88.                     $(this).html($this._tryTranslate($(this).html()));
  89.                     $(this).val($this._tryTranslate($(this).val()));
  90.                     $(this).attr('title', $this._tryTranslate($(this).attr('title')));
  91.                 });
  92.             },
  93.             _tryTranslate: function (word) {
  94.                 return this._words[$.trim(word)] !== undefined ? this._words[$.trim(word)] : word;
  95.             },
  96.             learn: function (wordsMap) {
  97.                 this._words = wordsMap;
  98.             }
  99.         };
  100.         window.SwaggerTranslator.learn({
  101.             "Please enter verification code - OneinStack WAF""输入验证码",
  102.             "Your query looks similar to an automated request from computer software. In order to protect our users, please forgive us for temporarily not processing your request.""您的查询看起来类似于来自计算机软件的自动请求。为了保护我们的用户,请原谅我们现在暂时不能处理您的请求。",
  103.             "To continue accessing the webpage, please enter the characters shown below:""要继续访问网页,请输入下面所示字符:",
  104.             "Sorry...""很抱歉...",
  105.             "Submit""提交",
  106.         });
  107.         $(function () {
  108.             window.SwaggerTranslator.translate();
  109.         });
  110.     </script>
  111.     </body>
  112. </html>
  113. ]]
  114. config_output_html=[[
  115. <html xmlns="http://www.w3.org/1999/xhtml"><head>
  116. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  117. <title>网站防火墙</title>
  118. <style>
  119. p {
  120.     line-height:20px;
  121. }
  122. ul{ list-style-type:none;}
  123. li{ list-style-type:none;}
  124. </style>
  125. </head>
  126. <body style=" padding:0; margin:0; font:14px/1.5 Microsoft Yahei, 宋体,sans-serif; color:#555;">
  127.  <div style="margin: 0 auto; width:1000px; padding-top:70px; overflow:hidden;">
  128.   <div style="width:600px; float:left;">
  129.     <div style=" height:40px; line-height:40px; color:#fff; font-size:16px; overflow:hidden; background:#6bb3f6; padding-left:20px;">网站防火墙 </div>
  130.     <div style="border:1px dashed #cdcece; border-top:none; font-size:14px; background:#fff; color:#555; line-height:24px; height:220px; padding:20px 20px 0 20px; overflow-y:auto;background:#f3f7f9;">
  131.       <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; color:#fc4f03;">您的请求带有不合法参数,已被网站管理员设置拦截!</span></p>
  132.       <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">可能原因:您提交的内容包含危险的攻击请求</p>
  133.       <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:0px;">如何解决:</p>
  134.       <ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">1)检查提交内容;</li>
  135.       <li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">2)如网站托管,请联系空间提供商;</li>
  136.       <li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">3)普通网站访客,请联系网站管理员;</li></ul>
  137.     </div>
  138.   </div>
  139. </div>
  140. </body></html>
  141. ]]

自然使用的oneinstack的包:http://mirrors.linuxeye.com/oneinstack/src/ngx_lua_waf.tar.gz

不要问我为什么,应为oneinstack非常好用。

总结

自然正在使用这款web应用防火墙,效果还是非常不错的。对于服务器安全比较看重的小伙伴们可以使用一下,不需要占用太多资源即可为网站部署一款效果显著的WEB应用防火墙,对于不像额外购买web应用防火墙的小伙伴而言是一个极佳的选择。

weinxin
公众号:网科文媒
快来关注一下,你想要的这里都有喔!! -运维笔记 -建站知识 -绿色软件 -爱听音乐 -热门电影 -校园语录 -视频教程 -OFFICES -购物联盟 -智慧服务 -运维托管 -建站指导
自然

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: