diff options
Diffstat (limited to 'README')
-rw-r--r-- | README | 218 |
1 files changed, 0 insertions, 218 deletions
@@ -1,218 +0,0 @@ | |||
1 | Background | ||
2 | ========== | ||
3 | |||
4 | 'usbmuxd' stands for "USB multiplexing daemon". This daemon is in charge of | ||
5 | multiplexing connections over USB to an iPhone or iPod touch. To users, it means | ||
6 | you can sync your music, contacts, photos, etc. over USB. To developers, it | ||
7 | means you can connect to any listening localhost socket on the device. usbmuxd | ||
8 | is not used for tethering data transfer, which uses a dedicated USB interface as | ||
9 | a virtual network device. | ||
10 | |||
11 | Multiple connections to different TCP ports can happen in parallel. An example | ||
12 | (and useful) tool called 'iproxy' is included that allows you to forward | ||
13 | localhost ports to the device---allows SSH over USB on jailbroken devices, or | ||
14 | allowing access the lockdown daemon (and then to all of the file access, sync, | ||
15 | notification and backup services running on the device). | ||
16 | |||
17 | The higher-level layers are handled by libimobiledevice. 'ifuse' is then able | ||
18 | to sit on top of this and mount your device's AFC filesystem share. | ||
19 | |||
20 | There is also a Python implementation of the client library in the python-client | ||
21 | library, and an example tcprelay.py which performs a similar function to iproxy. | ||
22 | This implementation supports OSX and Windows and the new iTunes plist-based | ||
23 | usbmuxd protocol, so it is portable and will run on those operating systems with | ||
24 | no modification, using Apple's native usbmuxd. This is useful if you need to | ||
25 | tunnel to your device from another OS in a pinch. Run python tcpclient.py --help | ||
26 | for usage information. | ||
27 | |||
28 | License | ||
29 | ======= | ||
30 | |||
31 | The contents of this package are licensed under the GNU General Public License, | ||
32 | versions 2 or 3 (see COPYING.GPLv2 and COPYING.GPLv3), except for libuxbmuxd | ||
33 | which is licensed under the GNU Lesser General Public License, version 2.1 or, | ||
34 | at your option, any later version (see COPYING.LGPLv2.1). If a more permissive | ||
35 | license is specified at the top of a source file, it takes precedence over this. | ||
36 | |||
37 | Legal | ||
38 | ===== | ||
39 | |||
40 | Apple, iPhone, and iPod touch are trademarks of Apple Inc., registered in the | ||
41 | U.S. and other countries. | ||
42 | |||
43 | Building | ||
44 | ======== | ||
45 | |||
46 | mkdir build | ||
47 | cd build | ||
48 | cmake .. | ||
49 | make | ||
50 | sudo make install | ||
51 | |||
52 | You should also create a 'usbmux' user that has access to USB devices on your | ||
53 | system. Alternatively, you can pass a different username after the -U argument. | ||
54 | |||
55 | Running (with magic) | ||
56 | ==================== | ||
57 | |||
58 | (Unplug + replug your jailbroken device) | ||
59 | ./iproxy 2222 22 & | ||
60 | ssh -p 2222 root@localhost | ||
61 | |||
62 | Hopefully you get the normal SSH login prompt. You may still lots of debugging | ||
63 | output for the moment. If this is getting in the way of your ssh login, then | ||
64 | run the 'ssh' command from a different xterminal or virtual console. Of course, | ||
65 | you need to have OpenSSH installed on your jailbroken device for this to work. | ||
66 | |||
67 | If you have iFuse, you can run "ifuse <mountpoint">. This doesn't require | ||
68 | iproxy and works on all devices, jailbroken or not. | ||
69 | |||
70 | Running (without magic) | ||
71 | ======================= | ||
72 | |||
73 | If 'udev' is _not_ automatically running on your machine and picking up the new | ||
74 | .rules file, you will need to start usbmuxd by hand first. Check it's running | ||
75 | and that there is only one copy with 'ps aux | grep | ||
76 | usbmuxd'. | ||
77 | |||
78 | sudo usbmuxd -U -v -v & | ||
79 | ./iproxy 2222 22 & | ||
80 | ssh -p 2222 root@localhost | ||
81 | |||
82 | Tip: Starting SSH if disabled | ||
83 | ============================= | ||
84 | |||
85 | If your device is rooted, but SSH isn't started and you _cannot_ (for instance, | ||
86 | cracked/broken screen) get to the Services control panel on the device, then you | ||
87 | can start the SSH service over the USB by mounting the (jailbroken) filesystem. | ||
88 | |||
89 | You will need to mount it using 'ifuse --afc2' (to access the root directory of | ||
90 | the device), and then edit: | ||
91 | |||
92 | /Library/LaunchDaemons/com.openssh.sshd.plist | ||
93 | |||
94 | to _remove_ the lines: | ||
95 | |||
96 | <key>Disabled</key> | ||
97 | <true/> | ||
98 | |||
99 | Reboot the device and then sshd should be running. | ||
100 | |||
101 | TODO | ||
102 | ==== | ||
103 | |||
104 | The server currently assumes that the device is well-behaved and does not do a | ||
105 | bunch of checks like looking for the expected SEQ and ACK numbers from it. This | ||
106 | is normally not an issue, but it's annoying for debugging because lost packets | ||
107 | (which shouldn't happen, but can happen if the code is buggy) mean that stuff | ||
108 | gets out of sync and then might crash and burn dozens of packets later. | ||
109 | |||
110 | The server needs more testing, and some optimizing. | ||
111 | |||
112 | Someone should probably do some edge-case testing on the TCP stuff. | ||
113 | |||
114 | The outgoing ACK handling on the server probably needs some thought. Currently, | ||
115 | when there's an outstanding ACK, we send it after a timeout (to avoid sending | ||
116 | a no-payload ACK packet for everything the phone sends us). However, there's | ||
117 | probably a better way of doing this. | ||
118 | |||
119 | Architecture information | ||
120 | ======================== | ||
121 | |||
122 | The iPhone / iPod Touch basically implements a rather strange USB networking | ||
123 | system that operates at a higher level. It is of course completely proprietary. | ||
124 | Generally speaking, this is what goes on in a typical usage scenario: | ||
125 | |||
126 | 0. iTunes opens a connection to usbmuxd and asks it for device notifications | ||
127 | 1. User inserts phone into computer | ||
128 | 2. usbmuxd notices the phone and pings it with a version packet | ||
129 | 3. phone replies | ||
130 | 4. usbmuxd now considers the phone to be connected and tells iTunes | ||
131 | 5. iTunes opens another separate connection to usbmuxd and asks it to connect | ||
132 | to, say, the afc port on the device | ||
133 | 6. usbmuxd sends a pseudo-TCP SYN packet to the phone | ||
134 | 7. the phone's kernel driver receives the SYN packet and itself opens a | ||
135 | TCP connection to localhost on the afc port | ||
136 | 8. the phone replies with a pseudo-TCP SYN/ACK indicating that the port is open | ||
137 | and the connection can proceed | ||
138 | 7. usbmuxd sends a final ACK to the phone | ||
139 | 8. usbmuxd replies to iTunes with a "connection successful" message | ||
140 | 9. any data that iTunes writes to the usbmuxd socket from now on is forwarded, | ||
141 | through pseudo-TCP, through USB, back into a more regular TCP connection to | ||
142 | localhost, to the afc daemon on the phone, and vice versa | ||
143 | |||
144 | The usbmuxd protocol is a relatively simple binary message protocol documented | ||
145 | here: | ||
146 | |||
147 | http://wikee.iphwn.org/usb:usbmux | ||
148 | |||
149 | Note that once a connection is established the UNIX socket essentially becomes | ||
150 | a dedicated pipe to the TCP connction and no more high-level control is | ||
151 | possible (closing the socket closes the TCP connection). Ditto for the "listen | ||
152 | for devices" mode - usbmuxd will reject any commands in such mode, and the | ||
153 | socket essentially becomes a dedicated device notification pipe. This means | ||
154 | that you need, at minimum, TWO connections to usbmuxd to do anything useful. | ||
155 | |||
156 | On Windows, usbmuxd works the same way but a TCP connection to localhost port | ||
157 | 27015 replaces the UNIX socket. On OSX, the UNIX socket is /var/run/usbmuxd. The | ||
158 | server and client implemented here default the same /var/run/usbmuxd socket. | ||
159 | |||
160 | The phone protocol operates over a pair of USB bulk endpoints. There is an outer | ||
161 | layer used for packet size info and a "protocol" (version and TCP are the only | ||
162 | two options), and that header is followed by TCP headers for actual data comms. | ||
163 | However, the protocol isn't actual TCP, just a custom protocol which for some | ||
164 | reason uses a standard TCP header and leaves most fields unused. | ||
165 | |||
166 | There is no reordering or retransmission. There are no checksums, no URG, no | ||
167 | PSH, no non-ACK, no FIN. What there *is* is the SEQ/ACK/window mechanism used | ||
168 | for flow control, and RST is used as the only connection teardown mechanism (and | ||
169 | also for "connection refused"), and the connection startup is SYN/SYNACK/ACK. | ||
170 | |||
171 | Windows are constant-scaled by 8 bits. This is legal TCP as long as the | ||
172 | corresponding option is negotiated. Of course, no such negotiation happens on | ||
173 | this protocol. | ||
174 | |||
175 | Note that, since there are no retransmissions, there is some overlap between ACK | ||
176 | and window for flow control. For example, the server doesn't ever touch its | ||
177 | window size, and just refuses to ACK stuff if its buffers are full and the | ||
178 | client isn't reading data. The phone happily seems to stop sending stuff. | ||
179 | |||
180 | Also, if the phone RSTs you out of nowhere, look at the packet payload for a | ||
181 | textual error message. Note: if it claims to suffer from amnesia, that probably | ||
182 | means you overflowed its input buffer by ignoring its flow control / window | ||
183 | size. Go figure. Probably a logic bug in the kernel code. | ||
184 | |||
185 | Note that all normal packets need to have flags set to ACK (and only ACK). There | ||
186 | is no support for, erm, not-acking. Keep the ack number field valid at all | ||
187 | times. | ||
188 | |||
189 | The usbmuxd CONNECT request port field is byte-swapped (network-endian). This is | ||
190 | even more annoying for the plist based protocol, since it's even true there | ||
191 | (where the field is plain text). So even for the plain text int, you need to | ||
192 | swap the bytes (port 22 becomes <integer>5632</integer>). I have no clue if this | ||
193 | is the case on the new plist protocol on PPC macs (is the newer iTunes available | ||
194 | for those?) | ||
195 | |||
196 | There are a bunch of gotchas due to the USB framing, and this is even worse | ||
197 | because implementations tend to get it wrong (i.e. libusb, and this is the | ||
198 | reason for the patch). Basically, USB Bulk offers, at the low level, the ability | ||
199 | to transfer packets from 0 to wMaxPacketSize (512 here) bytes, period. There is | ||
200 | no other support for higher level framing of transfers. The way you do those is | ||
201 | by breaking them up into packets, and the final shorter packet marks the end of | ||
202 | the transfer. The critical bit is that, if the transfer happens to be divisible | ||
203 | by 512, you send a zero-length packet (ZLP) to indicate the end of the transfer. | ||
204 | Libusb doesn't set this option by default and the iPhone gets packets stuck to | ||
205 | each other, which it doesn't like. Actually, this framing is sort of redundant | ||
206 | because the usbmux packet header includes a length field, but the phone still | ||
207 | wants the ZLPs or else it breaks. To make matters worse, usbdevfs imposes a max | ||
208 | transfer size of 16k, so libusb breaks transfers into that size. This is okay | ||
209 | for sending as long as the ZLP is only added to the last transfer (the patch | ||
210 | does that), but it can easily cause nasty race conditions on RX due to libusb | ||
211 | doing multiple outstanding reads at the same time and then cancelling the rest | ||
212 | when shorter data arrives (but what if some data got into the other requests | ||
213 | already?), so we only do 16k reads and stick them together ourselves by looking | ||
214 | at the packet size header. We still depend on ZLPs being sent to end transfers | ||
215 | at non-16k boundaries that are multiples of 512, but that seems to work fine. I | ||
216 | guess the ZLPs might cause spurious 0-byte transfers to show up on RX if things | ||
217 | line up right, but we ignore those. By the way, the maximum packet/transfer size | ||
218 | is 65535 bytes due to the 16-bit length header of the usbmux protocol. | ||