【答疑解惑】爲什麼你的 Charles 會抓包失敗?

作爲一名 Web 開發工程師,天天都會和網絡打交道。Charles 作爲一款網絡抓包工具,幾乎成了 Web 開發的標配。

本文是我深度使用 Charles 後總結而成,不同於其它介紹 Charles 的文章,這篇文章不會詳細介紹 Charles 的各個功能(例如 remote 和 rewrite),而是專注於分析一個問題:什麼情況下 Charles 會抓包失敗?

爲了解決這個問題,我會從 Charles 的原理分析,並且結合 Android/iOS 的官方政策,一一分析 Charles 抓包中的那些失效問題。看完後如果你覺得有用,一定要記得給我點贊 🌟,謝謝你,這對我真的很重要!

一、Charles 抓包原理

市面上絕大多數的抓包軟件,背後的原理都是中間人攻擊(Man-in-the-middle attack,縮寫:MITM)

維基百科是這樣定義 MITM 的:

中間人攻擊在密碼學和計算機安全領域中是指攻擊者與通訊的兩端分別建立獨立的聯繫,並交換其所收到的數據,使通訊的兩端認爲他們正在通過一個私密的連接與對方直接對話,但事實上整個會話都被攻擊者完全控制。

上面的定義寫的很清晰,我結合 Charles 畫了一個圖,結合箭頭方向就能看懂 HTTP Packets 的流向:

MITM
MITM

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

結合 Wireshark 的抓包報文和 Charles 的網絡分析,我們可以看出這個 HTTP 請求的報文流向:

  1. 瀏覽器(Client)從端口號 56075 發起一個請求,請求發送到本地 Charles 監聽的 8888 端口(MITM Server),這個連接直接在本機進行

  2. 收到瀏覽器的請求後,Charles 再從端口號 56076MITM Client)發起一個新的請求,因爲這個網絡包要入公網,所以 IP 爲 192.168.31.44(我的電腦 IP 地址,下節會介紹); cdn.staticfile.orgServer)的 IP 爲 111.63.183.223,因爲是 HTTP 請求,所以端口號爲 80

  3. 111.63.183.223:80 返回一個 HTTP 響應到 Charles 的代理客戶端 192.168.31.44:56076

  4. Charles 內部做了一些處理(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 1.2
TLS 1.2

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 包同時信任 systemuser 級別的證書,這樣我們在 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,然後導入 .pemp12 文件即可。

⚠️ 注:.p12 是一種文件格式,同時包含證書和密鑰

6.證書雙向驗證

在絕大部分的情況下,TLS 都是客戶端認證服務端的真實性的,但是在一些非常注重安全的場景下(例如匿名社交),部分 APP 會開啓 TLS 的雙向驗證,也就是說服務端也要驗證客戶端的真實性

在這種情況,客戶端必然內置了一套公鑰證書和私鑰。相對於服務端,APP 有很大的砸殼風險,所以公鑰證書和私鑰一般都是極其隱蔽的,比如說寫到 .so 裏,隱藏在一個混淆的媽都不認識的隨機數算法函數裏,從而增大破譯難度。

我不是安全專家對這個研究的不深,平常工作也沒遇到這麼刁難的問題。從功能面板看,Charles 應該也支持這種極限場景的抓包,但是個人沒有具體實踐過,大家可以嘗試一下。

四、總結

Charles 抓包是一個很常見的職業技能,如果深入研究,你會發現它涉及到網絡連接的五元組、報文轉發的代理服務、密碼學裏的 MITM 和公鑰證書知識。綜合來看,只有掌握這些較爲底層的基礎知識,面對工作中各種奇奇怪怪得問題時,才能遊刃有餘的應對。

五、感謝大家

如果大家覺得這篇文章不錯,請一定不要忘記點贊 🌟 支持作者,謝謝你,這對我真的很重要!

歡迎大家關注公衆號「滷蛋實驗室」,寫一些不注水的原創乾貨。

歡迎關注我的個人網站:supercodepower.com,因爲各大平臺修改文章都會重新審覈,個人博客修改更新更方便一些。

六、推薦閱讀

本人之前寫過一些計算機網絡相關的博文,橫跨多個坑點,歡迎大家圍觀點贊:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章