如何使用 charlesproxy 检查 websocket 流量 iOS simulator/devices

How to inspect websocket traffic with charlesproxy for iOS simulator/devices

我想检查通过 web sockets 的网络流量,我无法控制网络代码,因为这是一个二进制库,我没有源代码,所以 我无法在代码的网络部分执行任何 log/breakpoint

我已经尝试使用最新版本的 CharlesProxy,它声称能够嗅探 websockets 但是当我尝试 url 并且甚至没有提到使用 websockets 的 api在从我的 iPhone.

调用的端点列表中

我已验证 CharlesProxy 配置正确,因为即使在 SSL 下我也能够检查非 websocket 流量。

所以我的问题是:有没有人找到解决方案来检查使用 CharlesProxy 通过 websockets 的流量?

注意:我在使用 iOS9

时禁用了 ATS

谢谢!

我终于找到了答案。

Charles 3.11.2 与 WebSocket 完美配合。

我使用 socketIO,所以我已经看到在协商阶段发送的 http 请求,但是 我错过了 websockets 流量。

一开始,socketIO尝试使用polling然后切换到使用websockets.

当您转到状态为 "Sending request body" 的请求时,websocket 流量是可见的,实际上是 wss:// 请求。

您甚至可以为此类流量设置专门的标签。其余消息将显示在此处。

PS1。确保您已正确连接到套接字,然后它会出现在 Charles 中。
PS2。我建议使用 socketIO 它是对像 websockets 这样的全双工流量的一个很好的增强。

更新: 显然 socket.io-client-swift v15.1.0 现在可以正确支持 SOCKS 代理。我还没有尝试过,但这意味着不再需要对红蜘蛛进行这些手动编辑。


接受的答案似乎不适用于 iOS 设备上的 Socket.IO。

Socket.IO-Client-Swift 的最新版本(撰写本文时为 15.0.0)在 iOS/OS X 上使用 Starscream 作为 WebSockets。

好消息是红蜘蛛支持 SOCKS 代理:

  1. Socket.IO 不公开 Starscream websocket 或提供任何 API 来启用 SOCKS 代理行为。

  2. 红蜘蛛内置的 SOCKS 代理使用 OS SOCKS 代理设置,设置起来很麻烦(至少对于 iOS)。

如果我有时间,我可能会提出一个 PR 来更彻底地解决这个问题,但是考虑到它需要对 Starscream 和 Socket.IO-Client-Swift 进行工作,这并不完全简单.

为了临时调试目的(这就是 Charles 的用例!),解决这个问题的最简单方法是编辑 WebSocket.swift 文件作为 Starscream 的一部分,并替换此代码:

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 代理,并将通过 Charles 路由所有 websockets 流量。

然后您需要确保在 iOS 中配置了 HTTP 代理设置(因为 HTTP 和 SOCKS 将使用相同的 IP),在 Charles 中启用了 SOCKS 代理,并且端口匹配上面代码中的端口(默认 8889)。

感谢乔纳森·埃利斯的非常有用的回答! 我正在使用 Pusher,效果很好!

但是,我发现 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)

然后按照您的描述在 Charles 中启用了 socks 代理。

再次感谢!

找到解决方法: 尝试后,我得出结论,尽管 iOS 模拟器遵循 HTTP 的系统代理设置,但未遵循 WebSocket。也不遵循 Socks5 代理设置。 但是,我们可以在Charles中使用Reverse Proxies来强制模拟器使用它。 在Charles中,点击Proxy -> Reverse Proxies,设置一个本地地址作为你的WebSocket服务器的透明代理,然后在你的new WebSocket(<address>)中使用该地址(React Native的话),然后你就可以看到你的WebSocket连接出现在 Charles