I finally figured out the “easy” way to tether an Ubuntu laptop to an Android phone over USB without rooting the phone, provided you have remote SSH access to an Ubuntu machine somewhere else connected to the web.
The general idea is to use the phone to create a forwarded port from a laptop to some other machine with access to the web, and then to run a VPN connection over that port.
You will need:
- A phone running Android 2 or later (or maybe earlier).
- ConnectBot installed on the phone
- A “host” machine running Linux, with SSH and OpenVPN installed and on which you have root access, and which has a public IP address.
- Your Linux laptop that you want to tether, where you’ll need OpenVPN and root access again. And the Android SDK development tools (in particular, adb).
Setup on the host machine (i.e. the VPN server):
- Install OpenVPN. Start the server with the following command:
sudo /usr/sbin/openvpn --proto tcp-server --local localhost --dev tun --ifconfig 192.168.2.1 192.168.2.2
- This will set up the server to run and listen for incoming VPN connections from the localhost only, using 192.168.2.1 for itself on the VPN and expecting your laptop to be configured for 192.168.2.2 (in the last step).
- The VPN itself is set up unencrypted since the VPN connection will be running over an encrypted line (see below).
- Obviously you’ll want to do this before you leave your home, though you also have an opportunity to start it where I’ve noted it below.
On the phone:
- In Settings -> Applications -> Development turn on USB Debugging, which allows us to forward TCP connections through the USB cable.
- Connect the phone to the laptop using the USB cable.
- In ConnectBot, set up a new connection to the host machine with a SOCKS (aka dynamic) port forward on port 1080.
- Start the connection and log in to the host machine.
- If you haven’t already, start OpenVPN on the host machine at the command prompt.
On the laptop:
- Start a port forward from the laptop to the phone using:
sudo adb forward tcp:1080 tcp:1080
- Set up DNS options in an alternate /etc/resolv.conf.tether file. For instance, put “nameserver IPADDR” into the file where IPADDR is the IP address of a public nameserver (e.g. copy it from /etc/resolv.conf on the host machine).
- Start the VPN:
sudo openvpn --proto tcp-client --dev tun --socks-proxy localhost --remote localhost --ifconfig 192.168.2.2 192.168.2.1 --route 0.0.0.0 0.0.0.0 --script-security 2 system --route-up "/bin/cp /etc/resolv.conf.tether /etc/resolv.conf"
- The VPN connection first connects to the standard SOCKS port of 1080 on localhost, which adb is forwarding to the actual SOCKS proxy server on the phone. Through the proxy OpenVPN is connecting to “localhost” which is passed through the proxy to the host machine where it resolves to the host machine itself.
- The route parameter sets up a default route to forward traffic on the laptop over the VPN. And the final option sets up DNS from your preconfigured options.
I haven’t tested this really. Just some notes for later.