本文使用青花瓷軟件和Wireshark進行抓包分析
Wireshark的使用:
本次主要通過 RVI 抓取 iPhone 數據包
使用 Mac 抓取 iPhone 數據包可通過共享和代理兩種方式:
使用 Mac 的網絡共享功能將 Mac 的網絡通過 WiFi 共享給 iPhone 連接;
使用代理軟件(例如 Charles、Flidder for Mono、Andiparos)在Mac上 建立HTTP代理服務器。
這兩種方式都是將 iPhone 的網絡流量導入到 Mac 電腦中,通過 Mac 連接互聯網。這就要求 Mac 本身是聯網的,對于網絡共享的方式還要求 Mac 本身的網絡不能使用 WiFi,而且在 iPhone 上只能使用 WiFi 連接,無法抓取到 xG(2G/3G/4G) 網絡包。
蘋果在 iOS 5 中新引入了“遠程虛擬接口(Remote Virtual Interface,RVI)”的特性,可以在 Mac 中建立一個虛擬網絡接口來作為 iOS 設備的網絡棧,這樣所有經過 iOS 設備的流量都會經過此虛擬接口。此虛擬接口只是監聽 iOS 設備本身的協議棧(但并沒有將網絡流量中轉到 Mac 本身的網絡連接上),所有網絡連接都是 iOS 設備本身的,與 Mac 電腦本身聯不聯網或者聯網類型無關。iOS設備本身可以為任意網絡類型(WiFi/xG),這樣在 Mac 電腦上使用任意抓包工具(tcpdump、Wireshark、CPA)抓取 RVI 接口上的數據包就實現了對 iPhone 的抓包。
Mac OS X 對 RVI 的支持是通過終端命令 rvictl 提供的,在終端(Terminal)中輸入“ rvictl ? ”命令可查看幫助:
rvictl Options:
-l, -L List currently active devices
-s, -S Start a device or set of devices
-x, -X Stop a device or set of devices
使用 “ rvictl -s ”命令創建虛擬接口
首先,通過 MFI USB 數據線將 iPhone 連接到安裝了 Mac OS+Xcode 4.2(or later) 的 Mac 機上。iOS 7 以上需要搭配 Xcode 5.0(or later),抓包過程中必須保持連接。
然后,通過 Xcode->Organizer->Devices 獲取 iPhone 的 UDID(identifier)。
接著,使用“rvictl -s”命令創建 RVI 接口,使用 iPhone 的 UDID 作為參數。
$rvictl -s <UDID>
Http報文首部
HTTP協議的請求和響應報文必定包含HTTP首部。首部內容為客戶端和服務端分別處理請求和響應提供所需的信息。
HTTP請求報文
響應報文
在響應中,HTTP報文是有HTTP版本、狀態碼、HTTP首部字段3部分構成。
HTTP首部字段會根據實際用途分為4種類型
1. 通用首部字段 請求報文和響應報文兩方都會使用首部。
2. 請求首部字段 從客戶端向服務端發送請求報文的時候使用首部字段。補充了請求的附加內容,也會要求客戶端附加額外的內容信息。
3. 響應首部字段 從服務端向客戶端返回響應報文時使用的首部。
4. 實體首部字段 針對請求報文和響應報文的實體部分使用的首部。
通用首部字段
首部字段名 | 說明 |
---|---|
Cache-Control | 控制緩存的行為 |
Connection | 逐跳首部、連接的管理 |
Date | 創建報文的日期時間 |
Pragma | 報文指令 |
Trailer | 報文末端的首部一覽 |
Transfer-Encoding | 指定報文主體的傳輸編碼方式 |
請求首部字段
首部字段名稱 | 說明 | 舉例 |
---|---|---|
Accept | 用戶代理可處理的媒體類型 | Accept: text/html,application/xhtml+xml,application/xml |
Accept-Charset | 優先的字符集 | Accept-Charset: iso-8859-5, unicode-1-1;q=0.8 |
Accept-Encoding | 優先的內容編碼 | Accept-Encoding: gzip, deflate Accept-Encoding 首部字段用來告知服務器用戶代理支持的內容編碼及內容編碼的優先級順序??梢淮涡灾付ǘ喾N內容編碼 |
Accept-Language | 優先的語言(自然語言) | ccept-Language: zh-cn,zh;q=0.7,en-us,en;用來告知服務器用戶代理能夠處理的自然 |
Authorization | Web認證信息 | Authorization: Basic dWVub3NlbjpwYXNzd29yZA==.首部字段 Authorization 是用來告知服務器,用戶代理的認證信息(證書值)。通常,想要通過服務器認證的用戶代理會在接收到返回的401 狀態碼響應后,把首部字段 Authorization 加入請求中。共用緩存在接收到含有 Authorization 首部字段的請求時的操作處理會略有差 |
Expect | 期待服務器的特定行為 | expect: 100-continue.客戶端使用首部字段 Expect 來告知服務器,期望出現的某種特定行為。因服務器無法理解客戶端的期望作出回應而發生錯誤時,會返回狀態碼 417 Expectation Failed。客戶端可以利用該首部字段,寫明所期望的擴展。雖然 HTTP/1.1 規范只定義了 100-continue(狀碼 100 Continue 之意)。等待狀態碼 100 響應的客戶端在發生請求時,需要指定 Expect:100-continue。 |
From | 用戶的電子郵箱地址 | 郵箱地址 |
Host | 請求資源所在服務器 | Host 會告知服務器,請求的資源所處的互聯網主機名和端口號。Host 首部字段在 HTTP/1.1 規范內是唯一一個必須被包含在請求內的首部字段。首部字段 Host 和以單臺服務器分配多個域名的虛擬主機的工作機制有很密切的關聯,這是首部字段 Host 必須存在的意義。請求被發送至服務器時,請求中的主機名會用 IP 地址直接替換解決。但如果這時,相同的 IP 地址下部署運行著多個域名,那么服務器就會無法理解究竟是哪個域名對應的請求。因此,就需要使用首部字段 Host 來明確指出請求的主機名。若服務器未設定主機名,那直接發送一個空值即可 |
If-Match | 比較實體標記(ETag) | If-xxx 這種樣式的請求首部字段,都可稱為條件請求。服務器接收到附帶條件的請求后,只有判斷指定條件為真時,才會執行請求 |
If-Modified-Since | 比較資源的更新時間 | If-Modified-Since,屬附帶條件之一,它會告知服務器若 If-Modified-Since 字段值早于資源的更新時間,則希望能處理該請求。而在指定 If-Modified-Since 字段值的日期時間之后,如果請求的資源都沒有過更新,則返回狀304 Not Modified 的響應。If-Modified-Since 用于確認代理或客戶端擁有的本地資源的有效性。獲取資源的更新日期時間,可通過確認首部字段 Last-Modified 來確定。 |
If-None-Match | 比較實體標記(與 If-Match 相反) | If-None-Match 屬于附帶條件之一。它和首部字段 If-Match作用相反。用于指定 If-None-Match 字段值的實體標記(ETag)值與請求資源的 ETag 不一致時,它就告知服務器處理該請求。在 GET 或 HEAD 方法中使用首部字段 If-None-Match 可獲取最新的資源。因此,這與使用首部字段 If-Modified-Since 時有些類似 |
If-Range | 資源未更新時發送實體 Byte 的范圍請求 | If-Range 屬于附帶條件之一。它告知服務器若指定的 If-Range 字段值(ETag 值或者時間)和請求資源的 ETag 值或時間相一致時,則作為范圍請求處理。反之,則返回全體資源 |
If-Unmodified-Since | 比較資源的更新時間(與If-Modified-Since相反) | If-Unmodified-Since 和首部字段 If-Modified-Since 的作用相反。它的作用的是告知服務器,指定的請求資源只有在字段值內指定的日期時間之后,未發生更新的情況下,才能處理請求。如果在指定日期時間后發生了更新,則以狀態碼 412 Precondition Failed 作為響應返回 |
Max-Forwards | 最大傳輸逐跳數 | 通過 TRACE 方法或 OPTIONS 方法,發送包含首部字段 Max-Forwards 的請求時,該字段以十進制整數形式指定可經過的服務器最大數目。服務器在往下一個服務器轉發請求之前,Max-Forwards 的值減 1 后重新賦值。當服務器接收到 Max-Forwards 值為 0 的請求時,則不再進行轉發,而是直接返回響應 |
Proxy-Authorization | 代理服務器要求客戶端的認證信息 | 接收到從代理服務器發來的認證質詢時,客戶端會發送包含首部字段Proxy-Authorization 的請求,以告知服務器認證所需要的信息。這個行為是與客戶端和服務器之間的 HTTP 訪問認證相類似的,不同之處在于,認證行為發生在客戶端與代理之間??蛻舳伺c服務器之間的認證,使用首部字段 Authorization 可起到相同作用 |
Range | 實體的字節范圍請求 | Range: bytes=5001-10000。對于只需獲取部分資源的范圍請求,包含首部字段 Range 即可告知服務器資源的指定范圍。上面的示例表示請求獲取從第 5001 字節至第10000 字節的資源。接收到附帶 Range 首部字段請求的服務器,會在處理請求之后返回狀態碼為 206 Partial Content 的響應。無法處理該范圍請求時,則會返回狀態碼 200 OK 的響應及全部資源 |
Referer | 對請求中 URI 的原始獲取方 | 客戶端一般都會發送 Referer 首部字段給服務器。但當直接在瀏覽器的地址欄輸入 URI,或出于安全性的考慮時,也可以不發送該首部字段。因為原始資源的 URI 中的查詢字符串可能含有 ID 和密碼等保密信息,要是寫進 Referer 轉發給其他服務器,則有可能導致保密信息的泄露 |
User-Agent | HTTP 客戶端程序的信息 | User-Agent 會將創建請求的瀏覽器和用戶代理名稱等信息傳達給服務器。由網絡爬蟲發起請求時,有可能會在字段內添加爬蟲作者的電子郵件地址。此外,如果請求經過代理,那么中間也很可能被添加上代理服務器的名稱 |
響應首部字段
響應首部字段是由服務器端向客戶端返回響應報文中所使用的字段,用于補充響應的附加信息、服務器信息,以及對客戶端的附加要求等信息。
| 首部字段名 | 說明 | 舉例 |
| ------------- |:-------------:| |
|Accept-Ranges| 是否接受字節范圍請求 |首部字段 Accept-Ranges 是用來告知客戶端服務器是否能處理范圍請求,以指定獲取服務器端某個部分的資源??芍付ǖ淖侄沃涤袃煞N,可處理范圍請求時指定其為 bytes,反之則指定其為 none。 |
| Age | 推算資源創建經過時間 | Age: 600;首部字段 Age 能告知客端,源服務器在多久前創建了響應。字段值的單位為秒。若創建該響應的服務器是緩存服務器,Age 值是指緩存后的響應再次發起認證到認證完成的時間值。代理創建響應時必須加上首部字段=Age。 |
| ETag | 資源的匹配信息|ETag: "82e22293907ce725faf67773957acd12”。首部字段 ETag 能告知客戶端實體標識。它是一種可將資源以字符串形式做唯一性標識的方式。服務器會為每份資源分配對應的 ETag值。 另外,當資源更新時,ETag 值也需要更新。生成 ETag 值時,并沒有統一的算法規則,而僅僅是由服務器來分配。資源被緩存時,就會被分配唯一性標識。例如,當使用中文版的瀏覽器訪問 http://www.google.com/ 時,就會返回中文版對應的資源,而使用英文版的瀏覽器訪問時,則會返回英文版對應的資源。兩者的URI 是相同的,所以僅憑 URI 指定緩存的資源是相當困難的。若在下載過程中出現連接中斷、再連接的情況,都會依照 ETag 值來指定資源。強 ETag 值和弱 Tag 值。ETag 中有強 ETag 值和弱 ETag 值之分強 ETag 值。強 ETag 值,不論實體發生多么細微的變化都會改變其值。ETag: "usagi-1234"弱 ETag 值弱 ETag 值只用于提示資源是否相同。只有資源發生了根本改變,產生差異時才會改變 ETag 值。這時,會在字段值最開始處附加 W/ETag: W/"usagi-1234" |
| Location | 令客戶端重定向至指定URI| Location: http://www.usagidesign.jp/sample.html。使用首部字段 Location 可以將響應接收方引導至某個與請求 URI 位置不同的資源?;旧?,該字段會配合 3xx :Redirection 的響應,提供重定向的URI。幾乎所有的瀏覽器在接收到包含首部字段 Location 的響應后,都會強制性地嘗試對已提示的重定向資源的訪問。 |
| Proxy-Authenticate| 代理服務器對客戶端的認證信息| 首部字段 Proxy-Authenticate 會把由代理服務器所要求的認證信息發送給客戶端。它與客戶端和服務器之間的 HTTP 訪問認證的行為相似,不同之處在于其認證行為是在客戶端與代理之間進行的。而客戶端與服務器之間進行認證時,首部字段 WWW-Authorization 有著相同的作用。有關HTTP 訪問認證,后面的章節會再進行詳盡闡述。 |
| Retry-After |對再次發起請求的時機要求| Retry-After 告知客戶端應該在多久之后再次發送請求。主要配合狀碼 503 Service Unavailable 響應,或 3xx Redirect 響應一起使用。字段值可以指定為具體的日期時間(Wed, 04 Jul 2012 06:34:24GMT 等格式),也可以是創建響應后的秒數。 |
| Server|HTTP服務器的安裝信息 | Server: Apache/2.2.17 (Unix)。首部字段 Server 告知客戶端當前服務器上安裝的 HTTP 服務器應用程序的信息。不單單會標出服務器上的軟件應用名稱,還有可能包括版本號和安裝時啟用的可選項。Server: Apache/2.2.6 (Unix) PHP/5.2.5|
| Vary|代理服務器緩存的管理信息| 當代理服務器接收到帶有 Vary 首部字段指定獲取資源的請求時,如果使用的 Accept-Language 字段的值相同,那么就直接從緩存返回響應。反之,則需要先從源服務器端獲取資源后才能作為響應返回。首部字段 Vary 可對緩存進行控制。源服務器會向代理服務器傳達關于本地緩存使用方法的命令。從代理服務器接收到源服務器返回包含 Vary 指定項的響應之后,若再要進行緩存,僅對請求中含有相同 Vary 指定首部字段的請求返回緩存。即使對相同資源發起請求,但由于 Vary 指定的首部字段不相同,因此必須要從源服務器重新獲取資源。|
| WWW-Authenticate| 服務器對客戶端的認證信息 | WWWAuthenticate: Basic realm="Usagidesign Auth"首部字段 WWW-Authenticate 用于 HTTP 訪問認證。它會告知客戶端適用于訪問請求 URI 所指定資源的認證方案(Basic 或是 Digest)和帶參數提示的質詢(challenge)。狀態碼 401 Unauthorized 響應中,肯定帶有首部字段 WWW-Authenticate。|
實體首部字段
實體首部字段是包含在請求報文和響應報文中的實體部分所使用的首部,用于補充內容的更新時間等與實體相關的信息。
首部字段名 | 說明 | 舉例 |
---|---|---|
Allow | 資源可支持的HTTP方法 | Allow: GET, HEAD。首部字段 Allow 用于通知客戶端能夠支持 Request-URI 指定資源的所有 HTTP 方法。當服務器接收到不支持的 HTTP 方法時,會以狀態碼405 Method Not Allowed 作為響應返回。與此同時,還會把所有能支持的 HTTP 方法寫入首部字段 Allow 后返回。 |
Content-Encoding | 實體主體適用的編碼方式 | Content-Encoding: gzip。首部字段 Content-Encoding 會告知客戶端服務器對實體的主體部分選用的內容編碼方式。內容編碼是指在不丟失實體信息的前提下所進行的壓縮。 |
Content-Language | 實體主體的自然語言 | 首部字段 Content-Language 會告知客戶端,實體主體使用的自然語言(指中文或英文等語言) |
Content-Length | 實體主體的大?。▎挝唬鹤止潱?/td> | 首部字段 Content-Length 表明了實體主體部分的大?。▎挝皇亲止潱?。對實體主體進行內容編碼傳輸時,不能再使用 Content-Length首部字段 |
Content-Location | 替代對應資源的URI | Content-Location: http://www.hackr.jp/index-ja.html。首部字段 Content-Location 給出與報文主體部分相對應的 URI。和首部字段 Location 不同,Content-Location 表示的是報文主體返回資源對應的 URI。比如,對于使用首部字段 Accept-Language 的服務器驅動型請求,當返回的頁面內容與實際請求的對象不同時,首部字段 Content-Location內會寫明 URI。(訪問 http://www.hackr.jp/ 返回的對象卻是http://www.hackr.jp/index-ja.html 等類似情況) |
Content-MD5 | 實體主體的報文摘要 | 客戶端會對接收的報文主體執行相同的 MD5 算法,然后與首部字段 Content-MD5 的字段值比較Content-MD5: OGFkZDUwNGVhNGY3N2MxMDIwZmQ4NTBmY2IyTY==首部字段 Content-MD5 是一串由 MD5 算法生成的值,其目的在于檢查報文主體在傳輸過程中是否保持完整,以及確認傳輸到達。對報文主體執行 MD5 算法獲得的 128 位二進制數,再通過 Base64 編碼后將結果寫入 Content-MD5 字段值。由于 HTTP 首部無法記錄二進制值,所以要通過 Base64 編碼處理。為確保報文的有效性,作為接收方的客戶端會對報文主體再執行一次相同的 MD5 算法。計算出的值與字段值作比較后,即可判斷出報文主體的準確性。采用這種方法,對內容上的偶發性改變是無從查證的,也無法檢測出惡意篡改。其中一個原因在于,內容如果能夠被篡改,那么同時意味著 Content-MD5 也可重新計算然后被篡改。所以處在接收階段的客戶端是無法意識到報文主體以及首部字段 Content-MD5 是已經被篡改過的。 |
Content-Range | 實體主體的位置范圍 | Content-Range: bytes 5001-10000/10000。針對范圍請求,返回響應時使用的首部字段 Content-Range,能告知客戶端作為響應返回的實體的哪個部分符合范圍請求。字段值以字節為單位,表示當前發送部分及整個實體大小。 |
Content-Type | 實體主體的媒體類型 | Content-Type: text/html; charset=UTF-8。首部字段 Content-Type 說明了實體主體內對象的媒體類型。和首部字段 Accept 一樣,字段值用 type/subtype 形式賦值。參數 charset 使用 iso-8859-1 或 euc-jp 等字符集進行賦值。 |
Expires | 實體主體過期的日期時間 | 首部字段 Expires 會將資源失效的日期告知客戶端。緩存服務器在接收到含有首部字段 Expires 的響應后,會以緩存來應答請求,在Expires 字段值指定的時間之前,響應的副本會一直被保存。當超過指定的時間后,緩存服務器在請求發送過來時,會轉向源服務器請求資源。源服務器不希望緩存服務器對資源緩存時,最好在 Expires 字段內寫入與首部字段 Date 相同的時間值。但是,當首部字段 Cache-Control 有指定 max-age 指令時,比起首部字段 Expires,會優先處理 max-age 指令。 |
Last-Modified | 資源的最后修改日期時間 | Last-Modified: Wed, 23 May 2012 09:59:55 GMT。首部字段 Last-Modified 指明資源最終修改的時間。一般來說,這個值就是 Request-URI 指定資源被修改的時間。但類似使用 CGI 腳本進行動態數據處理時,該值有可能會變成數據最終修改時的時間。 |