web-dev-qa-db-ja.com

iOSシミュレーター/デバイスのcharlesproxyを使用してwebsocketトラフィックを検査する方法

web socketsを通過するネットワークトラフィックを検査したいのですが、これはネットワークライブラリを制御できません。ソースコードですので、コードのネットワーク部分でログ/ブレークポイントを実行できません。

私は最新バージョンのCharlesProxyを使用してみましたが、websocketを使用してurlとapiを試したときでも言及されていませんでした。 iPhoneから呼び出されたエンドポイントのリスト。

Version 3.11 release notes

SSLでもWebSocket以外のトラフィックを検査できるため、CharlesProxyが正しく構成されていることを確認しました。

だから私の質問は次のとおりです。CharlesProxyを使用してWebSocketを通過するトラフィックを検査するソリューションを見つけた人はいますか?

注:iOS9を使用する場合、ATSが無効になっています

ありがとう!

31
matanwrites

私は最終的に答えを見つけました。

Charles 3.11.2はWebSocketで完璧に動作します。

socketIO を使用しているので、ネゴシエーションフェーズ中に送信されたhttpリクエストを既に見ていますが、websocketsトラフィックを逃しました。

最初に、socketIOはpollingを使用しようとし、次にwebsocketsを使用するように切り替えます。

WebSocketトラフィックは、ステータスでリクエストにアクセスすると表示されます: "Sending request body"これは実際にはwss://要求。

この種のトラフィック専用のタブもあります。残りのメッセージはすぐそこに表示されます。

enter image description here

PS1。ソケットに正しく接続されていることを確認すると、Charlesに表示されます。
PS2。 socketIOを使用することをお勧めします。socketIOは、websocketのような全二重トラフィックの優れた拡張機能です。

22
klimat

UPDATE:socket.io-client-Swift v15.1.0はSOCKSプロキシを適切にサポートするようになりました。まだ試していませんが、Starscreamに対するこれらの手動の編集は不要になりました。


受け入れられた答えは、iOSデバイスのSocket.IOでは機能しないようです。

Socket.IO-Client-Swiftの最新バージョン(執筆時点では15.0.0)では、iOS/OS X上のWebSocketに Starscream を使用しています。

ただし、StarscreamはSOCKSプロキシをサポートしています。

  1. Socket.IOは、Starscream WebSocketを公開せず、SOCKSプロキシ動作を有効にするAPIを提供しません。

  2. Starscreamに組み込まれているSOCKSプロキシは、セットアップが面倒なOS SOCKSプロキシ設定を使用します(少なくともiOSの場合)。

時間があれば、PRを提案してこれをより徹底的に解決することもできますが、StarscreamとSocket.IO-Client-Swiftの両方に作業が必要であることを考えると、これは完全に簡単ではありません。

一時的なデバッグ目的でこれをハックする最も簡単な方法(Charlesの使用例です)は、WebSocket.Swift St​​arscreamの一部としてファイルし、次のコードを置き換えます。

if enableSOCKSProxy {
    let proxyDict = CFNetworkCopySystemProxySettings()
    let socksConfig = CFDictionaryCreateMutableCopy(nil, 0, proxyDict!.takeRetainedValue())
    let propertyKey = CFStreamPropertyKey(rawValue: kCFStreamPropertySOCKSProxy)
    CFWriteStreamSetProperty(outputStream, propertyKey, socksConfig)
    CFReadStreamSetProperty(inputStream, propertyKey, socksConfig)
}

このコードで:

let socksConfig = CFDictionaryCreateMutableCopy(nil, 0, CFNetworkCopySystemProxySettings()!.takeRetainedValue()) as! [String: Any]
let propertyKey = CFStreamPropertyKey(rawValue: kCFStreamPropertySOCKSProxy)
let ip = socksConfig["HTTPSProxy"]
let proxySocksConfig = ["SOCKSProxy": ip, "SOCKSPort": 8889, "SOCKSEnable": true] as CFDictionary // Where 8889 is the SOCKS proxy port in Charles
CFWriteStreamSetProperty(outputStream, propertyKey, proxySocksConfig)
CFReadStreamSetProperty(inputStream, propertyKey, proxySocksConfig)

これにより、SOCKSプロキシがデフォルトで有効になり、すべてのWebソケットトラフィックがCharles経由でルーティングされます。

次に、HTTPプロキシ設定がiOSで構成されていること(HTTPとSOCKSの両方に同じIPが使用されるため)、SOCKSプロキシがCharlesで有効になっていること、およびポートが上記のコードのポートと一致することを確認する必要があります(デフォルトで) 8889)。

3
Jonathan Ellis

ジョナサンエリスの非常に役立つ回答をありがとう!私はプッシャーを使用していますが、これはうまくいきました!

ただし、socksConfigが常に有効なデータを含むとは限らず、そこからIPをプルすると動作しなかったり、アプリがクラッシュしたりすることがわかりました。そこから取得しているのはローカルホストのIPだけなので、WebSocket.Swift

if enableSOCKSProxy {
    let proxyDict = CFNetworkCopySystemProxySettings()
    let socksConfig = CFDictionaryCreateMutableCopy(nil, 0, proxyDict!.takeRetainedValue())
    let propertyKey = CFStreamPropertyKey(rawValue: kCFStreamPropertySOCKSProxy)
    CFWriteStreamSetProperty(outputStream, propertyKey, socksConfig)
    CFReadStreamSetProperty(inputStream, propertyKey, socksConfig)
}

これとともに:

let propertyKey = CFStreamPropertyKey(rawValue: kCFStreamPropertySOCKSProxy)
let proxySocksConfig = ["SOCKSProxy": "127.0.0.1", "SOCKSPort": 8889, "SOCKSEnable": true] as CFDictionary // Where 8889 is the SOCKS proxy port in Charles
CFWriteStreamSetProperty(outputStream, propertyKey, proxySocksConfig)
CFReadStreamSetProperty(inputStream, propertyKey, proxySocksConfig)

そして、あなたが説明したようにチャールズの靴下プロキシを有効にしました。

再度、感謝します!

1