前言:最近一段時間在寫加密資料功能,對安全相關知識還是缺少積累,無意間接觸到了WAF相關知識,剛好Nginx可以實現WAF功能,也簡單學習了Lua這門語言,分享下
一、WAF產生的背景
過去企業通常會採用防火牆,作為安全保障的第一道防線;當時的防火牆只是在第三層(網路層)有效的阻斷一些資料包;而隨著web應用的功能越來越豐富的時候,Web伺服器因為其強大的計算能力,處理效能,蘊含較高的價值,成為主要的被攻擊目標(第七層應用層)。而傳統防火牆在阻止利用應用程式漏洞進行的攻擊方面,卻沒有辦法;在此背景下,WAF(Web Application Firewall)應運而生。
二、什麼是WAF
Web 應用防火牆 (WAF-Web Application Firewall) 旨在保護 Web 應用免受各類應用層攻擊,例如跨站點指令碼 (XSS)、SQL 注入,以及 cookie 中毒等。應用是您重要資料的閘道器,因此針對應用發起的攻擊就成為了造成漏洞的主要原因。有了 WAF 就可以攔截一系列企圖通過入侵系統來洩漏資料的攻擊。
三、工作原理
1.使用者通過瀏覽器向Web伺服器傳送網頁請求。
2.使用者的請求到達Web伺服器之前,WAF對使用者的請求進行過濾
3.WAF拿到使用者的HTTP請求引數去跟配置檔案定義的規則做比較(比如ip黑名單),如果匹配上就返回403拒絕,否則就放行。
4.WEB伺服器響應使用者請求,把頁面資料返回給使用者。
四、WAF作用
五、WAF和傳統防火牆的區別
1.傳統防火牆是工作在網路層(第三層)和傳輸層(第四層)
2.WAF是工作在應用層(第七層)
3.傳統防火牆更多是對IP和埠進行過濾
4.WAF是對HTTP請求進行過濾,包括URL,IP,User-Agent等等
六、WAF和DDos
DDos的全稱是Distributed Denial of service。主要依靠一組計算機來發起對一個單一的目標系統的請求,從而造成目標系統資源耗盡而拒絕正常的請求。
根據OSI網路模型,最常見的DDos有三類,第三層(網路層)DDos、第四層(傳輸層)DDos和第七層(應用層)DDos。
-
支援IP白名單和黑名單功能,直接將黑名單的IP訪問拒絕(新增cdip功能支援ip段)
-
支援URL白名單,將不需要過濾的URL進行定義
-
支援User-Agent的過濾,匹配自定義規則中的條目,然後進行處理
-
支援CC攻擊防護,單個URL指定時間的訪問次數,超過設定值(新增針對不同域名)
-
支援Cookie過濾,匹配自定義規則中的條目,然後進行處理
-
支援URL過濾,匹配自定義規則中的條目,如果使用者請求的URL包含這些
-
支援URL引數過濾,原理同上
-
支援日誌記錄,將所有拒絕的操作,記錄到日誌中去
-
新增支援拉黑快取(預設600秒)
八、Nginx Waf防護流程
if whiteip() then elseif blockip() then elseif denycc() then elseif ngx.var.http_Acunetix_Aspect then ngx.exit(444) elseif ngx.var.http_X_Scan_Memo then ngx.exit(444) elseif whiteurl() then elseif ua() then elseif url() then elseif args() then elseif cookie() then elseif PostCheck then
-
-
檢查IP黑名單,不通過即拒絕;
-
檢查CC攻擊,匹配即拒絕
-
檢查http_Acunetix_Aspect掃描是否開啟
-
檢查http_X_Scan_Memo掃描是否開啟
-
檢查白名單URL檢查;
-
檢查UA,UA不通過即拒絕;
-
檢查URL引數檢查;
-
檢查cookie;
-
檢查post;
九、基於Nginx實現的WAF
9.1安裝依賴包
yum -y install gcc gcc-c++ autoconf automake make unzip yum -y install zlib zlib-devel openssl openssl-devel pcre pcre-devel
9.2安裝LuaJIT2.0
LuaJIT是Lua的即時編譯器,簡單來說,LuaJIT是一個高效的Lua虛擬機器。
# 進入目錄 cd /usr/local/src/ # 下載LuaJIT2.0 wget http://luajit.org/download/LuaJIT-2.0.5.tar.gz # 解壓 tar xf LuaJIT-2.0.5.tar.gz && cd LuaJIT-2.0.5 # 編譯 make # 安裝 make install PREFIX=/usr/local/lj2 # 建立軟連線 ln -s /usr/local/lj2/lib/libluajit-5.1.so.2 /lib64/ # 新增環境變數 export LUAJIT_LIB=/usr/local/lj2/lib/ export LUAJIT_INC=/usr/local/lj2/include/luajit-2.0/
9.3安裝ngx_devel_kit
kit模組是一個擴充nginx伺服器核心功能的模組,第三方模組開發可以基於它來快速實現。
# 進入目錄 cd /user/local/src/ # 下載v0.3.0.tar.gz wget https://github.com/simplresty/ngx_devel_kit/archive/v0.3.0.tar.gz -O ngx_devel_kit.tar.gz # 解壓 tar xf ngx_devel_kit.tar.gz
9.4安裝lua-nginx-module
ngx_lua_module 是一個nginx http模組,它把 lua 解析器內嵌到 nginx,用來解析並執行lua 語言編寫的網頁後臺指令碼。
ngx_lua模組的原理
1. 每個worker(工作程式)建立一個Lua VM,worker內所有協程共享VM; 2. 將Nginx I/O原語封裝後注入 Lua VM,允許Lua程式碼直接訪問; 3. 每個外部請求都由一個Lua協程處理,協程之間資料隔離; 4. Lua程式碼呼叫I/O操作等非同步介面時,會掛起當前協程(並保護上下文資料),而不阻塞worker; 5. I/O等非同步操作完成時還原相關協程上下文資料,並繼續執行
安裝
# 進入目錄 cd /user/local/src/ # 下載v0.10.9rc7.tar.gz wget https://github.com/openresty/lua-nginx-module/archive/v0.10.9rc7.tar.gz # 解壓 tar -xzvf v0.10.9rc7.tar.gz
9.5安裝Nginx
# 進入目錄 cd /user/local/src/ # 下載 wget http://nginx.org/download/nginx-1.21.0.tar.gz # 解壓 tar xf nginx-1.21.0.tar.gz # 進入nginx目錄 cd nginx-1.21.0 # 編譯 ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_flv_module --with-http_stub_status_module --with-http_gzip_static_module --with-http_realip_module --with-pcre --add-module=/usr/local/src/lua-nginx-module-0.10.9rc7 --add-module=/usr/local/src/ngx_devel_kit-0.3.0 --with-stream # 安裝 make && make install # 新增nginx配置,在server塊裡新增下面內容 [root@localhost_test_192.168.10.132 11:04:48 ~]# vim /usr/local/nginx/conf/nginx.conf location /lua { default_type 'text/plain'; content_by_lua 'ngx.say("hello, lua")'; } # 檢查語法 [root@localhost_test_192.168.10.132 09:59:33 /usr/local/src]# nginx -t nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful # 啟動 [root@localhost_test_192.168.10.132 11:08:35 ~]# nginx # 測試 curl 127.0.0.1:80/lua
9.6安裝ngx_lua_waf
# 進入目錄 cd /user/local/src/ # 把ngx_lua_waf下載到conf目錄下 wget https://github.com/loveshell/ngx_lua_waf/archive/master.zip # 解壓命名為waf unzip master.zip -d /usr/local/nginx/conf/ # 更改目錄名 mv /usr/local/nginx/conf/ngx_lua_waf-master /usr/local/nginx/conf/waf # 在nginx.conf的http段新增 lua_package_path "/usr/local/nginx/conf/waf/?.lua"; lua_shared_dict limit 10m; init_by_lua_file /usr/local/nginx/conf/waf/init.lua; access_by_lua_file /usr/local/nginx/conf/waf/waf.lua; # 在nginx.conf最外層新增使用者執行 user www; # 建立日誌目錄 mkdir /usr/local/nginx/logs/hack chown www /usr/local/nginx/logs/hack # Lua_waf 配置 [root@localhost_test_192.168.10.132 11:33:53 /usr/local/nginx/conf/waf]# cat config.lua # 規則存放路徑 RulePath = "/usr/local/nginx/conf/waf/wafconf/" # 是否開啟攻擊資訊記錄,需要配置logdir attacklog = "on" # log儲存目錄,該目錄需要使用者自己新建,切需要nginx使用者的可寫許可權 logdir = "/usr/local/nginx/logs/hack/" # 是否攔截url訪問 UrlDeny="on" # 是否攔截後重定向 Redirect="on" # 是否攔截cookie攻擊 CookieMatch="on" # 是否攔截post攻擊 postMatch="on" # 是否開啟URL白名單 whiteModule="on" # 填寫不允許上傳檔案字尾型別 black_fileExt={"php","jsp"} # ip白名單,多個ip用逗號分隔 ipWhitelist={"127.0.0.1"} # ip黑名單,多個ip用逗號分隔 ipBlocklist={"192.168.10.1"} # 是否開啟攔截cc攻擊(需要nginx.conf的http段增加lua_shared_dict limit 10m;) CCDeny="off" # 設定cc攻擊頻率,單位為秒. # 預設1分鐘同一個IP只能請求同一個地址100次 CCrate="100/60" # 告警內容 html= [] # 規則檔案 [root@localhost_test_192.168.10.132 11:42:12 /usr/local/nginx/conf/waf]# ll wafconf/ total 24 -rw-r--r-- 1 root root 749 Apr 6 2016 args -rw-r--r-- 1 root root 652 Apr 6 2016 cookie -rw-r--r-- 1 root root 733 Apr 6 2016 post -rw-r--r-- 1 root root 335 Apr 6 2016 url -rw-r--r-- 1 root root 177 Apr 6 2016 user-agent -rw-r--r-- 1 root root 8 Apr 6 2016 whiteurl args裡面的規則get引數進行過濾的 cookie是對請求過濾的cookie過濾 url是隻在get請求url過濾的規則 post是隻在post請求過濾的規則 whiteurl是白名單,裡面的url匹配到不做過濾 user-agent是對user-agent的過濾規則 # 載入Nginx [root@localhost_test_192.168.10.132 11:32:41]# nginx -s reload
9.7測試效果
訪問帶有引數的URL
http://192.168.10.132/?id=<script>
總結:Nginx使用Lua模組實現WAF的功能很強大,可以對程式碼進行修改二次開發,修改成為自己想要的效果,不妨試試看看