Proxyman で iOS シミュレータと実機の WebSocket をデバッグする方法
iOS アプリが URLSessionWebSocketTask や、Starscream、SocketRocket などの iOS 向け WebSocket ライブラリを使っている場合、Proxyman は標準の状態では WS/WSS 通信をキャプチャできないことがあります。
理由
これは Apple が意図した仕様です。URLSessionWebSocketTask はシステムの HTTP プロキシ設定を使用しません。そのため、すべての WS/WSS 通信はインターネットへ直接送られ、Proxyman や Charles Proxy ではキャプチャできません。
この記事の内容
- 開発中に、Proxyman を使って iOS デバイス(iOS 18 以降)から WebSocket メッセージをキャプチャします。
解決方法
このチュートリアルでは、HTTP/HTTPS と WebSocket を強力にデバッグできる Proxyman を使い、開発中に iOS デバイスの WebSocket メッセージをインターセプトしてデバッグする方法を紹介します。
このチュートリアルの手順は次のとおりです。
- Proxyman を準備する
- iOS デバイス(iPhone / iPad)または iOS シミュレータに Proxyman を設定する
- Proxyman SOCKS Proxy Server を起動する
- アプリが Proxyman SOCKS Proxy Server を使うように設定する
- これで完了です。Proxyman がアプリの WebSocket メッセージをキャプチャします。URLSessionWebSocketTask に対応しています。
コードを確認したい場合は、GitHub をご覧ください。
1. Proxyman を準備する
まず、Proxyman を入手するには、Proxyman の公式サイト から直接ダウンロードするか、ターミナルを使う方法が簡単です。
$ brew cask install proxyman
2. iOS シミュレータや iOS デバイスに Proxyman を設定する
2.1 iOS シミュレータ
Certificate Menu→Install for iOS→iOS Simulatorsを選択するだけです。- 画面の手順に従って、証明書を iOS シミュレータにインストールします。(少なくとも 1 つの iOS シミュレータが必要です)
- 完了です。

2.2 iOS デバイス
Certificate Menu→Install for iOS→iOS Devicesを選択します。- 画面の手順に従って、証明書を iOS デバイスにインストールします。
- 最後のステップとして、iOS デバイスで Proxyman の証明書を信頼する設定を必ず完了してください。
- 完了です。

3. Proxyman SOCKS Proxy Server を起動する
- Proxyman アプリを開き、
Tools→Proxy Settings→SOCKS Proxy settings→Enableを選択します。 - ポート番号を控えておきます。現時点でのデフォルトのポートは
8889です。 - 完了です。

4. アプリが Proxyman SOCKS Proxy Server を使うように設定する
使用している WebSocket ライブラリに応じて、以下の手順に従ってください。
4.1 NWConnection の場合
let parameters = webSocketURL.scheme == "wss" ? NWParameters.tls : NWParameters.tcp
let options = NWProtocolWebSocket.Options()
options.autoReplyPing = true
parameters.defaultProtocolStack.applicationProtocols.insert(options, at: 0)
if #available(iOS 17.0, *) {
let socksv5Proxy = NWEndpoint.hostPort(host: "x.x.x.x", port: 8889) // Replace with your Proxyman SOCKS Proxy Server IP address
let config = ProxyConfiguration.init(socksv5Proxy: socksv5Proxy)
let context = NWParameters.PrivacyContext(description: "my socksv5Proxy")
context.proxyConfigurations = [config]
parameters.setPrivacyContext(context)
}
let connection = NWConnection(to: .url(webSocketURL), using: parameters)
connection.start(queue: .main)
4.2 URLSession と URLSessionWebSocketTask の場合
private lazy var urlSession: URLSession = {
let config = URLSessionConfiguration.default
if #available(iOS 17.0, *) {
let socksv5Proxy = NWEndpoint.hostPort(host: "x.x.x.x", port: 8889) // Replace with your Proxyman SOCKS Proxy Server IP address
let proxyConfig = ProxyConfiguration.init(socksv5Proxy: socksv5Proxy)
config.proxyConfigurations = [proxyConfig]
}
return URLSession(configuration: config, delegate: nil, delegateQueue: nil)
}()
5. 完了
これで完了です。Proxyman がアプリの WebSocket メッセージをキャプチャします 🎉

6. 別の方法
アプリのコードを変更したくない場合は、Atlantis フレームワークを使って WebSocket メッセージをキャプチャできます。
次のステップ
WebSocket について詳しくは、Proxyman の 公式ドキュメント をご覧ください。
SOCKS の設定は、デバッグビルドにのみ残してください。リリース版のアプリが開発用プロキシに依存すべきではありません。Proxyman の Automatic Setup セッションから起動した Web ブラウザやサーバーは、この iOS 向けコードを追加しなくても、キャプチャできることがよくあります。また、メッセージの情報を指定すれば、Proxyman で WebSocket の Protobuf ペイロードをデコードすることもできます。これは、バイナリのフレームを手作業で読むよりも簡単です。
Proxyman は、高性能な macOS アプリで、iOS デバイス、iOS シミュレータ、Android デバイス上のアプリやドメインからの HTTP/HTTPS リクエストをキャプチャして確認できます。
https://proxyman.com からダウンロードできます。
