摘要#
隨著互聯網技術的快速發展,信息傳播的速度和範圍大幅提升。社交媒體、博客、視頻平台等新興媒介使得個人和團體能夠輕鬆地分享觀點和信息。這種信息的自由流動促進了公眾參與、社會運動和民主化進程。然而,網絡的開放性也帶來了信息控制的挑戰。許多國家和地區的政府出於維護國家安全、社會穩定和政治控制的考量,逐漸加強了對網絡內容的審查。這種審查制度通常表現為對特定網站的封鎖、對社交媒體內容的監控以及對言論的限制。
本文將對兩種常見的封鎖技術進行原理說明,並提供檢測思路:DNS 緩存投毒和SNI 阻斷。此外,我們還將提供相應的 PoC(概念驗證)工具,以便更方便地檢測您的網絡和目標域名是否受到這兩種封鎖方式的影響。需要注意的是,所提供的方法尚未經過廣泛測試,因此在某些使用這些審查技術的國家或地區可能有效,但在其他國家或地區則可能無法正常工作。
本文不討論繞過封鎖技術的方法,也不討論其他未被提到的封鎖和審查手段。對於 DNS 緩存投毒的討論僅限於基於 UDP 的 DNS 協議,基於 TCP 的 DNS 可以自行去實驗。
本文的檢測方法不需要實驗者部署額外的伺服器,是一種原理檢測的方法。
名詞解釋#
域名(Domain Name): 域名是一個易於記憶的字符串,用於標識互聯網上的一個特定位置或資源。域名的存在是為了解決 IP 地址不便於記憶的問題。例如:www.fubao.dev 就是一個域名。
DNS(Domain Name System):域名系統。目標域名的訪問實際上最終使用的依然是 IP,這個系統相當於一個號碼簿,通過姓名可以查到電話號碼,通過域名系統可以通過域名查詢到 IP 地址,例如 www.fubao.dev 對應的 IP 地址為 34.41.105.151
SNI(Server Name Indication):伺服器名稱指示(SNI)是 TLS 協議的一個擴展。在握手過程開始時,客戶端會告知所連接的伺服器目標主機名稱。這使得伺服器能夠在同一 IP 地址和 TCP 端口上呈現多個證書,從而支持在同一 IP 地址上提供多個安全(HTTPS)網站或其他基於 TLS 的服務,而無需所有站點使用相同的證書。
簡單來說,一個 IP 地址可以部署多個域名。當通過 HTTPS 訪問時,若需驗證證書的合法性,客戶端必須通過 SNI 告知伺服器應提供哪個域名的證書,以確保握手過程順利進行。雖然伺服器可能只關注 HTTP 層面的 Host 信息,但為了兼容性,通常會在握手時發送 SNI 信息。
SNI 信息分為兩類:一種是明文 SNI 信息,這種方式最為常見且兼容性較好;另一種是加密的 SNI(ESNI),但本文不討論 ESNI。
DPI(Deep Packet Inspection):深度包檢測技術,是一種網絡數據包過濾技術,旨在分析通過檢測點的數據包內容,包括其數據部分和可能的標頭。該技術用於識別不符合規範的協議、病毒、垃圾郵件和入侵行為。通過預設的標準,DPI 可以決定數據包是否允許通過,或將其路由至其他目的地。此外,DPI 還可用於收集網絡流量的統計數據,用於監控和定向投送廣告。例如,對於一些 DPI 系統,SNI 信息和 DNS 查詢的目標信息就是需要收集和關注的信息。
通常對於網絡封鎖技術來說,DPI 系統還需要與一些能執行具體封鎖動作的服務進行交互。大型的 DPI 系統及其執行單元為了不影響正常網絡,一般採用鏡像流量並旁路部署的方式,通過注入特定的包達到阻止通信的目的。這種系統一般被稱為包注入器。
DNS 污染:DPI 檢測到對封鎖域名的查詢後,通過包注入器搶答 DNS 響應。因為 DPI 設備離查詢方更近,注入包會先到達;對於某些先進的 DPI 及動作系統,可能還會丟棄後續到達的正確的響應包。
SNI 阻斷:DPI 檢測到對目標域名 HTTPS 請求中包含需要封鎖域名的 SNI 信息後,注入 TCP RST 包,斷掉請求方和目標的連接。對於一些專業的 DPI 系統,這個 RST 阻斷包大多數都是雙向的,即告訴客戶端,伺服端與你主動斷開了連接,也告訴伺服端,客戶端與你主動斷開了連接,保證一些簡單丟棄 RST 包繞過封鎖的手段不生效。
審查殘留:對於某些 DPI 系統來說,基於應用層和其他層的封鎖邏輯可能會發生聯動。舉例來說,如果你使用特定 IP 和 SNI 訪問了目標網站,下次在連接此 IP 時,握手包可能會被丟棄,通常這種用於丟棄包的系統不是旁路部署;審查殘留對研究一些 DPI 系統的工作方式提供了方便,也帶來了一些不便,本文會提及,但不會做大面積討論。
漁:DPI 和包注入器的常見弱點#
對於大規模數據場景下的 DPI 和包注入系統來說,吞吐量和處理能力是其重要的指標。為了在成本和效果之間做平衡,DPI 系統和包注入器通常都具有以下缺陷:
-
對目標協議棧的實現通常都是輕量的,是完整協議棧的一個最小可用子集,通常不會完全滿足 RFC 實現,這是出於成本的考量。例如,用於 TCP 的 DPI 系統並不會校驗 TCP 包的 checksum 值是否合法;
-
DPI 和包注入器為旁路部署,只能看到經過他們的包,收集的信息不完整。例如,DPI 系統無法知道離目標還有多少跳,因此很容易受到欺騙。例如,如果發送剛好能夠經過 DPI 和包注入器而到達不了目標的 TTL 值的包,DPI 和包注入器也會開始工作;雖然很多 DPI 和包注入器會假設和目標的跳數,但是這種假設是不能覆蓋精心構造的 TTL 值的包
-
DPI 可能會重組被 TCP 等流式傳輸的協議的數據流,但是都存在一個等待時間的限制。
-
etc
DNS 污染的識別#
通常 DNS 污染識別的方法是和正確的結果進行對比,但是這種方法不具有通用性,由於 ECS 和 CDN 技術的存在,DNS 伺服器可能會返回離請求方最近的伺服器 IP 信息,以此來保證最佳的訪問體驗,目標服務可能會在不同的區域和國家使用不同供應商的服務,這種檢測方法可能會造成大量的假陽性。
結合 DPI 系統的常見弱點,因為 DPI 系統不關心請求是否合法,我們可以構造這樣一個非法的 DNS 查詢,這個查詢請求中告訴 DNS 伺服器,我們的查詢請求中包含查詢結果。
正常的 DNS 查詢如下圖:
我們構造的非法查詢,修改了如圖圈出的部分:
非法查詢如果未被搶答(也就是沒被污染),我們看到的結果是 DNS 伺服器報錯:
非法查詢被搶答(也就是 DNS 被污染),我們看到的響應是正常的的響應結果:
PoC: dns_pollution.py
使用示例:
SNI 阻斷的檢測#
SNI 阻斷的檢測我們要排除 DNS 污染的影響。由於 DPI 系統通常使用的信息有限,我們使用一些確保一定可以訪問的出境 IP 地址,發送帶 SNI 的請求,看是否收到 RST 包即可,無需完整完成 HTTPS 握手。
PoC:sni_block.py
使用示例:
總結#
根據以上思路,檢測的方法還有很多變種,祝大家玩得愉快。