| Background |
| ========== |
| |
| 'usbmuxd' stands for "USB multiplexing daemon". This daemon is in charge of |
| multiplexing connections over USB to an iPhone or iPod touch. To users, it means |
| you can sync your music, contacts, photos, etc. over USB. To developers, it |
| means you can connect to any listening localhost socket on the device. usbmuxd |
| is not used for tethering data transfer, which uses a dedicated USB interface as |
| a virtual network device. |
| |
| Multiple connections to different TCP ports can happen in parallel. An example |
| (and useful) tool called 'iproxy' is included that allows you to forward |
| localhost ports to the device---allows SSH over USB on jailbroken devices, or |
| allowing access the lockdown daemon (and then to all of the file access, sync, |
| notification and backup services running on the device). |
| |
| The higher-level layers are handled by libimobiledevice. 'ifuse' is then able |
| to sit on top of this and mount your device's AFC filesystem share. |
| |
| This package contains the usbmuxd communication interface library 'libusbmuxd'. |
| |
| There is also a Python implementation of the client library in the python-client |
| directory, and an example tcprelay.py which performs a similar function to iproxy. |
| This implementation supports OSX and Windows and the new iTunes plist-based |
| usbmuxd protocol, so it is portable and will run on those operating systems with |
| no modification, using Apple's native usbmuxd. This is useful if you need to |
| tunnel to your device from another OS in a pinch. Run python tcpclient.py --help |
| for usage information. |
| |
| License |
| ======= |
| |
| The contents of this package are licensed under the GNU Lesser General Public |
| License, version 2.1 or, at your option, any later version (see COPYING.LGPLv2.1). |
| If a more permissive license is specified at the top of a source file, it takes |
| precedence over this. |
| |
| Legal |
| ===== |
| |
| Apple, iPhone, and iPod touch are trademarks of Apple Inc., registered in the |
| U.S. and other countries. |
| |
| Building |
| ======== |
| |
| ./autogen.sh |
| make |
| sudo make install |
| |
| Running (with magic) |
| ==================== |
| |
| (Unplug + replug your jailbroken device) |
| ./iproxy 2222 22 & |
| ssh -p 2222 root@localhost |
| |
| Hopefully you get the normal SSH login prompt. You may still lots of debugging |
| output for the moment. If this is getting in the way of your ssh login, then |
| run the 'ssh' command from a different xterminal or virtual console. Of course, |
| you need to have OpenSSH installed on your jailbroken device for this to work. |
| |
| If you have iFuse, you can run "ifuse <mountpoint">. This doesn't require |
| iproxy and works on all devices, jailbroken or not. |
| |
| Running (without magic) |
| ======================= |
| |
| If 'udev' is _not_ automatically running on your machine and picking up the new |
| .rules file, you will need to start usbmuxd by hand first. Check it's running |
| and that there is only one copy with 'ps aux | grep |
| usbmuxd'. |
| |
| sudo usbmuxd -U -v -v & |
| ./iproxy 2222 22 & |
| ssh -p 2222 root@localhost |
| |
| Tip: Starting SSH if disabled |
| ============================= |
| |
| If your device is rooted, but SSH isn't started and you _cannot_ (for instance, |
| cracked/broken screen) get to the Services control panel on the device, then you |
| can start the SSH service over the USB by mounting the (jailbroken) filesystem. |
| |
| You will need to mount it using 'ifuse --afc2' (to access the root directory of |
| the device), and then edit: |
| |
| /Library/LaunchDaemons/com.openssh.sshd.plist |
| |
| to _remove_ the lines: |
| |
| <key>Disabled</key> |
| <true/> |
| |
| Reboot the device and then sshd should be running. |
| |
| TODO |
| ==== |
| |
| The server currently assumes that the device is well-behaved and does not do a |
| bunch of checks like looking for the expected SEQ and ACK numbers from it. This |
| is normally not an issue, but it's annoying for debugging because lost packets |
| (which shouldn't happen, but can happen if the code is buggy) mean that stuff |
| gets out of sync and then might crash and burn dozens of packets later. |
| |
| The server needs more testing, and some optimizing. |
| |
| Someone should probably do some edge-case testing on the TCP stuff. |
| |
| The outgoing ACK handling on the server probably needs some thought. Currently, |
| when there's an outstanding ACK, we send it after a timeout (to avoid sending |
| a no-payload ACK packet for everything the phone sends us). However, there's |
| probably a better way of doing this. |
| |
| Architecture information |
| ======================== |
| |
| The iPhone / iPod Touch basically implements a rather strange USB networking |
| system that operates at a higher level. It is of course completely proprietary. |
| Generally speaking, this is what goes on in a typical usage scenario: |
| |
| 0. iTunes opens a connection to usbmuxd and asks it for device notifications |
| 1. User inserts phone into computer |
| 2. usbmuxd notices the phone and pings it with a version packet |
| 3. phone replies |
| 4. usbmuxd now considers the phone to be connected and tells iTunes |
| 5. iTunes opens another separate connection to usbmuxd and asks it to connect |
| to, say, the afc port on the device |
| 6. usbmuxd sends a pseudo-TCP SYN packet to the phone |
| 7. the phone's kernel driver receives the SYN packet and itself opens a |
| TCP connection to localhost on the afc port |
| 8. the phone replies with a pseudo-TCP SYN/ACK indicating that the port is open |
| and the connection can proceed |
| 7. usbmuxd sends a final ACK to the phone |
| 8. usbmuxd replies to iTunes with a "connection successful" message |
| 9. any data that iTunes writes to the usbmuxd socket from now on is forwarded, |
| through pseudo-TCP, through USB, back into a more regular TCP connection to |
| localhost, to the afc daemon on the phone, and vice versa |
| |
| The usbmuxd protocol is a relatively simple binary message protocol documented |
| here: |
| |
| http://wikee.iphwn.org/usb:usbmux |
| |
| Note that once a connection is established the UNIX socket essentially becomes |
| a dedicated pipe to the TCP connction and no more high-level control is |
| possible (closing the socket closes the TCP connection). Ditto for the "listen |
| for devices" mode - usbmuxd will reject any commands in such mode, and the |
| socket essentially becomes a dedicated device notification pipe. This means |
| that you need, at minimum, TWO connections to usbmuxd to do anything useful. |
| |
| On Windows, usbmuxd works the same way but a TCP connection to localhost port |
| 27015 replaces the UNIX socket. On OSX, the UNIX socket is /var/run/usbmuxd. The |
| server and client implemented here default the same /var/run/usbmuxd socket. |
| |
| The phone protocol operates over a pair of USB bulk endpoints. There is an outer |
| layer used for packet size info and a "protocol" (version and TCP are the only |
| two options), and that header is followed by TCP headers for actual data comms. |
| However, the protocol isn't actual TCP, just a custom protocol which for some |
| reason uses a standard TCP header and leaves most fields unused. |
| |
| There is no reordering or retransmission. There are no checksums, no URG, no |
| PSH, no non-ACK, no FIN. What there *is* is the SEQ/ACK/window mechanism used |
| for flow control, and RST is used as the only connection teardown mechanism (and |
| also for "connection refused"), and the connection startup is SYN/SYNACK/ACK. |
| |
| Windows are constant-scaled by 8 bits. This is legal TCP as long as the |
| corresponding option is negotiated. Of course, no such negotiation happens on |
| this protocol. |
| |
| Note that, since there are no retransmissions, there is some overlap between ACK |
| and window for flow control. For example, the server doesn't ever touch its |
| window size, and just refuses to ACK stuff if its buffers are full and the |
| client isn't reading data. The phone happily seems to stop sending stuff. |
| |
| Also, if the phone RSTs you out of nowhere, look at the packet payload for a |
| textual error message. Note: if it claims to suffer from amnesia, that probably |
| means you overflowed its input buffer by ignoring its flow control / window |
| size. Go figure. Probably a logic bug in the kernel code. |
| |
| Note that all normal packets need to have flags set to ACK (and only ACK). There |
| is no support for, erm, not-acking. Keep the ack number field valid at all |
| times. |
| |
| The usbmuxd CONNECT request port field is byte-swapped (network-endian). This is |
| even more annoying for the plist based protocol, since it's even true there |
| (where the field is plain text). So even for the plain text int, you need to |
| swap the bytes (port 22 becomes <integer>5632</integer>). I have no clue if this |
| is the case on the new plist protocol on PPC macs (is the newer iTunes available |
| for those?) |
| |
| There are a bunch of gotchas due to the USB framing, and this is even worse |
| because implementations tend to get it wrong (i.e. libusb, and this is the |
| reason for the patch). Basically, USB Bulk offers, at the low level, the ability |
| to transfer packets from 0 to wMaxPacketSize (512 here) bytes, period. There is |
| no other support for higher level framing of transfers. The way you do those is |
| by breaking them up into packets, and the final shorter packet marks the end of |
| the transfer. The critical bit is that, if the transfer happens to be divisible |
| by 512, you send a zero-length packet (ZLP) to indicate the end of the transfer. |
| Libusb doesn't set this option by default and the iPhone gets packets stuck to |
| each other, which it doesn't like. Actually, this framing is sort of redundant |
| because the usbmux packet header includes a length field, but the phone still |
| wants the ZLPs or else it breaks. To make matters worse, usbdevfs imposes a max |
| transfer size of 16k, so libusb breaks transfers into that size. This is okay |
| for sending as long as the ZLP is only added to the last transfer (the patch |
| does that), but it can easily cause nasty race conditions on RX due to libusb |
| doing multiple outstanding reads at the same time and then cancelling the rest |
| when shorter data arrives (but what if some data got into the other requests |
| already?), so we only do 16k reads and stick them together ourselves by looking |
| at the packet size header. We still depend on ZLPs being sent to end transfers |
| at non-16k boundaries that are multiples of 512, but that seems to work fine. I |
| guess the ZLPs might cause spurious 0-byte transfers to show up on RX if things |
| line up right, but we ignore those. By the way, the maximum packet/transfer size |
| is 65535 bytes due to the 16-bit length header of the usbmux protocol. |