超輕量級反爬蟲方案

roukei 8年前發布 | 13K 次閱讀 Linux命令 Nginx iptables 網絡爬蟲

前言

爬蟲和反爬蟲日益成為每家公司的標配系統。爬蟲在 情報獲取、虛假流量、動態定價、惡意攻擊、薅羊毛 等方面都能起到很關鍵的作用,所以每家公司都或多或少的需要開發一些爬蟲程序,業界在這方面的成熟的方案也非常多;有矛就有盾,每家公司也相應的需要反爬 蟲系統來達到數據保護、系統穩定性保障、競爭優勢保持的目的。

然而,一方面防守這事ROI不好體現,另一方面反爬蟲這種系統,相對簡單的爬蟲來說難度和復雜度都要高很多,往往需要一整套大數據解決方案才能把事情做好,因此只有少量的公司可以玩轉起來。當出現問題的時候,很多公司往往束手無策。

本文將描述一種盡量簡單的反爬蟲方案,可以 在十幾分鐘內解決部分簡單的爬蟲問題,緩解惡意攻擊或者是系統超負荷運行的狀況 ;至于復雜的爬蟲以及更精準的防御 , 需要另外討論。

整套方案會盡量簡單易懂,不會涉及到專門的程序開發,同時盡量利用現有的組件,避免額外組件的引入。內容上主要分為三大部分:

·訪問數據獲取。采集用戶的訪問數據,用來做爬蟲分析的數據源

·爬蟲封禁。當找到爬蟲后,想辦法去阻斷它后續的訪問

·爬蟲分析。示例通過簡單策略來分析出爬蟲

簡單的數據獲取

數據獲取是做好反爬蟲系統的關鍵,常見的幾種模式

方案 優點 缺點 成本
應用內部埋點吐數據 最精確的數據,可以實現業務相關數據的分析 開發成本高 極高
中間件吐數據 精確的數據,部分業務相關的數據分析 開發成本較高 較高
訪問日志(nginx/apache) 配置簡單,開源的現成方案較多 只能取到部分數據
全流量鏡像和分析(最佳) 最精確的數據,可以實現業務相關的分析,同時旁路系統,不影響生產 技術難度和開發成本高 較高

本篇,采用nginx的日志方式,這種只需要通過對常見的nginx最簡單的配置就能從遠程獲取相應的訪問日志

官方nginx配置:

log_format warden '" "$remote_addr" "$remote_port" "$server_addr" "$server_port" "$request_length" "$content_length" "$body_bytes_sent" "$request_uri" "$host" "$http_user_agent" "$status" "$http_cookie" "$request_method" "$http_referer" "$http_x_forwarded_for" "$request_time" "$sent_http_set_cookie" "$content_type" "$upstream_http_content_type" "$request_body"\n';

access_log syslog:server=127.0.0.1:9514 warden ;

tengine配置( 編譯時帶上 –with-syslog )

log_format warden '" "$remote_addr" "$remote_port" "$server_addr" "$server_port" "$request_length" "$content_length" "$body_bytes_sent" "$request_uri" "$host" "$http_user_agent" "$status" "$http_cookie" "$request_method" "$http_referer" "$http_x_forwarded_for" "$request_time" "$sent_http_set_cookie" "$content_type" "$upstream_http_content_type" "$request_body"\n';

access_log syslog:user::127.0.0.1:9514 warden ;

這里面需要注意的是:

由于較老的nginx官方版本不支持syslog,所以tengine在這塊功能上做了單獨的開發(需要通過編譯選項來啟用),在不確定的情況下,請修改配置 文件后先使用(nginx -t)來測試一下,如果不通過,需要重新在configure時加上syslog選項,并編譯。

盡量獲取了跟爬蟲相關的數據字段,如果有定制的http header,可以自行加上

采用udp方式來發送syslog,可以將訪問日志發送給遠端分析服務,同時udp的方式保證nginx本身不會受到影響

訪問日志拿不到響應的具體內容(nginx有辦法搞定,但有代價),無法支持業務相關的防護

簡單的爬蟲封禁

反爬蟲最后的生效,需要靠合理的封禁模式,這里比較幾種模式:

本段將介紹基于iptables的方案,雖然適用范圍較小;但是依賴少,可以通過簡單配置linux就能達到效果。

第一步

安裝ipset。ipset擴充了iptables的基本功能,可以提供更加高效的訪問控制

# centos 6.5上面安裝非常簡單
sudoyuminstall -y ipset

第二步

在iptables中建立相應的ipset,來進行訪問權限的封禁

# 新增用于封禁的ipset
sudo ipset -N --exist warden_blacklist iphash

# 增加相應的iptables規則
sudo iptables -A INPUT -m set --set warden_blacklist src -j DROP

# 保存iptables
sudo service iptables save

第三步

獲取當前封禁的ip黑名單,并導入到iptables里面去

sudoipset --exist destroy warden_blacklist_tmp;sudoipset -N warden_blacklist_tmp iphash;echo"1.1.1.1,2.2.2.2"|tr,"\n"|xargs-n 1 -I {}sudoipset -A warden_blacklist_tmp {} ;sudoipset swap warden_blacklist_tmp warden_blacklist

這里為了盡可能的提升效率,作了以下事情:

l建立臨時ipset,方便做操作

l將當前封禁黑名單中的ip提取出來,加入到此ipset(示例中用了最簡單的echo來展示,實際可相應調整)

l將ipset通過原子操作與iptables正在使用的ipset作交換,以最小的代價將最新的黑名單生效

簡單的爬蟲策略

要能精確的分析爬蟲,需要強大的數據分析平臺和規則引擎,來分析這個IP/設備/用戶分別在短時間區間/長時間范圍里的行為特征和軌跡,這里涉及到了非常復雜的數據系統開發,本文將通過簡單的shell腳本描述比較簡單的規則

例子 1

封禁最近100000條中訪問量超過5000的ip

nc -ul 9514 |head-100000 |awk-F'" "''{print $2}'|sort|uniq-c |sort-nr |awk'$1>=5000 {print $2}'

這里面:

1.udp服務監聽nginx發過來的syslog消息,并取10000條,找到其中每條訪問記錄的ip

2.通過sort 和uniq來獲取每個ip出現的次數,并進行降序排列

3.再通過awk找到其中超過閾值的ip,這就得到了我們所需要的結果。

例子 2

封禁最近100000條中user agent明顯是程序的ip

nc -ul 9514 |head-100000 |awk-F'" "''$10 ~ /java|feedly|universalfeedparser|apachebench|microsoft url control|python-urllib|httpclient/ {print $2}'|uniq

這里面:

1.通過awk的正則來過濾出問題agent,并將相應ip輸出

2.關于agent的正則表達式列出了部分,可以根據實際情況去調整和積累

當然,這里只是列舉了簡單的例子,有很多的不足之處

1.由于只采用了shell,規則比較簡單,可以通過擴展awk或者其他語言的方式來實現更復雜的規則

2.統計的窗口是每100000條,這種統計窗口比較粗糙,好的統計方式需要在每條實時數據收到是對過去的一小段時間(例如5分鐘)重新做統計計算

3.不夠實時,無法實時的應對攻擊行為;生產環境中,需要毫秒級的響應來應對高級爬蟲

4…….

拼起來

所有模塊組合起來,做一個完整的例子。假設:

1.負載均衡192.168.1.1,使用了官方nginx,并配置了syslog發往192.168.1.2

2.192.168.1.2啟動nc server,每隔一段時間進行分析,找出問題ip,并吐給192.168.1.1

3.192.168.1.1通過iptables進行阻攔,數據來源于192.168.1.2的分析機器

除了nginx配置和iptables基本配置,前幾段的配置略作改動:

### nginx conf@192.168.1.1
log_format warden '" "$remote_addr" "$remote_port" "$server_addr" "$server_port" "$request_length" "$content_length" "$body_bytes_sent" "$request_uri" "$host" "$http_user_agent" "$status" "$http_cookie" "$request_method" "$http_referer" "$http_x_forwarded_for" "$request_time" "$sent_http_set_cookie" "$content_type" "$upstream_http_content_type" "$request_body"\n';
access_log syslog:server=192.168.1.2:9514 warden ;

### 分析@192.168.1.2, 增加了結果會吐,同時每隔60分鐘跑一次,把數據返回給192.168.1.1
while true ; do nc -ul 9514 | head -100000 | awk -F '" "' '{print $2}' | sort | uniq -c | sort -nr | awk '$1>=5000 {print $2}' | tr '\n' ',' | awk '{print $0}' | socat - UDP:192.168.1.1:9515  ; sleep 3600 ; done

### 阻斷@192.168.1.1
#基礎配置
sudo ipset -N --exist warden_blacklist iphash
sudo iptables -A INPUT -m set --set warden_blacklist src -j DROP
sudo service iptables save

#動態接收并更新iptables
while true ; do sudo ipset --exist destroy warden_blacklist_tmp; sudo ipset -N warden_blacklist_tmp iphash; socat UDP-LISTEN:9515 - | tr , "\n" | xargs -n 1 -I {} sudo ipset -A warden_blacklist_tmp {} ;sudo ipset swap warden_blacklist_tmp warden_blacklist ; sudo ipset list ; done

以上只是簡單示例,實際中還是建議換成shell腳本

總結

本文列出一種簡單的反爬蟲方案,由于過于簡單,可以當做 概念示例或者是救急方案 ,如果需要進一步深化,需要在以下方面去 加強

1.強化數據源,可以通過流量獲得全量數據。目前爬蟲等網絡攻擊逐漸轉向業務密切相關的部分,往錢的方向靠近,所以需要更多的業務數據去支撐,而不僅僅是訪問日志

2.更靈活的阻斷,需要有多種阻斷手段和略復雜的阻斷邏輯

3.除卻ip,還需要考察用戶、設備指紋等多種追蹤方式,應對移動環境和ipv6環境下,“IP”這一信息的力不從心

4.強化規則引擎和模型,需要考察更多用戶行為的特征,僅僅從頻率等手段只等應對傻爬蟲,同時會造成誤殺率更高

5.建立數據存儲、溯源、統計體系,方便分析人員去分析數據并建立新的模型和規則。反爬蟲是一件持續性行為,需要良好的平臺來支撐。

6.可以根據實際需要去做好反爬蟲系統的集成。比如nginx數據–>反爬系統–>nginx阻斷;F5數據–>反爬系統–>F5阻斷

 

 

來自:http://www.freebuf.com/articles/web/115960.html

 

 本文由用戶 roukei 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!