做爲一名 Web 開發工程師,每天都會和網絡打交道。Charles 做爲一款網絡抓包工具,幾乎成了 Web 開發的標配。前端
本文是我深度使用 Charles 後總結而成,不一樣於其它介紹 Charles 的文章,這篇文章不會詳細介紹 Charles 的各個功能(例如 remote 和 rewrite),而是專一於分析一個問題:什麼狀況下 Charles 會抓包失敗?android
爲了解決這個問題,我會從 Charles 的原理分析,而且結合 Android/iOS 的官方政策,一一分析 Charles 抓包中的那些失效問題。看完後若是你以爲有用,必定要記得給我點贊 🌟,謝謝你,這對我真的很重要!程序員
市面上絕大多數的抓包軟件,背後的原理都是中間人攻擊(Man-in-the-middle attack,縮寫:MITM)。算法
維基百科是這樣定義 MITM 的:後端
中間人攻擊在密碼學和計算機安全領域中是指攻擊者與通信的兩端分別創建獨立的聯繫,並交換其所收到的數據,使通信的兩端認爲他們正在經過一個私密的鏈接與對方直接對話, 但事實上整個會話都被攻擊者徹底控制。
上面的定義寫的很清晰,我結合 Charles 畫了一個圖,結合箭頭方向就能看懂 HTTP Packets 的流向:瀏覽器
只看理論有些幹,咱們能夠用個實例看一下 Charles 內部的工做狀況。我在電腦瀏覽器上訪問 cdn.staticfile.org
的一個 HTTP 資源,具體的網絡報文我用 Wireshark 抓了一下:緩存
結合 Wireshark 的抓包報文和 Charles 的網絡分析,咱們能夠看出這個 HTTP 請求的報文流向:安全
56075
發起一個請求,請求發送到本地 Charles 監聽的 8888
端口(MITM Server),這個鏈接直接在本機進行56076
(MITM Client)發起一個新的請求,由於這個網絡包要入公網,因此 IP 爲 192.168.31.44
(個人電腦 IP 地址,下節會介紹); cdn.staticfile.org
(Server)的 IP 爲 111.63.183.223
,由於是 HTTP 請求,因此端口號爲 80
111.63.183.223:80
返回一個 HTTP 響應到 Charles 的代理客戶端 192.168.31.44:56076
8888
端口發送到 127.0.0.1:56075
,到這裏瀏覽器就收到了響應在第二步和第三步中,報文通過了 Charles,Charles 這時就能夠對報文進行一些加工,例如 Remote 重定向,Rewrite,緩存報文並可視化等操做。服務器
爲了文章的連續性,這裏我會對 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
,通常不建議修改。
肯定好 Charles 的 IP 和端口號後,咱們就能夠分設備配置 HTTP 代理了。
不管你使用的是 window 仍是 mac,Charles 做爲一款在電腦上安裝的 APP,代理本機請求時,網絡數據都是在本地轉發的,因此相對來講電腦端的配置是最簡單的。咱們只要根據路徑 Charles -> Proxy -> macOS Proxy 依次點擊開啓代理就可。
由於本機代理默認是關閉的,咱們也能夠在 Proxy Setttings
中點擊 macOS
,勾選 Enable macOS proxy on lounch
,這樣每次打開 Charles 就會默認打開代理了。
想要抓 iOS 的網絡包,只須要把 iOS 的網絡包轉發到代理 IP 和代理端口就行。
配置前咱們要保證手機和電腦在同一個局域網裏(通常手機電腦連同一個 Wi-Fi 就行),而後打開 iOS 的 設置 -> 無線局域網,進入已鏈接的 Wi-Fi 的設置頁面,滑動到最底部選擇配置代理,而後手動配置代理。
服務器要輸入的就是前面獲得的 Charles IP 地址,案例裏是 192.168.31.44
;端口是前面的 Charles 代理端口,通常爲 8888
。
Android 的代理配置其實和 iOS 差很少,可是 Android 廠家衆多,操做步驟不像 iOS 那麼統一,一一覆蓋也沒有太大的意義,因此我只作個簡單的步驟演示:
HTTPS 本質上就是 HTTP 協議 + TLS 協議,從創建鏈接的角度看,主要是在 TCP 三次握手以後又加入了四次 TLS 握手,以下圖所示,TLS 握手過程當中會校驗加密用的公鑰證書,因此咱們就要手動安裝並信任 Charles 的證書,以達到抓取 HTTPS Packets 的目的。
TLS 的加入,增強了網絡的安全性的同時,也增長了抓包的複雜度,下一節我會詳細解釋,這裏先作個證書安裝的步驟演示。
⚠️ 注:證書安裝前要確保 HTTP 代理已經配置完畢
電腦端安裝證書是最簡單的。首先點擊 Charles -> Help -> SSL Proxying -> Install Charles Root Certificate 在電腦端安裝證書,而後點擊剛剛安裝的證書,手動信任所有權限,最後輸入密碼保存修改就可。
iOS 安裝證書相對來講複雜一些。首先點擊 Charles -> Help -> SSL Proxying -> Install Charles Root Certificate on a Mobile Derive,這時候會跳出一個彈窗,而後咱們根據提示在手機端訪問 chls.pro/ssl
,下載安裝 Charles CA 證書。
安裝好後還要手動開啓權限。先要到 通用 -> 描述文件與設備管理 -> 信任 裏安裝剛剛下載的證書,而後到 通用 -> 關於本機 -> 證書信任設置 -> 針對根證書啓用徹底信任 裏手動信任證書,這兩個贊成後 iOS 就安裝證書成功了。
Android 安裝證書的步驟不但麻煩,做用還不大。
首先點擊 Charles -> Help -> SSL Proxying -> Save Charles Root Certificate,把證書文件以 *.cer
格式保存。
⚠️ 注:Charles 保存證書文件時,有兩種格式可選:.pem
和.cer
。前者是一種證書容器格式,通常是對證書進行 base64 編碼;後者通常是二進制格式的證書,Android 系統對二進制格式的證書兼容性更好一些,因此咱們選擇.cer
文件。
保存好文件後,咱們再用 USB 或着其它方式把 CA 證書導入到 Android 內,最後點擊證書安裝就可。
本節實際上是本文的重點,從 6 個方向分析 Charles 抓包失敗的緣由,從代理服務器到 TLS 證書,覆蓋了計算機網絡的各個知識點,很是值得收藏學習。
做爲一名程序員,爲了順暢的訪問 GitHub 等網站,咱們總會用些「輔助工具」。這些工具通常會自動開啓 HTTP/HTTPS 代理從而搶佔端口,致使 Charles 代理失敗。
解決這個問題也很簡單,Charles 抓包前,把電腦和手機的輔助工具都關掉,這樣就不會有代理衝突的問題了。咱們能夠查看電腦的 Wi-Fi 代理界面,開啓 Charles 抓包前要保證下面的選項都沒被勾選就行了。
確定也有人想過咱們本地掛兩個代理,報文先通過工具,而後通過 Charles 抓包,最後傳輸到客戶端。首先這種方案是可行的,可是實際用下來會很是的卡,延遲也很高,因此並不建議這樣使用。
本小節開始前咱們先看一下官方是如何定義 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 支持如下協議:
⚠️ 注: Charles 不支持 HTTP/3,可是大部分開啓 HTTP/3 的網站都作了降級處理。例如用 Chrome 正常訪問 Google 時,走的協議是 HTTP/3,鏈接 Charles 代理後,協議會降級到 HTTP/2
上面列出的幾個協議,其實已經覆蓋平常業務開發 90% 的應用場景了,若想抓取其餘協議的報文,仍是老老實實用 Wireshark 吧。
我想平常工做中,你或你的同事確定遇到過這種場景:
測試報上來一個 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 哪裏作了接口限制,你就掃一眼右下角開啓的功能,而後依次檢查就可。
在「Android 安裝證書」那個小節裏,我說這個步驟意義不大,根本緣由在於:用戶本身安裝的 CA 證書沒有 ROOT 權限。
咱們先看一張圖,這個是 Android 的證書信任頁面:
從上圖能夠看出,Android 系統把證書信任分爲兩大塊:
咱們本身安裝的 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>
證書固定(Certificate Pinning) 是指客戶端內置了服務端真正的公鑰證書。
在 HTTPS 請求時,服務端發給客戶端的公鑰證書必須和客戶端內置的公鑰證書一致才能請求成功。通常對安全比較重視的公司會採起這種操做。
在這種狀況下,利用 Charles 抓包時,Charles 的公鑰證書和客戶端的公鑰證書不同,僞造的請求就會被駁回,咱們就抓包失敗了。那麼這種狀況怎麼解決?
和前面介紹的同樣,路其實仍是有兩條:
Charles 導入公鑰證書和私鑰比較簡單,點擊 Charles -> Proxy -> SSL Proxying Setting -> Root Certificate,而後導入 .pem
或 p12
文件便可。
⚠️ 注:
.p12
是一種文件格式,同時包含證書和密鑰
在絕大部分的狀況下,TLS 都是客戶端認證服務端的真實性的,可是在一些很是注重安全的場景下(例如匿名社交),部分 APP 會開啓 TLS 的雙向驗證,也就是說服務端也要驗證客戶端的真實性。
在這種狀況,客戶端必然內置了一套公鑰證書和私鑰。相對於服務端,APP 有很大的砸殼風險,因此公鑰證書和私鑰通常都是極其隱蔽的,好比說寫到 .so
裏,隱藏在一個混淆的媽都不認識的隨機數算法函數裏,從而增大破譯難度。
我不是安全專家對這個研究的不深,日常工做也沒遇到這麼刁難的問題。從功能面板看,Charles 應該也支持這種極限場景的抓包,可是我的沒有具體實踐過,你們能夠嘗試一下。
Charles 抓包是一個很常見的職業技能,若是深刻研究,你會發現它涉及到網絡鏈接的五元組、報文轉發的代理服務、密碼學裏的 MITM 和公鑰證書知識。綜合來看,只有掌握這些較爲底層的基礎知識,面對工做中各類奇奇怪怪得問題時,才能遊刃有餘的應對。
若是你們以爲這篇文章不錯,請必定不要忘記點贊 🌟 支持做者,謝謝你,這對我真的很重要!
歡迎你們關注公衆號「滷蛋實驗室」,寫一些不注水的原創乾貨。
歡迎關注個人我的網站:supercodepower.com,由於各大平臺修改文章都會從新審覈,我的博客修改更新更方便一些。
本人以前寫過一些計算機網絡相關的博文,橫跨多個坑點,歡迎你們圍觀點贊: