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 on which they are connected via USB, 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:
How to use Gnirehtet
Basically, just download the latest release, extract it, and execute the following command on the computer:
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.
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.
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).
- it requires root access on the computer;
- it does not work on platforms other than Linux.
You could still consider using these “TUN device” applications, they may better suit your needs.
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
You probably already used it to bypass annoying enterprise firewalls. For this purpose, just start the tunnel:
ssh my_serveur -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
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.
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.
Therefore, I developed both the client and the relay server manually.
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.
This post was initially published on medium.