如何使用 charlesproxy 为 iOS 模拟器/设备检查 websocket 流量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33090087/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 07:58:13  来源:igfitidea点击:

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

iossocketswebsocketcharles-proxycfnetwork

提问by matanwrites

I would like to inspect network traffic going through web sockets, I have no control over the networking code as this is a binary lib for which I do not have the source code, so I cannot do any log/breakpointin the networking part of the code.

我想检查通过web sockets 的网络流量,我无法控制网络代码,因为这是一个二进制库,我没有源代码,所以我不能在网络部分做任何日志/断点代码。

I have tried using the latest version of CharlesProxywhich claim to be able to sniff websockets however when I tried the url and apis using websockets were not even mentionned in the list of endpoints called from my iPhone.

我曾尝试使用最新版本的CharlesProxy,它声称能够嗅探 websockets 但是当我尝试使用 websockets 的 url 和 apis 时,甚至没有在从我的 iPhone 调用的端点列表中提到。

Version 3.11 release notes

版本 3.11 发行说明

I have verified that CharlesProxy is configured correctly as I am able to inspect non-websocket traffic even under SSL.

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

So my question is: did anyone find a solution to inspect traffic going through websockets with CharlesProxy?

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

Note: I have ATS disabled when using iOS9

注意:我在使用 iOS9 时禁用了 ATS

Thanks!

谢谢!

采纳答案by klimat

I finally found the answer.

我终于找到了答案。

Charles 3.11.2 works perfectly with WebSocket.

Charles 3.11.2 与 WebSocket 完美配合。

I use socketIO, so I've already seen http requests sent during the negotiation phase, but I missed websockets traffic.

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

In the beginning, socketIO try to use pollingthen switches to use websockets.

一开始,socketIO 尝试使用轮询,然后切换到使用websockets

The websocket traffic is visible when you go to the request with status: "Sending request body"which is actually wss://request.

当您转到状态为“发送请求正文”的请求时,可以看到 websocket 流量,这实际上是wss://请求。

You even have a dedicated tab for this kind of traffic. The rest of messages will appear right there.

你甚至有一个专门针对这种流量的标签。其余的消息将出现在那里。

enter image description here

在此处输入图片说明

PS1. Ensure you're connected to socket properly then it appears in Charles.
PS2. I suggest using socketIO it's a great enhancement for full-duplex traffic like websockets.

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

回答by Jonathan Ellis

UPDATE:Apparently socket.io-client-swift v15.1.0 now properly supports SOCKS proxy. I have not yet tried it, but it would mean that these manual edits to Starscream are no longer required.

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



The accepted answer does not seem to work with Socket.IO on iOS devices.

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

The latest version of Socket.IO-Client-Swift (15.0.0 at the time of writing) uses Starscreamfor WebSockets on iOS/OS X.

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

The good news is that Starscream supports SOCKS proxying however:

好消息是 Starscream 支持 SOCKS 代理:

  1. Socket.IO does not expose the Starscream websocket or provide any API for enabling the SOCKS proxying behaviour.

  2. The SOCKS proxying built into Starscream uses the OS SOCKS proxy settings which are cumbersome to setup (at least for iOS).

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

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

If I get some time I might propose a PR to address this more thoroughly, but given that it requires work to both Starscream and Socket.IO-Client-Swift, this is not entirely straightforward.

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

The easiest way to hack around this for temporary debugging purposes (which is the use case for Charles!), is to edit the WebSocket.swiftfile as part of Starscream, and replace this code:

出于临时调试目的(这是 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)
}

with this code:

使用此代码:

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)

This will ensure the SOCKS proxy is enabled by default, and will route all the websockets traffic via Charles.

这将确保默认情况下启用 SOCKS 代理,并将通过 Charles 路由所有 websockets 流量。

You then need to ensure that the HTTP proxy settings are configured in iOS (since the same IP will be used for both HTTP and SOCKS), SOCKS proxy is enabled in Charles, and that the port matches the port in the code above (by default 8889).

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

回答by Andrew Paul Simmons

Thanks for your very very helpful answer Jonathan Ellis! I'm using Pusher and this worked great!

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

However, I found socksConfigto not always contain valid data and didn't work or would crash the app when I pulled the IP from there. Since the only thing we are getting from there is the localhost IP I just replaced the following in WebSocket.swift

但是,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)
}

with this:

有了这个:

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)

And then enabled the socks proxy in Charles as you described.

然后按照您的描述在查尔斯中启用袜子代理。

Thanks Again!

再次感谢!