usbmuxd 1.0.0

usbmuxd 1.0.0

测试已测试
语言语言 CC
许可证 自定义
发布最后发布2014年12月

未指派 维护。



usbmuxd 1.0.0

  • Chris Stroud

背景

'usbmuxd' 代表 "USB 多路复用守护程序"。此守护程序负责对 iPhone 或 iPod touch 的 USB 连接进行多路复用。对于用户来说,这意味着您可以通过 USB 同步音乐、联系人、照片等。对于开发人员来说,这意味着您可以连接到设备上监听的本机 localhost 套接字。usbmuxd 不用于 tether 数据传输,它使用专用 USB 接口作为虚拟网络设备。

可以并行处理到不同 TCP 端口的多个连接。包含了一个名为 'iproxy' 的(示例和有价值的)工具,允许您将 localhost 端口转发到设备——允许在越狱的设备上进行 SSH over USB,或允许访问锁定守护程序(然后访问设备上运行的所有文件访问、同步、通知和备份服务)。

高层由 libimobiledevice 处理。'ifuse' 能够 sits 在其上并挂载您的设备上的 AFC 文件系统共享。

python-client 库中还有一个客户端库的 Python 实现,以及一个名为 tcprelay.py 的示例,它执行与 iproxy 相似的函数。此实现支持 OSX 和 Windows,以及全新的基于苹果 iTunes plist 的 usbmuxd 协议,因此它是可移植的,不需要修改就可以在这些操作系统上运行,使用苹果的本地 usbmuxd。如果您需要从其他操作系统临时连接到您的设备,这非常有用。运行 python tcpclient.py --help 以获取使用信息。

许可证

本软件包的内容受 GNU 通用公共许可证(版本 2 或 3)(见 COPYING.GPLv2 和 COPYING.GPLv3)的许可,除了 libuxbmuxd 是在 GNU Lesser General Public License,版本 2.1 或您的选择,任何后续版本(见 COPYING.LGPLv2.1)下的许可。如果一个更宽容的许可证在源文件的顶部指定,它将优先于此。

法律

苹果、iPhone 和 iPod touch 是苹果公司的商标,在美国和其他国家注册。

构建

mkdir build cd build cmake .. make sudo make install

您还应创建一个名为 'usbmux' 的用户,该用户可以访问系统中 USB 设备。或者,您可以在 -U 参数后传递不同的用户名。

运行(带有魔法)

(从您的越狱设备拔掉并重新插上)./iproxy 2222 22 & ssh -p 2222 root@localhost

希望您能收到正常的SSH登录提示。此刻可能会有大量的调试输出。如果这些调试信息影响到了您的SSH登录,那么请从其他xterminal或虚拟控制台运行'ssh'命令。当然,您需要在越狱的设备上安装OpenSSH才能使这个操作生效。

如果您有iFuse,可以运行"ifuse . 这不需要iproxy并在所有设备上工作,无论是越狱与否。

正常运行(无需魔法)

如果'udev'在您的机器上没有自动运行并拾取新的.rules文件,您需要首先手动启动usbmuxd。检查它是否正在运行,并且使用'ps aux | grep usbmuxd'查看是否存在只一个副本。

sudo usbmuxd -U -v -v & ./iproxy 2222 22 & ssh -p 2222 root@localhost

提示:SSH禁用时启动

如果您的设备已root,但SSH没有启动且您无法到达设备上的服务控制面板(例如,屏幕破损),则可以通过挂载越狱的文件系统通过USB启动SSH服务。

您需要使用'ifuse --afc2'挂载(访问设备根目录),然后编辑

/Library/LaunchDaemons/com.openssh.sshd.plist

删除以下行:

禁用

重新启动设备,然后sshd应该会启动。

待办事项

服务器目前假定设备行为良好且未进行大量检查,例如从它那里寻找预期的SEQ和ACK编号。这通常不是问题,但它在调试时很烦人,因为丢失的数据包(不应该发生,但可能会发生如果代码有bug)会导致数据不同步,然后可能会在略后的时间崩溃并烧毁数十个数据包。

服务器需要更多测试和一些优化。

应该有人做一些边界情况测试TCP部分。

服务器上对正在进行的ACK的处理可能需要一些考虑。目前,当有未完成的ACK时,我们会在超时后发送它(以避免为手机发送给我们的所有内容发送无负载ACK数据包)。但是,可能还有更好的处理方式。

架构信息

iPhone / iPod Touch基本实现了一个相当奇特的USB网络系统,它在一个更高的层级上运行。当然,它是完全专有的。一般而言,这是典型使用场景中的情况

  1. iTunes打开到usbmuxd的连接并请求设备通知
  2. 用户将手机插入电脑
  3. usbmuxd注意到手机并向它发送版本数据包
  4. 手机回复
  5. usbmuxd现在认为手机已经连接并通知iTunes
  6. iTunes打开另一个单独的连接到usbmuxd并请求将其连接到设备的afc端口
  7. usbmuxd发送一个伪TCP SYN数据包到手机
  8. 手机的内核驱动接收SYN数据包并在afc端口上自己打开TCP连接到localhost
  9. 手机回复一个伪TCP SYN/ACK指示端口已打开且连接可以继续
  10. usbmuxd向手机发送最终的ACK
  11. usbmuxd向iTunes回复一条“连接成功”的消息
  12. 从现在起,iTunes写入usbmuxd套接字的所有数据都通过伪TCP,通过USB转发回本地主机的更加规范的TCP连接,再到手机的afc守护进程,反之亦然。

usbmuxd协议是一种相对简单的二进制消息协议,在此处进行了记录

http://wikee.iphwn.org/usb:usbmux

请注意,一旦建立连接,UNIX套接字基本上就变成了一条专用的TCP连接管道,因此不可能再进行高级控制(关闭套接字将关闭TCP连接)。同样,“监听设备”模式也是如此 - usbmuxd将拒绝在此模式下的任何命令,套接字本质上变成了一条专用的设备通知管道。这意味着至少需要两个usbmuxd连接才能进行任何有用的操作。

在Windows上,usbmuxd的运行方式相同,但用本地主机端口27015的TCP连接代替了UNIX套接字。在OSX上,UNIX套接字是/var/run/usbmuxd。此处实现的客户端和服务器的默认套接字是相同的 /var/run/usbmuxd。

手机协议在一条USB大量端点上运行。有一个外层用于包大小信息和一个“协议”(版本和TCP是两种选项),然后是TCP头部,用于实际的数据通信。但是,该协议不是实际的TCP,而是一个自定义协议,出于某种原因使用了标准的TCP头部并且大多数字段未使用。

没有重新排序或重传。没有校验和,没有URG,没有PSH,没有非ACK,没有FIN。有的只是用于流量控制的SEQ/ACK/窗口机制,RST被用作唯一的连接拆除机制(以及“连接拒绝”),连接启动是SYN/SYNACK/ACK。

窗口是按8位常数缩放的。只要协商了相应的选项,这就是合法的TCP。当然,这种协商在这个协议中并没有发生。

请注意,由于没有重传,ACK和窗口之间存在一些重叠,用于流量控制。例如,服务器从不触碰其窗口大小,如果其缓冲区满了并且客户端不读取数据,就拒绝ACK。手机似乎很乐意停止发送数据。

另外,如果手机突然RST你,请查看数据包有效载荷中的文本错误信息。注意:如果它声称失去了记忆,这可能意味着你通过忽略其流量控制/窗口大小溢出了其输入缓冲区。想想吧。可能是在内核代码中的逻辑错误。

请注意,所有正常的包都需要设置标志为ACK(并且只有ACK)。不支持“不ACK”的功能。始终保持ACK号码字段有效。

usbmuxd的CONNECT请求端口号字段是字节交换的(网络端序)。这对于基于plist的协议来说尤其麻烦,因为那里也是这样(字段是纯文本)。所以即使是纯文本整型,也需要交换字节(端口22变成5632)。我不知道这是否适用于PPC mac上新的基于plist的协议(那些新版的iTunes对这些可用吗?)

由于USB帧结构,存在许多陷阱,而且这个问题更加严重,因为实现往往出错(例如libusb,这就是补丁的原因)。基本上,USB块传输在底层提供了从0到wMaxPacketSize(这里为512字节)字节数据传输的能力。没有其他支持更高层传输结构。实现这些传输的方法是将它们拆分成数据包,最后的数据包长度较短,标记传输结束。关键点是,如果传输恰好能被512整除,则需要发送一个零长度数据包(ZLP)来指示传输结束。libusb默认不设置此选项,因此iPhone数据包会粘在一起,这不是iPhone所喜好的。实际上,这种帧结构有些繁琐,因为USBmux数据包头部包含长度字段,但手机依然需要ZLP或否则会崩溃。更糟糕的是,usbdevfs施加了一个最大传输大小为16k的限制,因此libusb将传输拆分到这个大小。只要ZLP只添加到最后的传输(补丁就是这样做的),这就可以了,但它很容易在接收时由于libusb同时执行多个挂起的读取操作,然后取消剩余数据而导致恶劣的竞争条件(但如果有些数据已进入其他请求会怎么办呢?),所以我们只进行16k读取,并我们自己通过查看数据包大小头部将它们组合在一起。我们仍然依赖于在非16k边界的地方发送ZLP来结束传输,而这个地方是512的倍数,这似乎是可行的。我觉得如果事情按正确的方式排列,ZLP可能会在接收时出现虚假的0字节传输,但我们忽略了这些。顺便说一句,由于usbmux协议的16位长度头部,最大数据包/传输大小是65535字节。