發表文章

目前顯示的是 九月, 2015的文章

觀察 HTTP/HTTPS 傳輸的內容以及防範 man-in-the-middle attack

看到許多強者推薦 mitmproxy (MITM 是 man-in-the-middle 的意思), 試用了一下的確超好用的。它用 man-in-the-middle attack 的方式觀察 (甚至更改) HTTP/HTTPS 傳輸的內容。 How To: Use mitmproxy to read and modify HTTPS traffic 介紹原理和用法, 設定很簡單。 官方文件也很清楚, 可交叉參考:mitmproxy 0.13 - How mitmproxy works: 有附圖解說明 proxy 連線過程mitmproxy 0.13 - Linuxmitmproxy 0.13 - OSX 這裡摘要一下 mitmproxy 作為 Transparent Proxy 的方式和原理: 備好一台機器 R 作為觀察目標裝置 D (如手機) 的 gateway, 這樣就完成 man-in-the-middle 的設置。 設定 R 的 firewall, 重導往外連往 port 80 和 443 的連線到在 R 上執行的 mitmproxy。 在 D 上安裝 mitmproxy 的 certificate, 這樣 D 會相信 mitmproxy 幫自己簽的 certificate。測試 Android 手機在 MITM 情況下 App 的反應我是用 ASUS Zenfone 2, 不過 App 的測試結果應該和手機無關。 結果如下: Android OS 有出現訊息說網路可能被監控了, 但清掉訊息後就沒再出現了, 使用者應該不會注意到。 沒裝 mitmproxy certificate 的情況, Google Play 會出現連線錯誤; 裝 certificate 後可以用 Google Play 安裝 app。 沒裝 mitmproxy certificate 的情況, Chrome 會警告有問題; 有裝 certificate 會放行。 沒裝 mitmproxy certificate 的情況, Gmail 會如常運作, 看不到 HTTPS 傳的內容。裝 certificate 的後可以看到 HTTPS 傳的內容。雖然 Gmail 用自己訂的資料格式, 在搜尋信件時, 可看到搜尋字、回傳信件的標題、內文前面幾句的文字。 另外在有裝 mitmproxy c…

HTTP library 支援 gzip response body 的情況

為了節省 HTTP response 的傳輸量, HTTP 有提供 request header Accept-Encoding: gzip 要求 server 「可以的話, 用 gzip 壓縮 body 再傳回來」, 還有 response header Content-Encoding: gzip 告知 client 「response body 有用 gzip 壓縮」。 在這樣的規定下, 推測 HTTP library 可能會有兩種實作方式: 不處理。使用者自己加 request header "Accept-Encoding: gzip", 然後自己解 response body 有個 flag 開啟後會自動處理。自動加上 "Accept-Encoding: gzip", 然後自動解 response body 並且移掉 response header "Content-Encoding: gzip"。另外要註明 API 取得的 content length 是否會受 gzip 影響, 結果如何變化。 不過實際情況是: iOS NSURLConnection 文件沒有提到這件事, 但是會自動加 request header 並自動解 response body, 不過沒有移掉 response header "Content-Encoding: gzip" (Ref., 實測結果確實如此, 不需手動加 Accept-Encoding: gzip 就有作用) Android HttpURLConnection 指明預設就會作, 並會清掉 Content-Encoding 和 Content-Length。可以用 Accept-Encoding: identity 覆寫預設值 (Ref.)。 curl 開啟 flag CURLOPT_ACCEPT_ENCODING 後會支援, 也是自動加 request header 並自動解 response body, 不過沒有移掉 response header "Content-Encoding: gzip" (Ref.) 結果只有 Android 的實作符合預期。使用前還是要先測過才準啊。 附帶一提, http:/…

Android 線上原始碼

線上搜尋: AndroidXRef, 進版還滿新的 官方線上列表: https://android.googlesource.com/ 更多說明: Where can I browse Android source code on-line?

偵測網路環境是否有 Captive Portal (使用 Wi-Fi 時會先導到登入網頁)

Captive Portal 是指在可以正常用網路前, 先導到一個登入網頁, 登入後才可以正常上網。通常用在需要付費上網的地方, 或是飯店提供免費但需帳號登入的 Wi-Fi。不過不限於 Wi-Fi 連線 這樣作的好處是使用者可以透過網頁看到比較詳細的說明, 像是「使用者同意書」、「使用限制」、「收費標準」等。對於 Wi-Fi 連線的供應者, 在連上 Wi-Fi 時登入 Wi-Fi 帳號和密碼, 就無法提供這些資訊。 但缺點是使用裝置會誤以為有網路可用 (因為 Wi-Fi 層級有通), 但其實還不能用。如果用的 app 沒有作進一步的偵測, 不會開啟登入網頁, 就無法上網了。使用者會覺得「Wi-Fi 有通 app 卻不能用」, 而覺得是 app 的問題。 Android 4.0.1 開始有內建一套偵測機制 [*1], 發現有 Captive Portal 時會通知使用者: private boolean isCaptivePortal(InetAddress server) { HttpURLConnection urlConnection = null; if (!mIsCaptivePortalCheckEnabled) return false; mUrl = "http://" + server.getHostAddress() + "/generate_204"; if (DBG) log("Checking " + mUrl); try { URL url = new URL(mUrl); urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setInstanceFollowRedirects(false); urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS); urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS); urlConnection.setUseCaches(fa…

Web Proxy 是否能處理 HTTPS 連線?

在討論 HTTPS Proxy 前, 要先分清楚是在講那件事: Proxy 和 client 之間的連線用 HTTPS Proxy 允許 client 透過它往外用 HTTPS 連線 前者的好處是保護 client 和 Proxy 之間的連線, client 若是用 Wi-Fi 的話, 可藉此加密所有送出的 HTTP 連線, 防止有人偷聽 Wi-Fi 連線。 後者是本篇要討論的對象: Web Proxy 是否能支援 client 對外的 HTTPS 連線? 又是如何作到的? 畢竟 HTTPS 是基於 SSL 連線的 HTTP, 既然資料都用 SSL 加密了, Proxy 看不到 HTTP header 和 body, 要怎麼作好 Web Proxy 的角色? 用 HTTP tunnelProxy 接受 HTTP 1.1 的 CONNECT method, 讓 client 用 CONNECT 對外打通一個 TCP 連線 (又稱 HTTP tunnel), 然後只作 TCP packet forwarding, 於是 client 要作什麼都可以。比方說用 TCP 連線作 SSL handshake 轉成加密連線, 接著就可以走 HTTPS, SPDY 或 HTTP 2 了。 這個作法下, Proxy server 不知道 client 對外傳的內容, 只能經手封包, 不能作其它事。 置換 HTTPS 的 certificateProxy 一樣接受 CONNECT method 建立 HTTP tunnel, 不過在 SSL handshake 時, 換掉目的地 Web Server 回傳的 certificate, 改用 Proxy 自己的。然後分別和 client 和外部 Web Server 完成 SSL handshake, 形成這樣的連線: client <-> Proxy: 用 Proxy 的 certificate 建立 SSL 連線, 使用 key K1。 Proxy <-> 外部 Web Server: 用 Web Server 的 certificate 建立 SSL 連線, 使用 key K2。 Proxy 收到 client 的資料先用 K1 解密, 再用 K2 加密傳出去; 資料回來的時候反過來比照辦理。這樣 P…

用 Ubuntu 14.04 作為 Hotspot

最近需要模擬被擋封包的網路環境, 想想用筆電作為 hotspot 再設 firewall, 應該滿容易的。然後用手機連上 hotspot, 就可以模擬出各種擋封包的情況 (如立即回傳 connection error, 或只是 drop 封包)。 實際操作後的確很容易, 裝好 Ubuntu 14.04 後, 需要的東西都齊了, 內建的 Network Manager 有圖形介面, 點一點就可以分享 Wi-Fi。iPad/iPhone 可以連得上, 但是 Android 不行, 原因是 Ubuntu 預設 hotspot 用 Wi-Fi ad hoc mode, 但是 Android 不支援, 要改用 Wi-Fi infrastructure mode 才行。作法見 How do I create hotspots in Ubuntu 14.04?。 其它Android 4.0 後支援 Wi-Fi P2P, 可以讓 Android 裝置互連, 不過還是不支援 Wi-Fi ad hoc mode。 用 Wi-Fi ad hoc mode 的時候, iPad/iPhone 會在 Wi-Fi 列表的「裝置」看到筆電用的 SSID; 若改用 infrastructure mode 的時候, 會在 AP 列表看到筆電用的 SSID。 我有試過用 Mac OS X 作一樣的事, 但是新版 (我用 10.10.4) 內建只能用 pf 作 firewall, 和這東西不熟, 看起來沒 iptables 直覺。另外開啟 Internet Sharing 後 pf 就失效了, 就沒再深入研究。想想以後還是專心用 Linux 就好, 時間有限, 搞熟兩套 OS 的成本太高了。

HTTP POST 使用的編碼格式

三不五時會用到相關的東西, 所以花了點時間查清楚, 本篇重點是參考資料。 用 HTTP 的 POST 的時候, 參數會放在 request body, 然後用 HTTP header Content-Type 決定 request body 編碼方式。 常用的格式 ( Content-Type) 有兩種: application/x-www-form-urlencoded: HTML form 的預設值。和 GET 在 URL 後面帶的參數差不多, 用 URL encoding 編碼 (主要差異是空白字元用 '+' 取代), 適合用在簡單的資料。 multipart/form-data: 適合用在 binary data, 上傳檔案時要改用這個, 比較省空間 (檔案內容不需另外編碼)。 application/x-www-form-urlencoded 用 URL encoding 編碼, 遇到大量 binary 資料時, 資料會變大很多 (可能會到三倍)。若先用 base64 [*1] 編碼再套 URL encoding 會好一些 (變成 4/3 倍), 但還是沒有 multipart/form-data 省。 除了上述的格式也可以用 application/json 或其它格式, 不過得看 web server 是否支援。JSON 不支援 binary data, 所以有 binary data 時要先用 base64 編碼, binary 資料一樣會變 4/3 倍大。雖然 base64 會增加 1/3 倍的資料量, 但它簡單易用, 我個人滿喜歡 base64 的設計。 若目的是要壓縮上傳的文字資料, 除了 application layer 自己壓縮資料外, 也可以在 transport layer 作: 使用 HTTP header Content-Encoding: gzip 然後用 gzip 壓縮 request body [*2]。雖然 response 很常用 Content-Encoding: gzip, 但 request 很少這麼用的樣子, 需要改 web server 設定才能作用。如 apache2: 需另外設定 Input Decompression。 備註1. 嚴格來說, 要用 base64url (最後兩個…

Mac OS X 雜項常識

備忘用, 持續更新。硬體列表 (裝置沒反應時可看硬體形號找 driver) 左上角 Apple 圖示 -> About This Mac -> System Report -> Hardware 分享無線網路 (當作 hotspot )System Preference -> Internet -> Internet Sharing。開啟 Internet Sharing 後, 自訂的 pf rules 會失效。

備忘 nginx 設定

未來的某天應該會需要更了解 nginx, 現階段先隨便備忘用到的東西。request route 參考資料 Using nginx rewrite's to remove the file extension and still work with PHP-FastCGI — nullis.netModule ngx_http_core_moduleModule ngx_http_rewrite_module 用 try_files 設定 URI 對到不同 URI 的順序; 用 rewrite 改寫多種組合到同一位置。兩者都可用來實現 request route。

用 mtr 找出 routing 中有問題的節點

以前只知道用 traceroute 和 ping, 但用 traceroute 看完資訊後也不太清楚情況。用 "traceroute better" 搜了一下, 找到 mtr, 試了一下挺確不錯用。這裡有篇介紹: How To Use Traceroute and MTR to Diagnose Network Issues備忘指令 $ mtr HOSTNAME # 看 realtime 變化$ mtr -w HOSTNAME # 搜集一段時間內的資料