Although I've had an Android based phone for a while (the ADP1, the developer version of the T-Mobile G1) since I recently purchased what is now a Linux based laptop (Fedora 11 x86_64, to be exact) I'm now interested in tethering (network connectivity via the phone's USB data cable). Jump to the download section to download my scripts without reading this long blog post.
There are other ideas that are quite similar to what I'll propose in this blog post. For example, consider this post by DaveCC in an Android forum which talks about using creating a VPN with a slightly different approach.
Alternative Tethering Solutions
Tethering Android phones can be approached multiple ways. The easiest and most expensive is the official solution - get a T-Mobile webConnect USB Laptop Stick. I have not tried this so I don't know if it works in Linux.
However, I have tried various free solutions. For example, Graham Stewart has released a free SOCKS based proxy which can be found here. Although the SOCKS solution is close to what I need I'm interested in the additional privacy and possibly performance (I suspect that establishing new TCP/IP connections via 3G may not be terribly fast, but I don't have good data) that can be obtained by fully tunnelling all of my traffic. Also, nature of the connection is transparent to most applications.
I've also tried creating SOCKS connections with ConnectBot. Unfortunately due to this bug, which is fixed but not yet in the Android Market at the time this was written, the connections originate from the phone instead of the target endpoint.
The constraints I've mentioned suggest a VPN solution such as OpenVPN, which is what I ended up doing. The rest of this blog post talks about how I directed the traffic through the OpenVPN client, though the USB cable, through 3G via SSH, into my desktop's OpenVPN server and finally out to the Internet via IP Masquerading.
Android Debug Bridge
The first step is to get the Android Debug Bridge up and running so that you have a working adb executable that responds to things such as
adb -d shell
Next, choose a way of starting the OpenVPN client. Although it should be possible to use the OpenVPN GUI interface provided by the NetworkManager-openvpn plugin to NetworkManager there is a constraint that makes it difficult. See this bug that I opened for details on that constraint.
Due to my difficulty in getting NetworkManager to adapt to this particular case I ended up working with OpenVPN directly on both the client and server. I followed the directions that can be found here and then additionally made the connection TCP instead of UDP to make tunneling easier. On the client I ended up placing the certificates in /etc/openvpn/client for reasons having to do with SELinux that I'll explain.
With this approach there are two issues with getting the OpenVPN client to work with SELinux.
One way of addressing the first issue is to places files OpenVPN needs to read somewhere under /etc/openvpn and then using restorecon to set the types:
restorecon -R /etc/openvpn/client
For the second issue semanage can be used to allow access to additional ports:
semanage port -a -t openvpn_port_t -p tcp 9411
If you have not already make sure ConnectBot is installed from the Android Market. Create a connection to the OpenVPN server. Create a local port forward to forward port 1194 to localhost:1194. Make sure this connection is open prior to attempting to start the OpenVPN connection.
I've written some small scripts that can be used to start and stop the VPN connection. The scripts setup an OpenVPN connection that uses port 9411 on localhost as the gateway; which adb is listening to. The scripts can be downloaded from the download section.
To start the OpenVPN connection:
To stop the OpenVPN connection:
The latest scripts may be downloaded by clicking here.