1. 介紹
自從了解了error和access日志的重要性,并且學會閱讀相關log文檔之后。
通過調整nginx配置,解決error中的大量報錯提示。通過過濾js等靜態資源減少大量的access日志記錄內容。
同時,經過使用阿里云安全組封禁大量國外ip地址的訪問。我的access.log文件和error.log的尺寸得到了有效壓縮管理。
access.log 從原先的12m左右的的文件,變成了現在的400KB。記錄的訪問數據也清晰了很多。
error.log也從原先的8M左右的文件,變成了現在的1KB,或者300Bytes的文件。甚至有時候還是0 Bytes。
日志文件的減少,也降低了服務器的IO讀取的性能開支??梢詫⒏嗟膬却尜Y源用于處理正常的請求。
可以說是一個雙贏的結局。
本篇作為一個回顧總結內容。具體的error文件內容配置可以參考:https://zinyan.com/?p=450 ,https://zinyan.com/?p=453。access.log的文件配置可以參考:https://zinyan.com/?p=445,https://zinyan.com/?p=444,以及爬蟲屏蔽過濾返回444:https://zinyan.com/?p=454
2. 總結
現在error文件中,剩下的記錄主要就是SSL: error:141CF06C:SSL routines:tls_parse_ctos_key_share:bad key share異常了。
處理這個異常,可以通過封禁ip地址的訪問,也可以不用在意。
剩下的就是access.log文件了。
當我們配置UserAgent?請求中帶有爬蟲關鍵字的請求直接返回444之后,例如:
Status:444,Bytes:0,IP:185.117.225.171,Time:[2022-11-24T04:18:36+08:00],Host:"zinyan.com",Request:"GET /robots.txt HTTP/1.1",Referer:"-",UserAgent:"python-requests/2.28.1"
Status:444,Bytes:0,IP:51.77.247.119,Time:[2022-11-24T04:57:39+08:00],Host:"47.101.47.241",Request:"POST /phpinfo HTTP/1.1",Referer:"-",UserAgent:"curl/7.64.0"
對比不同日期的access.log 可以發現,爬蟲請的數量在不斷變少。
因為當爬蟲多次請求得到結果是444后,會漸漸降低我們網站的爬取級別,最終猶豫得不到數據而放棄爬取。
但是,也會有一些新增加的爬蟲需要我們注意,并添加到過濾條件中。
而且也有一些過濾無法生效的情況,需要我們隨時進行一些配置的修改例如:
Status:404,Bytes:177,IP:18.195.96.149,Time:[2022-11-24T04:58:10+08:00],Host:"zinyan.com",Request:"GET /s/.git/HEAD HTTP/1.1",Referer:"-",UserAgent:"RepoLookoutBot/1.0.0 (abuse reports to abuse@repo-lookout.org)"Status:404,Bytes:186,IP:18.195.96.149,Time:[2022-11-24T04:58:42+08:00],Host:"zinyan.com",Request:"GET /categories/.git/HEAD HTTP/1.1",Referer:"-",UserAgent:"RepoLookoutBot/1.0.0 (abuse reports to abuse@repo-lookout.org)"
我們需要新增:RepoLookoutBot 爬蟲工具的過濾。還有通過CensysInspect 工具:
Status:400,Bytes:248,IP:167.248.133.62,Time:[2022-11-24T07:17:24+08:00],Host:"47.101.47.241:443",Request:"GET / HTTP/1.1",Referer:"-",UserAgent:"Mozilla/5.0 (compatible; CensysInspect/1.1; +https://about.censys.io/)"
同時在屏蔽過程中出現了有些能夠屏蔽而有些無法屏蔽的問題:
Status:444,Bytes:0,IP:167.248.133.62,Time:[2022-11-24T07:17:20+08:00],Host:"47.101.47.241:443",Request:"GET / HTTP/1.1",Referer:"-",UserAgent:"-"
Status:400,Bytes:248,IP:167.248.133.62,Time:[2022-11-24T07:17:23+08:00],Host:"47.101.47.241:443",Request:"GET / HTTP/1.1",Referer:"-",UserAgent:"-"
兩種訪問從access.log中看到,可以說完全一樣。但是卻一個返回444,一個返回400 。返回444說明我的nginx過濾規則生效了。而400說明沒有生效。
同時,還需要添加上Host為空的訪問,將它們進行過濾,例如:
Status:400,Bytes:150,IP:167.248.133.62,Time:[2022-11-24T07:17:24+08:00],Host:"-",Request:"PRI * HTTP/2.0",Referer:"-",UserAgent:"-"
同時,我們也可以檢查靜態資源是否全部都過濾的情況,例如我的資源用到了jfif,webp文件。我就需要添加到過濾規則中去。
PS:可能存在部分的過濾失敗,但是整體上來說。提高了網站的安全性,降低了大量的非法請求。
在收獲上來說,這一些配置的付出是值得的。
3. 改進 nginx過濾規則
基于發現的問題,再次改進access的過濾規則。以及非法請求返回444的判斷邏輯。
3.1 修改access_log 記錄
在/etc/nginx/nginx.conf文件中修改如下:
http {
...
log_format main 'Status:$status,Bytes:$body_bytes_sent,IP:$remote_addr,Time:[$time_iso8601],Host:"$http_host",Request:"$request",Referer:"$http_referer",UserAgent:"$http_user_agent"';
map $uri $zinyanloggable {
default 1;
~^(.*\.(ico|gif|jpg|jpeg|png|bmp|swf|js|css|svg|woff|ttf|jfif|webp)$) 0;
}
access_log /var/log/nginx/access.log main if=$zinyanloggable;
...
}
這樣,access文件中就不會添加ico|gif|jpg|jpeg|png|bmp|swf|js|css|svg|woff|ttf|jfif|webp 作為后綴結尾的日志內容了。
3.2 map實現爬蟲屏蔽
老版本寫法為:
server{
...
if ($http_user_agent ~ ^$){
return 444;
}
if ($http_user_agent ~* "scrapy|python|curl|java|wget|httpclient|okhttp|MJ12bot|Expanse|ahrefsbot|seznambot|serpstatbot|sindresorhus|zgrab"){
return 444;
}
...
}
效率比較低,如果是多個server那么得寫多遍。所以修改為map的規則進行
但是如果改為map的話,需要在http{}之中先創建map規則,然后再到server中使用就可以了。示例如下:
http {
...
# 創建一個屏蔽規則zinyanUA,而它的取值從$http_user_agent 中獲取。
map $http_user_agent $zinyanUA {
default 0;
~*(scrapy|python|curl|java|wget|httpclient|okhttp|MJ12bot|Expanse|ahrefsbot|seznambot|serpstatbot|sindresorhus|zgrab|censys|RepoLookoutBot) 1;
~ ^$ 1;
}
...
}
語法解釋:
- ~ 表示正則表達式對大小寫敏感。
- ~* 表示正則表達式對大小寫不敏感。
- 后面跟著的內容就是正則表達式了
- 在正則表達式中^?代表開頭,$?代表結尾,^$就代表開頭和結尾中間沒有字符。也就是字符串為空的。
配置完畢后,在需要的server{}段中添加:
server{
...
if ($zinyanUA){
return 444;
}
...
}
因為在nginx 的if判斷中,參數值0或者為空字符串,會判斷為false,其他判斷為true。
而我在上面創建的map對象中,規范了,如果匹配就返回1,不匹配返回0。所以if ($zinyanUA)?為true的就是需要返回444的請求了。
nginx: [emerg] unknown directive "if($http_host)" in /etc/nginx/conf.d/zinyan.conf:49nginx: configuration file /etc/nginx/nginx.conf test failed
如果你出現了這個if命名錯誤的提示,并不是所謂的缺乏if命名的依賴庫,而是Nginx中的if命名和括號中間需要有空格。
nginx -t? 檢測通過后,通過service nginx reload刷新配置就可以生效了。
PS:如果實在過濾不了的,建議直接封IP地址,特別是國外的訪問。國內也有不少的攻擊