本篇文章更新時間:2022/11/23
如有資訊過時或語誤之處,歡迎使用 Contact 功能通知。
一介資男的 LINE 社群開站囉!歡迎入群聊聊~
如果本站內容對你有幫助,歡迎使用 BFX Pay 加密貨幣 或 新台幣 贊助支持。
先前筆記的 [VPS] WordPress 網站主機群防護升級的作法 、 [Nginx] 阻擋惡意請求來源(User-Agent)的方法 與 [Fail2ban] 同步 Cloudflare WAF 防火牆封鎖 IP 清單的方法 這三篇,主要都是在實作第一版 PHP WAF 網站應用程式防火牆的筆記。
而自從挖到了 CIDRAM 這款開源工具後,寫了這篇 [WordPress] 開源且強大的防火牆外掛 – CIDRAM 筆記。隨後我就開始展開第二版的「即時防護」功能開發。
畢竟第一版還沒解決分析速度,只能從 Log 瀏覽請求日誌下手,這次有方向後就花了一個禮拜給他大改版!
由於整個專案裡包含了公司的機敏內容,所以不能開源,但日後整理出一些技術細節還會再發文筆記。以下就是過程中整理的資源筆記~
架構上主要思路是:「來自機房、非普通瀏覽者的請求都給予封鎖
」
所以整理好這些機房 IP 區段的黑、白名單就是首要任務!而正巧 CIDRAM 這專案已經準備好了,再來就是先前第一版的防火牆這半年來的封鎖「功績」紀錄。
CIDRAM 的黑名單紀錄:
$cidram_list = array(
'ipv4.dat' => 'https://raw.githubusercontent.com/CIDRAM/CIDRAM/v3/vault/signatures/ipv4.dat',
'ipv4_isps.dat' => 'https://raw.githubusercontent.com/CIDRAM/CIDRAM/v3/vault/signatures/ipv4_isps.dat',
'ipv4_other.dat' => 'https://raw.githubusercontent.com/CIDRAM/CIDRAM/v3/vault/signatures/ipv4_other.dat',
'ipv6.dat' => 'https://raw.githubusercontent.com/CIDRAM/CIDRAM/v3/vault/signatures/ipv6.dat',
'ipv6_isps.dat' => 'https://raw.githubusercontent.com/CIDRAM/CIDRAM/v3/vault/signatures/ipv6_isps.dat',
'ipv6_other.dat' => 'https://raw.githubusercontent.com/CIDRAM/CIDRAM/v3/vault/signatures/ipv6_other.dat',
);
有興趣了解名單內容的可以花點時間研究這個專案!
再來是「白名單」,來自 Google / Bing / Facebook 等搜尋引擎與社群媒體爬蟲網段:
$cloudflare_list = array(
'cf_ips-v4' => 'https://www.cloudflare.com/ips-v4',
'cf_ips-v6' => 'https://www.cloudflare.com/ips-v6',
);
$goodbot_list = array(
'bingbot.json' => 'https://www.bing.com/toolbox/bingbot.json',
'goog.json' => 'https://www.gstatic.com/ipranges/goog.json',
'googlebot.json' => 'https://developers.google.com/static/search/apis/ipranges/googlebot.json',
);
看到這會想說,那 Facebook
呢? 就他最特別沒有一個公開的 IP 區段列表,只有公告這些 IP 地址時常變更,要最準的話只有從 ASN 編號去反查 AS32934
Facebook 註冊的網段。
處理 ASN 自治系統編號的網段又是另一個門路:
從 ASN 編號去查使用的企業主名稱
,最簡單是 whois AS編號
的指令方法,再來是網友開源的 Whois.php 與 php-whois PHP 版本工具以及 whois-locaweb Ruby 版本工具,還有網友直接每日程式自動更新 IP 資訊的 repo IP to ASN list。
如果想速查 ASN <-> 使用組織名稱
的關係,可以參考這份多來源整合版本的 repo AS numbers to organization names。其他資源就比較偏向「原始」一點,有些組織名稱還偏向代號,可讀性差一點,BGP 的網站查詢工具。(其他參考1, 其他參考2, 其他參考3)
如果想查 IP <-> ASN
的關係,基礎一樣可以使用 Whois 指令,直接 whois 1.1.1.1
這樣,而開發上,最快是直接使用現成的 DB 資料庫來查 IP 資訊,多來源版本 IP to location database by ASN,NodeJS 版本的 iptoasn、Rust 版本的網站查詢工具 iptoasn-webservice、 Bash 版本的查詢工具 ASN。(其他參考1, 其他參考2)
如果想查 ASN -> IP區段(prefixes)
的話,Whois 的 RADB 主機指令查詢 whois -h whois.radb.net -- '-i origin AS714'
(從 RADB 撈全部 ASN 對應網段的 Shell Script 工具 asn-ip-prefix-full-list),或使用 BGP 提供的 API https://api.bgpview.io/asn/714/prefixes
(上述兩個範例都是查詢 Apple AS714
的網段),Go 版本的查詢工具 SPK、CYMRU 網站提供的多元工具組、Shell Script 的工具 nginx-acl,直接幫你輸出成 Nginx 可以讀取的黑白名單檔案。
到這邊就差不多資源可以處理 ASN <- 組織 -> IP
這樣的關係了,所以 Facebook 的爬蟲白名單要撈到也不是問題。
下面提供目前我列出來的黑白名單:
$asn_list = array(
'deny' => array(
'9009' => 'M247',
'51167' => 'Contabo',
'141995' => 'Contabo Asia Private',
'47154' => 'HUSAM A. H. HIJAZI',
'30447' => 'Hostopia Inc. a Deluxe Company [USA]',
'207651' => 'Hosting technology',
'64286' => 'LogicWeb Inc Hosting Services',
'45544' => 'SUPERDATA',
'211632' => 'Internet Solutions & Innovations LTD',
),
'allow' => array(
'32934' => 'FB BOT',
'2635' => 'Automattic',
'3462' => 'Data Communication Business Group',
'9416' => 'Hoshin Multimedia Center Inc.',
'131596' => 'TBC',
'4780' => 'Digital United Inc.',
'17809' => 'VEE TIME CORP.',
'17421' => 'Mobile Business Group',
'18049' => 'Taiwan Infrastructure Network Technologie',
'9924' => 'Taiwan Fixed Network, Telco and Network Service Provider.',
'38841' => 'kbro CO. Ltd.',
'24163' => 'UNION BROADBAND NETWORK',
'24164' => 'UNION BROADBAND NETWORK',
'18182' => 'Sony Network Taiwan Limited',
'7482' => 'Asia Pacific On-line Service Inc.',
'131627' => 'Peicity Digital Cable Television., LTD',
'9919' => 'New Century InfoComm Tech Co., Ltd.',
'18419' => 'DaDa Broadband LTD.',
),
);
可以看得出來白名單其實主要多是國內網路提供業者 ISP,而這些還不是全部,但因為 CIDRAM 這專案有把這裡面的業者網段給封鎖,所以特別挑出來處理白名單部分。
原本還要直接從 IP 分配端的最前線來開始處理爬蟲,但後來想想也沒必要,這些雲端機房的資訊還滿公開的,可以碰一個封鎖一個。
當時處理 IP 的一些筆記也放一下:
$registries = array();
//資料源頭,包含管理局、地區(ISO 3166 2-letter country code)、ASN編號、地區、IP區段 Ref: https://ftp.ripe.net/pub/stats/ripencc/RIR-Statistics-Exchange-Format.txt
// afrinic|ZA|asn|1228|1|19910301|allocated
// afrinic|ZA|ipv4|41.56.0.0|65536|20100125|allocated
// afrinic|ZA|ipv6|2001:43f8:1300::|48|20181116|assigned
$registries['afrinic'] = 'http://ftp.afrinic.net/pub/stats/afrinic/delegated-afrinic-latest'; //Africa
$registries['apnic'] = 'https://ftp.apnic.net/stats/apnic/delegated-apnic-latest'; //Asia & Pacific
$registries['arin'] = 'https://ftp.arin.net/pub/stats/arin/delegated-arin-extended-latest'; //North America
$registries['lacnic'] = 'http://ftp.lacnic.net/pub/stats/lacnic/delegated-lacnic-latest'; //South America
$registries['ripe'] = 'https://ftp.apnic.net/stats/ripe-ncc/delegated-ripencc-latest'; //Europe
對應不同區域查詢的 Whois 主機服務清單:List of Routing Registries、IPv4 分配的狀態
然後因為爬 Whois 資料庫有些有每日的請求上限,如果需要套代理伺服器(Proxy)的話這個 Go 版本的工具 goforward 很方便處理!
到這邊也差不多告一個段落,取得黑、白名單後,就是建立資料庫,然後快速查詢請求的 IP 是否符合條件,要封鎖要放行,後面就容易多了!
我的網站伺服器環境主要是 Nginx,如果要列一份黑白名單的話,只要白名單在前,黑名單在後,就算後段黑名單有符合條件也還是會放行,就不會變成單一 IP 與 CIDR IP 區段的衝突,能夠達成「想封鎖 AWS 全網段,但又不要封鎖到我的 AWS 主機」,算是滿方便的設計。
後記
整個實作的過程中閱讀與尋找了很多資源。其實也發現有不少人跟我一樣的想法(至少從 CIDRAM 這專案開始)。
有人是直接套用 Cloudflare 的 WAF,列一份清單來處理 Hosting Companies ASN LIST,更也有人整理了一份雲端業者的清單來開源 bad-asn-list,看延伸要怎用都有自由,雖然名稱用了「bad」,但其實看說明也是能理解主要是用這些服務來亂的那些人。
我相信實作方式肯定會是因人因架構而異,像是我有些網站是在 Cloudflare CDN 背後且不同帳號管理,所以 WAF 防火牆也要去分主動被動模式,第一個請求雖然給予通過,但快速的將 IP 通報到 Cloudflare 的 WAF 就可以及時阻止第二個請求發生。
如此一來第一版本從 Log 去分析是否為攻擊請求,再搭配直接從可能的惡意名單(主機服務商)封鎖,攔截掉攻擊的可能性又更高了。