
作為一名 Web 開發工程師,天天都會和網路打交道,Charles 作為一款網路抓包工具,幾乎成了 Web 開發的標配,
本文是我深度使用 Charles 后總結而成,不同于其它介紹 Charles 的文章,這篇文章不會詳細介紹 Charles 的各個功能(例如 remote 和 rewrite),而是專注于分析一個問題:什么情況下 Charles 會抓包失敗?
為了解決這個問題,我會從 Charles 的原理分析,并且結合 Android/iOS 的官方政策,一一分析 Charles 抓包中的那些失效問題,看完后如果你覺得有用,一定要記得給我點贊 ??,謝謝你,這對我真的很重要!
一、Charles 抓包原理
市面上絕大多數的抓包軟體,背后的原理都是中間人攻擊(Man-in-the-middle attack,縮寫:MITM),
維基百科是這樣定義 MITM 的:
“中間人攻擊在密碼學和計算機安全領域中是指攻擊者與通訊的兩端分別建立獨立的聯系,并交換其所收到的資料,使通訊的兩端認為他們正在通過一個私密的連接與對方直接對話,但事實上整個會話都被攻擊者完全控制,
上面的定義寫的很清晰,我結合 Charles 畫了一個圖,結合箭頭方向就能看懂 HTTP Packets 的流向:

只看理論有些干,我們可以用個實體看一下 Charles 內部的作業情況,我在電腦瀏覽器上訪問 cdn.staticfile.org 的一個 HTTP 資源,具體的網路報文我用 Wireshark 抓了一下:

結合 Wireshark 的抓包報文和 Charles 的網路分析,我們可以看出這個 HTTP 請求的報文流向:
瀏覽器(Client)從埠號
56075發起一個請求,請求發送到本地 Charles 監聽的8888埠(MITM Server),這個連接直接在本機進行收到瀏覽器的請求后,Charles 再從埠號
56076(MITM Client)發起一個新的請求,因為這個網路包要入公網,所以 IP 為192.168.31.44(我的電腦 IP 地址,下節會介紹);cdn.staticfile.org(Server)的 IP 為111.63.183.223,因為是 HTTP 請求,所以埠號為80111.63.183.223:80回傳一個 HTTP 回應到 Charles 的代理客戶端192.168.31.44:56076Charles 內部做了一些處理(Capture & Analysis),然后把回應報文通過
8888埠發送到127.0.0.1:56075,到這里瀏覽器就收到了回應
在第二步和第三步中,報文經過了 Charles,Charles 這時就可以對報文進行一些加工,例如 Remote 重定向,Rewrite,快取報文并可視化等操作,
二、Charles 抓包配置
為了文章的連續性,這里我會對 Charles 的抓包代理配置進行簡單的說明,如果你對這里很熟悉可以選擇跳過,不太熟悉可以把文章收藏方便后續檢索查閱,
開始配置前我們先回顧一下基礎的網路知識,網路資料如果想從 A 傳輸到 B,想確定一個連接就必須確定 5 個關鍵資訊:源 IP 地址,源埠,傳輸層協議,目的 IP 地址和目的埠,這 5 個關鍵資訊又叫五元組,一個五元組就可以確定一個連接,

如果用 Charles 抓包,我們就要對照分析一下 Client 和 MITM Server 間代理鏈接的五元組:
源 IP 地址:被抓包應用的 IP 地址,一般為設備 IP,一般不做修改源埠:被抓包應用的埠號,一般為作業系統分配,無法修改傳輸層協議:Charles 目前主要代理的是 HTTP 協議,一般為 TCP目的 IP 地址:Charles 的 IP 地址,一般為電腦本機 IP,一般不做修改目的埠:Charles 的代理埠,默認為 8888,可以修改
“?? 注:上述分析中只考慮了一般情況,如果你真的想改也可以改,但這種 hack 行為不在本文考慮范圍內
從上面的分析我們可以看出,想要打通五元組,我們主要要關注兩個點:目的 IP 地址和目的埠,
我們先分析一下目的 IP 地址,因為 Charles 安裝在電腦上,所以 Charles 的 IP 就是電腦的 IP,如果你是 Mac 電腦,可以按住 option 鍵再用滑鼠點擊選單欄的 Wi-Fi 圖示,得到電腦 IP 地址,也可以訪問 系統偏好設定 -> 網路 得到 IP 地址,這里我的 IP 地址是 192.168.31.44,后面會用到,

Charles 的代理埠號可以從 Charles -> Proxy -> Proxy Setttings 進行查看和更改,埠默認是 8888,一般不建議修改,

HTTP 代理配置
確定好 Charles 的 IP 和埠號后,我們就可以分設備配置 HTTP 代理了,
1.電腦端 HTTP 代理配置
無論你使用的是 window 還是 mac,Charles 作為一款在電腦上安裝的 APP,代理本機請求時,網路資料都是在本地轉發的,所以相對來說電腦端的配置是最簡單的,我們只要根據路徑 Charles -> Proxy -> macOS Proxy 依次點擊開啟代理就可,
因為本機代理默認是關閉的,我們也可以在 Proxy Setttings 中點擊 macOS,勾選 Enable macOS proxy on lounch,這樣每次打開 Charles 就會默認打開代理了,

2.iOS 代理配置
想要抓 iOS 的網路包,只需要把 iOS 的網路包轉發到代理 IP 和代理埠就行,
配置前我們要保證手機和電腦在同一個局域網里(一般手機電腦連同一個 Wi-Fi 就行),然后打開 iOS 的 設定 -> 無線局域網,進入已連接的 Wi-Fi 的設定頁面,滑動到最底部選擇配置代理,然后手動配置代理,

服務器要輸入的就是前面得到的 Charles IP 地址,案例里是 192.168.31.44;埠是前面的 Charles 代理埠,一般為 8888,
3.Android 代理配置
Android 的代理配置其實和 iOS 差不多,但是 Android 廠家眾多,操作步驟不像 iOS 那么統一,一一覆寫也沒有太大的意義,所以我只做個簡單的步驟演示:

HTTPS 代理配置
HTTPS 本質上就是 HTTP 協議 + TLS 協議,從建立連接的角度看,主要是在 TCP 三次握手之后又加入了四次 TLS 握手,如下圖所示,TLS 握手程序中會校驗加密用的公鑰證書,所以我們就要手動安裝并信任 Charles 的證書,以達到抓取 HTTPS Packets 的目的,

TLS 的加入,加強了網路的安全性的同時,也增加了抓包的復雜度,下一節我會詳細解釋,這里先做個證書安裝的步驟演示,
“?? 注:證書安裝前要確保 HTTP 代理已經配置完畢
1.電腦端安裝證書
電腦端安裝證書是最簡單的,首先點擊 Charles -> Help -> SSL Proxying -> Install Charles Root Certificate 在電腦端安裝證書,然后點擊剛剛安裝的證書,手動信任全部權限,最后輸入密碼保存修改就可,

2.iOS 安裝證書
iOS 安裝證書相對來說復雜一些,首先點擊 Charles -> Help -> SSL Proxying -> Install Charles Root Certificate on a Mobile Derive,這時候會跳出一個彈窗,然后我們根據提示在手機端訪問 chls.pro/ssl,下載安裝 Charles CA 證書,

安裝好后還要手動開啟權限,先要到 通用 -> 描述檔案與設備管理 -> 信任 里安裝剛剛下載的證書,然后到 通用 -> 關于本機 -> 證書信任設定 -> 針對根證書啟用完全信任 里手動信任證書,這兩個同意后 iOS 就安裝證書成功了,

3.Android 安裝證書
Android 安裝證書的步驟不但麻煩,作用還不大,
首先點擊 Charles -> Help -> SSL Proxying -> Save Charles Root Certificate,把證書檔案以 *.cer 格式保存,
“?? 注:Charles 保存證書檔案時,有兩種格式可選:
.pem和.cer,前者是一種證書容器格式,一般是對證書進行 base64 編碼;后者一般是二進制格式的證書,Android 系統對二進制格式的證書兼容性更好一些,所以我們選擇.cer檔案,
保存好檔案后,我們再用 USB 或著其它方式把 CA 證書匯入到 Android 內,最后點擊證書安裝就可,
三、Charles 抓包失敗案例分析
本節其實是本文的重點,從 6 個方向分析 Charles 抓包失敗的原因,從代理服務器到 TLS 證書,覆寫了計算機網路的各個知識點,非常值得收藏學習,
1.關閉代理!關閉代理!關閉代理!
作為一名程式員,為了順暢的訪問 GitHub 等網站,我們總會用些“輔助工具”,這些工具一般會自動開啟 HTTP/HTTPS 代理從而搶占埠,導致 Charles 代理失敗,
解決這個問題也很簡單,Charles 抓包前,把電腦和手機的輔助工具都關掉,這樣就不會有代理沖突的問題了,我們可以查看電腦的 Wi-Fi 代理界面,開啟 Charles 抓包前要保證下面的選項都沒被勾選就好了,

肯定也有人想過我們本地掛兩個代理,報文先經過工具,然后經過 Charles 抓包,最后傳輸到客戶端,首先這種方案是可行的,但是實際用下來會非常的卡,延遲也很高,所以并不建議這樣使用,
2.確定資料走的 HTTP 協議嗎?
本小節開始前我們先看一下官方是如何定義 Charles 的:
“Charles is an HTTP proxy / HTTP monitor / Reverse Proxy that enables a developer to view all of the HTTP and SSL / HTTPS traffic between their machine and the Internet.
從介紹中我們可以看出 Charles 是一款專注于分析 HTTP 報文的網路工具,所以說對于其它協議支持是非常有限的,比如說現在的 IM 或音視頻應用,出于性能和安全上的考慮,基本都是自己基于某一傳輸層協議自己封裝的,這些資料 Charles 肯定是抓不到的,
通過閱讀 Charles 的官方檔案和自己的測驗,Charles 支持以下協議:
HTTP/1.1 HTTPS HTTP/2 ws(WebSocket) wss(WebSocket Secure,TLS 加密的 WebSocket) SOCKS
“?? 注:Charles 不支持 HTTP/3,但是大部分開啟 HTTP/3 的網站都做了降級處理,例如用 Chrome 正常訪問 Google 時,走的協議是 HTTP/3,連接 Charles 代理后,協議會降級到 HTTP/2
上面列出的幾個協議,其實已經覆寫日常業務開發 90% 的應用場景了,若想抓取其他協議的報文,還是老老實實用 Wireshark 吧,
3.之前開了黑白名單,再次抓包忘記關了
我想日常作業中,你或你的同事肯定遇到過這種場景:
“測驗報上來一個 BUG,自己連上 Charles 打算分析一下 HTTP 報文想定位一下是前端問題還是后端問題,結果發現請求一直打不通,手忙腳亂半天,才發現自己開了黑白名單,請求都被 Block 掉了
上面案例的黑白名單只是一個統稱,具體到 Charles 里,下面的幾個配置都有可能造成誤解:
Proxy Settings的 Options 里過濾了一些網址SSL Proxying Settings沒有匹配所有網址Block List/Allow List做了黑白名單設定DNS Spoofing做了 HOST 的映射Map Remote重定向了請求Rewrite重寫了請求......
我寫了幾個高頻的 Charles Tools,這些功能很有可能在你開啟后就忘記關閉了,如果出了問題難道就要一一排查嗎?
其實 Charles 有一個很不起眼的功能,那就是它的 UI 界面右下角會展示 Charles 正在開啟的功能,如果你懷疑你的 Charles 哪里做了介面限制,你就掃一眼右下角開啟的功能,然后依次檢查就可,

4.Android 版本越高,HTTPS 報文越難抓
在「Android 安裝證書」那個小節里,我說這個步驟意義不大,根本原因在于:用戶自己安裝的 CA 證書沒有 ROOT 權限,
我們先看一張圖,這個是 Android 的證書信任頁面:

從上圖可以看出,Android 系統把證書信任分為兩大塊:
系統 CA 證書:基本擁有所有權限 用戶 CA 證書:用戶自行安裝,權限很低
我們自己安裝的 Charles 證書都屬于用戶 CA 證書,除了證書的權限問題,Android 的不同版本對權限的處理規則也不一樣:
?:Android 7.0 以下:信任用戶 CA 證書,可以簡單的理解為我們安裝的證書直接獲得 ROOT 權限
?:Android 7.0 以上, targetSdkVersion < 24:信任用戶 CA 證書
?:Android 7.0 以上, targetSdkVersion >= 24:不信任用戶 CA 證書
通過以上的分析,我們可以得出幾個讓 Android 信任 Charles 證書的方案:
1.ROOT
直接 ROOT Android 手機,把 Charles 證書放到系統證書里,實作證書洗白
2.準備一個低于 Android 7.0 的手機
Android 7.0 是 2016 年的系統,按照 Android 手機兩年一換代一年一更新的速度算,這種手機很難找到了
3.準備一個 targetSdkVersion < 24 的 APP 安裝包
國內各大應用市場 2019 年統一要求 APP API 版本必須大于 28,這種安裝包很難找到了,而且互聯網產品迭代這么快,不一定能保證安裝包可用
4.騷操作
正常大道走不通,Android 小道還是有很多的,社區上有各種輪子可以繞開限制,但和 Charles 關系不大,我就不展開說了,喜歡折騰的同學可以研究一下,
上面的幾個方案都是針對其它 APP 的,如果你想抓包的應用是自己公司的,那就很簡單了,
Android 有個 res/xml/network_security_config.xml 檔案,意如其名,這個組態檔是專門控制網路安全的,
比如下面的配置,release 包只信任 system 級別的證書,debug 包同時信任 system 和 user 級別的證書,這樣我們在 debug 環境下就可以開心的用 Charles 抓包了,當然安全配置肯定不止這一點內容,感興趣的同學可以去 Android 開發者官網學習了解,
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates overridePins="true" src="system" />
</trust-anchors>
</base-config>
<debug-overrides>
<trust-anchors>
<certificates overridePins="true" src="system" />
<certificates overridePins="true" src="user" />
</trust-anchors>
</debug-overrides>
</network-security-config>
5.證書固定(Certificate Pinning)
證書固定(Certificate Pinning) 是指客戶端內置了服務端真正的公鑰證書,
在 HTTPS 請求時,服務端發給客戶端的公鑰證書必須和客戶端內置的公鑰證書一致才能請求成功,一般對安全比較重視的公司會采取這種操作,
在這種情況下,利用 Charles 抓包時,Charles 的公鑰證書和客戶端的公鑰證書不一樣,偽造的請求就會被駁回,我們就抓包失敗了,那么這種情況怎么解決?
和前面介紹的一樣,路其實還是有兩條:
一條是 Hack 之路,刷機 ROOT,借助工具移除 APP 中固定的公鑰證書;
另一條是正路,你擁有這個 APP 的開發權限,那么一般你也就擁有了公鑰證書和隨之配套的私鑰,我們可以把證書和私鑰匯入到 Charles 中,解決證書固定引起的困擾,
Charles 匯入公鑰證書和私鑰比較簡單,點擊 Charles -> Proxy -> SSL Proxying Setting -> Root Certificate,然后匯入 .pem 或 p12 檔案即可,
“?? 注:
.p12是一種檔案格式,同時包含證書和密鑰

6.證書雙向驗證
在絕大部分的情況下,TLS 都是客戶端認證服務端的真實性的,但是在一些非常注重安全的場景下(例如匿名社交),部分 APP 會開啟 TLS 的雙向驗證,也就是說服務端也要驗證客戶端的真實性,
在這種情況,客戶端必然內置了一套公鑰證書和私鑰,相對于服務端,APP 有很大的砸殼風險,所以公鑰證書和私鑰一般都是極其隱蔽的,比如說寫到 .so 里,隱藏在一個混淆的媽都不認識的亂數演算法函式里,從而增大破譯難度,
我不是安全專家對這個研究的不深,平常作業也沒遇到這么刁難的問題,從功能面板看,Charles 應該也支持這種極限場景的抓包,但是個人沒有具體實踐過,大家可以嘗試一下,

四、總結
Charles 抓包是一個很常見的職業技能,如果深入研究,你會發現它涉及到網路連接的五元組、報文轉發的代理服務、密碼學里的 MITM 和公鑰證書知識,綜合來看,只有掌握這些較為底層的基礎知識,面對作業中各種奇奇怪怪得問題時,才能游刃有余的應對,
五、感謝大家
如果大家覺得這篇文章不錯,請一定不要忘記點贊 ?? 支持作者,謝謝你,這對我真的很重要!
歡迎大家關注公眾號「鹵蛋實驗室」,寫一些不注水的原創干貨,
歡迎關注我的個人網站:supercodepower.com,因為各大平臺修改文章都會重新審核,個人博客修改更新更方便一些,
六、推薦閱讀
本人之前寫過一些計算機網路相關的博文,橫跨多個坑點,歡迎大家圍觀點贊:
15 張精美動圖全面講解 CORS ?????? HTTP 冷知識 | X-Forwarded-For 拿到的就是真實 IP 嗎? HTTP 冷知識 | HTTP 請求中,空格應該被編碼為 %20 還是 + ? HTTP 的這幾個坑你都踩過嗎?
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/110980.html
標籤:其他
上一篇:京喜小程式首頁無障礙優化實踐
