Tunnelling ADB through SSH

TL;DR adb start-server && ssh -R 5037:localhost:5037 remote

In my current workflow, I use a MacBook Air to ssh to a Linux machine for developing and building Fennec (mostly because the Linux box has a way beefier CPU for building than the 2-core MacBook; also it saves battery when I'm not plugged in). But since everything is on the Linux box, I needed a way to make ADB talk to my phone which is connected to my MacBook.

A quick Google search didn't reveal anything, but turns out it's pretty easy to tunnel the ADB protocol over SSH. ADB uses a client-server model. The client is the actual adb command that you use, the server is responsible for talking to the phone, and they communicate through port 5037. So to tunnel it over SSH, you simply need to add a port forwarding rule to the .ssh/config file on your local machine (in my case the MacBook). For example,

Host super-awesome-linux-box
RemoteForward 5037 localhost:5037

This way, every time the client needs to talk to the server on the Linux box, it will be forwarded to the MacBook. You do have to make sure that the ADB server is running on the MacBook, by running

adb start-server

Also, the two machines should have the same version of adb.

However, one drawback of this is that, say you go over to your Linux box while your MacBook is still ssh'd in. Because your ADB is still being forwarded, you cannot use ADB on any devices connected to the Linux box directly. One way to solve this is by using a different port for forwarding ADB,

Host super-awesome-linux-box
RemoteForward 5038 localhost:5037

This forwards the Linux port 5038 to the MacBook port 5037. Then, on the Linux box, you can tell your ADB client to use port 5038 by adding the following to your shell profile script on the Linux remote host,

if [[ -n $SSH_CONNECTION ]]; then
  export ANDROID_ADB_SERVER_PORT=5038
fi

This snippet sets the ADB client port to 5038 only when you are ssh'd in. That way, ADB over SSH will use one port, and ADB used locally will use another port.

Finally, to debug Fennec, you would need a second forwarded port for tunnelling the gdbserver protocol,

Host super-awesome-linux-box
RemoteForward 5038 localhost:5037 # adb
RemoteForward 5039 localhost:5039 # gdbserver

If you pull the latest gdbutils for JimDB, you can uncomment the following line in utils/gdbinit to use this port for gdbserver.

python feninit.default.gdbserver_port = 5039

That's it! If you have any questions, feel free to ping me (jchen) in #mobile on irc.mozilla.org


Edit: Thanks kats for pointing out an unclear part about which .ssh/config file to edit, and that you need the same version of adb.