線上使用:API 開發人員專用的 Network Capture Tools

Lane LiaBraaten,Google Data API 團隊
2007 年 6 月

簡介

開發與網路服務互動的應用程式會帶來一組獨特的問題。造成使用者感到困擾的不尋常來源,並不知道收到的郵件到伺服器或收到的回應。其中最棘手的錯誤是因系統傳送的資料到伺服器,以及實際發生線上中斷而中斷。

本文介紹了多項工具,協助您在線路上取得清楚的資料,並從中獲得資料。這些工具通常稱為「封包探查器」,會擷取在網路介面中移動的所有網路封包。檢查這些封包的內容以及其傳送和接收順序是很實用的偵錯技巧。

範例:擷取公開資訊提供

我籌辦了一支慈善團體的慈善團體團活動,也為資訊會議、團隊募款活動和訓練搭車等活動建立了一個日曆。我們已將此日曆設為公開,方便小組成員和其他乘客查看日曆及參與活動。我也希望寄送包含近期活動的電子報,這樣就不必使用 Google 日曆網站複製資訊,而是使用 Google Calendar data API 查詢這個日曆並擷取活動。

Google Calendar API 說明文件說明如何使用 RESTful Google Data API,透過程式與我的日曆互動。(編輯者註意事項:自 v3 起,Google Calendar API 已不再使用 Google Data 格式)。首先,請按一下日曆設定頁面的 按鈕,取得日曆的活動資訊提供網址:

http://www.google.com/calendar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic

您可以使用 Google 日曆說明文件做為參考,以擷取和顯示這類日曆活動,其中 PUBLIC_FEED_URL 含有活動資訊提供網址。

CalendarService myService = new CalendarService("exampleCo-fiddlerExample-1");
final String PUBLIC_FEED_URL = "http://www.google.com/calendar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic";
URL feedUrl = new URL(PUBLIC_FEED_URL);
CalendarEventFeed resultFeed = myService.getFeed(feedUrl, CalendarEventFeed.class);

System.out.println("All events on your calendar:");
for (int i = 0; i < resultFeed.getEntries().size(); i++) {
  CalendarEventEntry entry = resultFeed.getEntries().get(i);
  System.out.println("\t" + entry.getTitle().getPlainText());
}
System.out.println();

這將產生我的日曆上活動的基本清單:

All events on your calendar:
    MS150 Training ride
    Meeting with Nicole
    MS150 Information session

以上程式碼片段顯示了日曆活動的標題,但從伺服器收到的其餘資料呢?Java 用戶端程式庫無法輕鬆地將資訊提供或項目輸出為 XML 檔案,即使是 XML 檔案也不例外。與要求一併附上的 HTTP 標頭呢?查詢是否經過 Proxy 處理或重新導向?隨著作業流程越來越複雜,這些問題變得越來越重要 (尤其是出了點小狀況或問題出錯)。封包監視軟體會呈現網路流量的答案,以便回答這些問題。

tcpdump

tcpdump 是一個命令列工具,可在類似 Unix 的平台上運作,不過也有一個名為 WinDump 的 Windows 連接埠。就如同大部分的封包監視程式一樣,TCPdump 會將您的網路卡片進入超高模式 (需要超級使用者權限)。如要使用 tcpdump,只要指定要監聽的網路介面,網路流量就會傳送至 stdout:

sudo tcpdump -i eth0

如果執行這個指令,就會受到各種網路流量的無聊影響,其中有些活動無法辨識。您稍後可以將輸出結果轉送至某個檔案,並在後面加上 grep,不過這樣可能會產生一些非常龐大的檔案。大部分封包擷取軟體都內建各種篩選機制,因此您只需要擷取所需內容即可。

tcpdump 支援根據網路流量的特性篩選。舉例來說,您可以將伺服器主機名稱插入下列運算式,藉此指示 tcpdump 只擷取通訊埠 80 上的伺服器流量 (HTTP 訊息):

dst or src host <hostname> and port 80

針對符合篩選器運算式的每個封包,TCPdump 會顯示時間戳記、封包的來源和目的地以及多個 TCP 旗標。由於資訊顯示封包的傳送和接收順序,因此資訊十分重要。

查看封包內容通常也很有用。「-A」旗標會指示 tcpdump 以 ASCII 輸出每個封包,顯示 HTTP 標頭和郵件內文。「-s」標記可用來指定要顯示的位元組數 (「-s 0」表示完全不要截斷郵件內文)。

總而言之,我們會得到以下指令:

sudo tcpdump -A -s 0 -i eth0 dst or src host <hostname> and port 80

如果您執行這個指令,然後執行上述簡短的 .Java 範例,就會看到執行這項作業的所有網路通訊。您會在流量中看到 HTTP GET 要求:

22:22:30.870771 IP dellalicious.mshome.net.4520 > po-in-f99.google.com.80: P 1:360(359) ack 1 win 65535
E.....@....\...eH..c...P.=.....zP......GET /calendar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic HTTP/1.1
User-Agent: exampleCo-fiddlerExample-1 GCalendar-Java/1.0.6 GData-Java/1.0.10(gzip)
Accept-Encoding: gzip
Cache-Control: no-cache
Pragma: no-cache
Host: www.google.com
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive

您也會看到包含 Google 資料動態饋給的 200 OK 回應訊息。請注意,動態饋給會分到四個封包:

22:22:31.148789 IP po-in-f99.google.com.80 > dellalicious.mshome.net.4520: . 1:1431(1430) ack 360 win 6432
E...1 ..2.I.H..c...e.P.....z.=.:P..M...HTTP/1.1 200 OK
Content-Type: application/atom+xml; charset=UTF-8
Cache-Control: max-age=0, must-revalidate, private
Last-Modified: Mon, 11 Jun 2007 15:11:40 GMT
Transfer-Encoding: chunked
Date: Sun, 24 Jun 2007 02:22:10 GMT
Server: GFE/1.3

13da
<?xml version='1.0' encoding='UTF-8'?><feed xmlns='http://www.w3.org/2005/Atom'
xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:gCal='http://sc
hemas.google.com/gCal/2005' xmlns:gd='http://schemas.google.com/g/2005'><id>http
://www.google.com/calendar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.calendar.goo
gle.com/public/basic</id><updated>2007-06-11T15:11:40.000Z</updated><category sc
heme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2
005#event'></category><title type='text'>MS150 Training Schedule</title><subtitl
e type='text'>This calendar is public</subtitle><link rel='http://schemas.google
.com/g/2005#feed' type='application/atom+xml' href='http://www.google.com/calend
ar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic'></
link><link rel='self' type='application/atom+xml' href='http://www.google.com/ca
lendar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic
?max-results=25'></link><author><name>Lane LiaBraaten</name><email>api.lliabraa@
gmail.com</email></author><generator version='1.0' uri='http://www.google.com/ca
lendar'>Google Calendar</generator><openSearch:totalRe


22:22:31.151501 IP po-in-f99.google.com.80 > dellalicious.mshome.net.4520: . 1431:2861(1430) ack 360 win 6432
E...1!..2.I.H..c...e.P.......=.:P.. 2...sults>3</openSearch:totalResults><openSe
arch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch
:itemsPerPage><gd:where valueString=''></gd:where><gCal:timezone value='America/
Los_Angeles'></gCal:timezone><entry><id>http://www.google.com/calendar/feeds/24v
j3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic/dgt40022cui2k3j
740hnj46744</id><published>2007-06-11T15:11:05.000Z</published><updated>2007-06-
11T15:11:05.000Z</updated><category scheme='http://schemas.google.com/g/2005#kin
d' term='http://schemas.google.com/g/2005#event'></category><title type='text'>M
S150 Training ride</title><summary type='html'>When: Sat Jun 9, 2007 7am to 10am

&amp;nbsp; PDT&lt;br&gt;   &lt;br&gt;Event Status:     confirmed</summary><conte
nt type='text'>When: Sat Jun 9, 2007 7am to 10am&amp;nbsp; PDT&lt;br&gt;   &lt;b
r&gt;Event Status:     confirmed</content><link rel='alternate' type='text/html'
 href='http://www.google.com/calendar/event?eid=ZGd0NDAwMjJjdWkyazNqNzQwaG5qNDY3
NDQgMjR2ajNtNXBsMTI1YmgyaWpiYm5laDk1M3NAZw' title='alternate'></link><link rel='
self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/24v
j3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic/dgt40022cui2k3j
740hnj46744'></link><author><name>MS150 Training Schedule</name></author><gCal:s
endEventNotifications value='false'></gCal:sendEventNotifications></entry><entry

><id>http://www.google.com/cal

22:22:31.153097 IP po-in-f99.google.com.80 > dellalicious.mshome.net.4520: . 2861:4291(1430) ack 360 win 6432
E...1#..2.I.H..c...e.P.......=.:P.. ....endar/feeds/24vj3m5pl125bh2ijbbneh953s%4
0group.calendar.google.com/public/basic/51d8kh4s3bplqnbf1lp6p0kjp8</id><publishe
d>2007-06-11T15:08:23.000Z</published><updated>2007-06-11T15:10:39.000Z</updated
><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.g
oogle.com/g/2005#event'></category><title type='text'>Meeting with Nicole</title

><summary type='html'>When: Mon Jun 4, 2007 10am to 11am&amp;nbsp; PDT&lt;br&gt;
  &lt;br&gt;Where: Conference Room B &lt;br&gt;Event Status:     confirmed</summ
ary><content type='text'>When: Mon Jun 4, 2007 10am to 11am&amp;nbsp; PDT&lt;br&
gt;  &lt;br&gt;Where: Conference Room B &lt;br&gt;Event Status:     confirmed

&lt;br&gt;Event Description: Discuss building cycling team for MS150</content><l
ink rel='alternate' type='text/html' href='http://www.google.com/calendar/event?
eid=NTFkOGtoNHMzYnBscW5iZjFscDZwMGtqcDggMjR2ajNtNXBsMTI1YmgyaWpiYm5laDk1M3NAZw'
title='alternate'></link><link rel='self' type='application/atom+xml' href='http
://www.google.com/calendar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.calendar.goo
gle.com/public/basic/51d8kh4s3bplqnbf1lp6p0kjp8'></link><author><name>MS150 Trai
ning Schedule</name></author><gCal:sendEventNotifications value='false'></gCal:s
endEventNotifications></entry><entry><id>http://www.google.com/calendar/feeds/24
vj3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic/va41amq3r08dhh
kpm3lc1abs2o</id><published>20


22:22:31.190244 IP po-in-f99.google.com.80 > dellalicious.mshome.net.4520: P 4291:5346(1055) ack 360 win 6432
E..G1$..2.K.H..c...e.P.....<.=.:P.. ....07-06-11T15:10:08.000Z</published><updat
ed>2007-06-11T15:10:08.000Z</updated><category scheme='http://schemas.google.com
/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title ty
pe='text'>MS150 Information session</title><summary type='html'>When: Wed Jun 6,
 2007 4pm to Wed Jun 6, 2007 5pm&amp;nbsp; PDT&lt;br&gt;   &lt;br&gt;Event Statu
s:     confirmed</summary><content type='text'>When: Wed Jun 6, 2007 4pm to Wed
Jun 6, 2007 5pm&amp;nbsp; PDT&lt;br&gt;   &lt;br&gt;Event Status:     confirmed<

/content><link rel='alternate' type='text/html' href='http://www.google.com/cale
ndar/event?eid=dmE0MWFtcTNyMDhkaGhrcG0zbGMxYWJzMm8gMjR2ajNtNXBsMTI1YmgyaWpiYm5la
Dk1M3NAZw' title='alternate'></link><link rel='self' type='application/atom+xml'
 href='http://www.google.com/calendar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.c
alendar.google.com/public/basic/va41amq3r08dhhkpm3lc1abs2o'></link><author><name
>MS150 Training Schedule</name></author><gCal:sendEventNotifications value='fals
e'></gCal:sendEventNotifications></entry></feed>

此輸出結果包括所有 HTTP 標頭和內容,以及數個加密的 TCP 旗標。所有資料都列在這裡,但難以閱讀及理解。還有數種圖像工具可讓您輕鬆查看這項資料。

WireShark (原名 Ethereal)

Wireshark 的螢幕畫面擷取
WireShark 可透過多種方式顯示網路流量。

WireShark 是一款透過 libpcap 建構的圖形工具,與 tcpdump 相同,而且適用於 Linux、Mac OS X 和 Windows。WireShark 的 GUI 支援多種解讀封包擷取資料並進行互動的方法。例如,從網路介面擷取封包時,封包會根據所使用的通訊協定以不同顏色顯示。您也可以按時間戳記、來源、目的地和通訊協定排序流量。

如果您選取封包清單中的任一列,Wireshark 會在使用者可理解的樹狀結構的封包標頭中顯示 IP、TCP 和其他通訊協定專屬資訊。這些資料也會顯示在 HEX 和 ASCII 的畫面底部。

WireShark 的視覺性質讓網路流量更容易理解,在大多數情況下,您還是可以篩選網路流量。WireShark 提供強大的篩選功能,還支援數百種通訊協定。

提示:如要查看可用通訊協定並建構複雜的篩選器,請按一下 WireShark 視窗頂端附近的 按鈕。

如要重新建立上述 tcpdump 範例中使用的篩選器,您可以在 WireShark 篩選器方塊中插入下列運算式:

ip.addr==<your IP address> && tcp.port==80

或運用 WireShark 對 HTTP 的瞭解:

ip.addr==<your IP address> && http

這麼做可篩選拍攝結果,只顯示與此日曆互動相關的封包。按一下各個封包即可查看內容並彙整交易。

提示:在其中一個封包上按一下滑鼠右鍵,然後選擇 [追蹤 TCP 串流],即可在單一視窗中依序顯示要求和回應。

WireShark 提供多種儲存擷取資訊的方法。您可以儲存一個、部分或所有封包。如果您正在檢視 TCP 串流,只要按一下 [另存新檔] 按鈕即可儲存相關的封包。您也可以在 tcpdump 擷取中匯入輸出內容,並在 WireShark 中查看。

問題:SSL 和加密作業

封包擷取工具的一個缺點是,無法查看透過 SSL 連線加密的資料。以上範例可存取公開的資訊提供,因此不需要使用 SSL。但是,如果範例存取了私人動態饋給,用戶端就必須透過需要安全資料傳輸層 (SSL) 連線的 Google 驗證服務進行驗證。

以下回應範例與上一個範例類似,但 CalendarService 會要求使用者的日曆中繼資訊提供,這是需要驗證的私人資訊提供。如要驗證,只要呼叫 setUserCredentials 方法即可。這個方法會觸發傳送至 ClientLogin 服務的 HTTPS 要求,並從回應中擷取驗證權杖。接著,CalendarService 物件會在所有後續要求中加入驗證權杖。

CalendarService myService = new CalendarService("exampleCo-fiddlerSslExample-1");
myService.setUserCredentials(username, userPassword);
final String METAFEED_URL = "http://www.google.com/calendar/feeds/default";
URL feedUrl = new URL(METAFEED_URL);
CalendarFeed resultFeed = myService.getFeed(feedUrl, CalendarFeed.class);

System.out.println("Your calendars:");
for (int i = 0; i < resultFeed.getEntries().size(); i++) {
  CalendarEntry entry = resultFeed.getEntries().get(i);
  System.out.println("\t" + entry.getTitle().getPlainText());
}
System.out.println();

驗證及存取私人 Google Data API 資訊提供所需的網路流量:

  1. 將使用者憑證提交給 ClientLogin 服務
    • 將 HTTP POST 傳送至 https://www.google.com/accounts/ClientLogin,並在郵件內文中使用下列參數:
      • 電子郵件 - 使用者的電子郵件地址。
      • Passwd - 使用者的密碼。
      • source (來源):識別您的用戶端應用程式。應採用 CompanyName-applicationName-versionID 的格式。例如使用 ExampleCo-FiddlerSSLExample-1。
      • service - Google 日曆服務名稱為「cl」。
  2. 接收授權權杖
    • 如果驗證要求失敗,您會收到 HTTP 403 禁止狀態碼。
    • 如果成功,服務的回應就會是 HTTP 200 OK 狀態碼,以及回應內文中的三個長英數字元代碼:SIDLSIDAuthAuth 值是授權憑證。
  3. 要求私人日曆中繼資訊提供
    • 將 HTTP GET 傳送至 http://www.google.com/calendar/feeds/default,並使用以下標頭:
    • Authorization: GoogleLogin auth=<yourAuthToken>
      

嘗試執行這個程式碼片段並查看 WireShark 中的網路流量 (使用「http || ssl」做為篩選器)。您會看到與交易相關的安全資料傳輸層 (SSL) 和傳輸層安全標準 (TLS) 封包,但「ClientLogin」要求和回應封包已在「Application Data」封包中加密。別擔心,接下來我們介紹一項能實際顯示這項加密資訊的工具。

Fiddler

Fiddler 是另一種圖形封包簡化工具,但其運作方式與目前呈現的工具大不相同。Fiddler 是您的應用程式與互動之遠端服務之間的 Proxy,可有效成為中間人。Fiddler 會與您應用程式和遠端網路服務建立 SSL 連線,先從一個端點解密流量,擷取純文字,然後重新加密流量,然後再傳送流量。很抱歉,Fidler 僅適用於 Windows 以及所有 Mac 和 Linux 使用者。

注意:SSL 支援需要 Fiddler 2 版和 .NET Framework 2.0 版。

您可透過 Session Inspector 分頁查看 Fiddler 中的網路流量。最適合用來偵錯 Google Data API 問題的子分頁:

  • 標頭 - 以可收合的樹狀格式顯示 HTTP 標頭。
  • Auth (驗證):顯示驗證標頭。
  • 原始值 - 以 ASCII 文字顯示網路封包的內容

提示:按一下 Fiddler 視窗左下角的 圖示,即可開啟或關閉拍攝功能。

Fiddler 使用 .NET Framework 設定網路連線,將 Fiddler 用做 Proxy。也就是說,根據預設,您透過 Internet Explorer 或 .NET 程式碼建立的所有連線都會顯示在 Fiddler 中。不過,由於 Java 採用不同的方式設定 HTTP Proxy,因此系統不會顯示上述 Java 範例的流量。

在 Java 中,您可以使用系統屬性來設定 HTTP Proxy。Fiddler 的通訊埠是通訊埠 8888,因此安裝本機時,您可以新增下列幾行程式碼,讓 Java 程式碼使用 Fiddler 做為 HTTP 和 HTTPS 的 Proxy:

System.setProperty("http.proxyHost", "localhost");
System.setProperty("http.proxyPort", "8888");
System.setProperty("https.proxyHost", "localhost");
System.setProperty("https.proxyPort", "8888");

如果您使用這幾行程式碼執行範例,實際上實際上是從 Java 安全性套件取得謹慎的堆疊追蹤:

[java] Caused by:
  sun.security.validator.ValidatorException: PKIX path building failed:
  sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Fiddler 的螢幕畫面擷取
Fiddler 可以解密並顯示安全資料傳輸層 (SSL) 流量。

如果無法驗證來自安全資料傳輸層 (SSL) 連線中的伺服器傳回的憑證,就會發生這個錯誤。在這個例子中,不良憑證是來自 Fiddler,而且是一名中間人。Fiddler 會即時產生憑證,由於 Fiddler 並不是可信任的發卡機構,因此這些憑證會導致 Java 無法設定 SSL 連線。

注意:當您執行 Fiddler 時,使用 Internet Explorer 建立的任何安全資料傳輸層 (SSL) 連線都會觸發「安全性警示」,詢問您是否仍要改用 Spetchy 憑證。您可以按一下 [檢視憑證] 查看 Fiddler 產生的憑證。

那麼,該如何解決這個問題呢?基本上,您必須重新設定 Java 的安全性架構,才能信任所有憑證。幸好,您不需要重新發動輪盤就能體驗 Francis Labrie 的解決方案,並將 SSLUtilities.trustAllHttpsCertificates() 方法新增至上述範例。

將 Java 設定為使用 Fiddler 做為 Proxy 並停用預設憑證驗證之後,您可以執行範例,並查看所有以純文字傳輸的傳輸流量。不要竊取我的密碼!

請注意,這類驗證交易只是少部分 SSL 流量的範例。部分網路應用程式僅使用安全資料傳輸層 (SSL) 連線,因此偵錯 HTTP 流量會排除問題,而不必解密資料。

結語

Linux、Mac OS X 和 Windows 都支援 tcpdump。這款工具可協助您輕鬆找到所需內容,而且只需快速拍攝即可。不過,有些圖形工具能以容易理解的格式提供網路流量。相較於此處提及的格式,TCPdump 擁有更多選項和篩選功能。如需 tcpdump 功能的完整說明,請輸入「man tcpdump」,或是前往 tcpdump man page

WireShark 也支援 Linux、Mac OS X 和 Windows。WireShark 內建支援數百種通訊協定,讓許多應用程式都可使用,不僅是 HTTP 偵錯。這個簡介幾乎無法刮開 WireShark 的眾多功能。如需更多資訊,請輸入「man 電匯」或造訪 WireShark 網站

Fiddler 也有許多很棒的功能,但其優勢在於解密 SSL 流量的能力。如要瞭解詳情,請造訪 Fiddler2 網站

這些封包稀少的應用程式是最適合使用工具的工具,觀測到的讀者則發現大家都完全免費!下次使用 Google API 時,如果遇到一些小事,請取下其中一個網路分析工具,然後仔細查看有線電線。如果找不到問題,您可以隨時將問題張貼到討論群組。附上相關的網路訊息,可幫助其他人瞭解並診斷您的特定問題。

祝你好運,祝你好運愉快!

資源