Introducing “gnirehtet”, a reverse tethering tool for Android

A cross-platform tool providing internet access to Android devices through USB

This article is also available in French on my personal blog.

I spent the last few weeks at Genymobile developing a tool providing reverse tethering for Android, so that devices may use the internet connection of the computer they are plugged in, without requiring any root access (neither on the device nor on the computer). It works on GNU/Linux, Windows and Mac OS.

We decided to open source it under the name gnirehtet.

Yeah, that’s a weird name, until you realize that this is the output of this bash command:

rev <<< tethering

How to use gnirehtet

Basically, just download the latest release, extract it, and execute the following command on the computer:

./gnirehtet rt

Once activated, a “key” logo appears in your device status bar:

Check the README file of the project for more details.

How does gnirehtet work?

Gnirehtet is composed of two parts:

an Android application (the client);

a Java desktop application (the relay server).

Since then, I rewrote it in Rust.

The client registers itself as a VPN, in order to intercept the whole device network traffic, as byte[] of raw IPv4 packets, which it transmits to the relay server over a TCP connection (established over adb).

The relay server parses the packets headers, open connections from the computer to the requested destinations, and relays the content in both directions following the UDP and TCP protocols. It creates and sends response packets back to the Android client, which writes them to the VPN interface.

In a sense, the relay server behaves like a NAT, in that it opens connections on behalf of private peers. However, it differs from standard NATs in the way it communicates with the clients (the private peers), by using a very specific (though simple) protocol over a TCP connection.

Relay server architecture

For more details, you can read the developers page.

Here are the solutions I have considered

Once the application is able to intercept the whole device network traffic, several alternative designs are possible.

TL;DR: I first considered creating a “TUN device” on the computer, but it did not suit our needs. Then I wanted to benefit from existing SOCKS servers, but some constraints prevented us to relay UDP traffic. So I implemented gnirehtet.

TUN device

During my investigations on how to implement reverse tethering, I first found projects creating a TUN device on the computer ( vpn-reverse-tether and SimpleRT ).

This design works very well, and has several advantages:

it operates at network level, so there is no need for translation between level 3 and level 5 of the OSI model;

all IP packets are tunneled, regardless of their transport protocol (so they are all supported, while gnirehtet “only” supports TCP and UDP).

However:

it requires root access on the computer;

it does not work on platforms other than Linux.

You could consider using these “TUN device” applications, they may better suit your needs.

SOCKS

In order to avoid to develop a specific relay server, my first idea was to make the client talk the SOCKS protocol (according to RFC 1928). That way, it would be possible to use any existing SOCKS server, for instance the one provided by ssh -D .

You probably already used it to bypass annoying enterprise firewalls. For this purpose, just start the tunnel:

ssh my_server -ND1080

Then configure your browser to use the SOCKS proxy localhost:1080 . Also take care to enable remote DNS resolution if you want to resolve domain names from my_server (in Firefox, enable network.proxy.socks_remote_dns in about:config ).

Unfortunately, the OpenSSH implementation does not support UDP, although the SOCKS5 protocol itself does. And we do need UDP, at least for DNS requests (and also NTP).

If you read carefully the two last paragraphs, you might want to ask yourself:

How may Firefox resolve domain names remotely through the OpenSSH SOCKS proxy if it does not even support UDP?

The answer lies in the section 4 of the RFC: the requested destination address may be an IPv4, an IPv6 or a domain name. However, using this feature implies that the client (e.g. Firefox) is aware of the proxy (since it must explicitly pass the domain name instead of resolving it locally), while our reverse tethering must be transparent.

But all is not lost. OK, OpenSSH does not support UDP, but this is just a specific implementation, we could consider another one. Unfortunately, SOCKS5 requires to relay UDP over UDP, but the devices and the computer communicate over adb (thanks to adb reverse ), which does not support UDP port forwarding either.

Maybe we could at least relay DNS requests by forcing them to use TCP, like tsocks does:

tsocks will normally not be able to send DNS queries through a SOCKS server since SOCKS V4 works on TCP and DNS normally uses UDP. Version 1.5 and up do however provide a method to force DNS lookups to use TCP, which then makes them proxyable.

But then, SOCKS was no longer attractive to me for implementing reverse tethering.

Gnirehtet

Therefore, I developed both the client and the relay server manually.

This blog post and several open source projects ( SimpleRT , vpn-reverse-tether , LocalVPN and ToyVpn ) helped me a lot to understand how to implement this solution.

Conclusion

Gnirehtet allows Android devices to use the internet connection from a computer easily, without any root access. It helps when you can’t access the network using a WiFi access point.

I hope it will be useful to some of you.