onlinemediagroup / ocaml-usbmux

Connect to your iDevices over USB at scale
114 stars 13 forks source link

ocaml-usbmux + gandalf

This is a library and command line tool to control port forwarding to jailbroken iOS devices.

Basically, it lets you do:

$ ssh root@localhost -p 2000

and you get a shell to an iDevice connected over a USB wire.

The command line tool is called gandalf and it requires that usbmuxd be running. If on OS X then you don't have to do anything, if on Linux then you need to have the open source version of usbmuxd. I recommend compiling from source, versions on most package managers are old.

Installation

You need to have opam installed, it is OCaml's package manager.

On OS X you can do:

$ brew install opam

(If on Linux, then get opam via your package manager, aka apt-get or whatever). NOTE if you are on Ubuntu, then you need to do:

$ add-apt-repository ppa:avsm/ppa
$ apt-get update
$ apt-get install ocaml opam

It is important that your compiler is up to date, you can check with opam switch, make sure its at least >= 4.02.0. Currently gandalf works with versions between ["4.02.0", "4.03.0"). Once ppx_core updates then I can update as well to let you use "4.03.0".

then

$ opam install usbmux

This will install the command line tool gandalf and an OCaml library.

gandalf usage.

The following are a series of usages of gandalf, all short form arguments have long-forms as well and -v can be added at any time.

  1. See with realtime updates what devices are connected

    $ gandalf

    This will start up gandalf in listen mode, that is it will print out whenever a device connects or disconnects.

  2. Start with a mapping file such that # start comments and consists of an array of json objects with these fields, note that name can be null and is just a nickname for this tunnel, other fields are required.

    # This is a comment
    [{"udid":"9cdfac9f74c5e18a6eff3611c0927df5cf4f2eca",
      "name":"i11", "forwarding": [{"local_port":2000, "device_port":22},
                                   {"local_port":3000, "device_port":1122}]
                                   }]
    $ gandalf -m mapping

2.1) You can also daemonize gandalf with the -d flag. NOTE: You might need to end up doing that under sudo as gandalf needs to make a pid file under /var/run.

  1. To see a pretty JSON representation of devices and their ports that are currently connected, do:

    $ gandalf -s
  2. To reload the gandalf with a new set of mappings, do:

    $ gandalf -r

    This will cancel all running threads and reload from the original mappings file, so make your changes there.

  3. To cleanly exit gandalf, do: NOTE This might require super user permissions.

    $ gandalf -e

Check out the man page, accessible with:

$ gandalf --help

or

$ man gandalf

Simple invocation:

$ sudo `which gandalf` --mappings etc/mapping --daemonize --verbose

Important Notes and Catches

  1. If you are running this on Linux, then you might get issues with usbmuxd having issues when more than around 7 devices are plugged in. This is because multiple threads are trying to call various libxml2 freeing functions. I have a forked version of libplist that usbmuxd uses, sans the memory freeing calls. Its available here. Compile and install that, then compile and install usbmuxd from source. This will leak memory but its not that much at all and I believe it to be a fixed amount.

  2. Another issue you might have is USB3.0. The Linux kernel might crap out on you after 13 devices. This is a combination of the kernel not giving enough resources and the host controller on your motherboard being crappy. The solution to this problem is to disable USB3.0 in your BIOS. To verify that USB3.0 isn't working check with lsusb

For reference, this project is currently in use given these two issues and works fine with > 20 iPhones.

Acknowledgements

  1. Much appreciation to MixRank for green lighting this project
  2. Ivg, Edwin and others on #OCaml
  3. Starting point ideas from irelay, an npm package.

Future plans

Future plans include writing C bindings to libusbmuxd itself, thereby eliminating the dependency on usbmuxd.