Reverse tethering moves a phone's traffic to a computer and out through the computer's connection. A USB cable alone does not do it: the phone needs a capture service that takes over its routing, and the computer needs a relay that carries those packets onward. The path has four hops, application, phone capture, USB relay and host egress, and each one has a different owner. This runbook builds that path, puts the host VPN where it belongs, and checks every hop before you trust the result.

Map the hops before you run anything

Each hop applies its own policy, which is why a working result at one end says nothing about the other. The application chooses a destination and a resolver, the capture service decides which traffic enters the relay, the relay forwards into host sockets, and the host's routing and VPN decide the address the destination finally sees.

HopOwnerWhat it decides
Application requestThe appDestination, resolver, address family
Capture servicePhone VpnService appWhich traffic enters the relay at all
ADB relayHost processForwarding phone flows to host sockets
Host egressHost routing and VPNExit address and host policy

Only one VPN-service client can hold the phone's capture role at a time, so a second ordinary VPN app does not stack on top of the relay. If the VPN belongs on the computer, the capture service is the access link toward that computer, not proof that a remote tunnel already protects the result.

Stage the relay before you touch the phone

Gnirehtet is the documented example of this architecture: a no-root VPN-service client on the phone plus an ADB-carried relay on the host, supporting TCP and UDP over IPv4. Its repository also states that the project is no longer actively maintained, so treat it as the reference design and a working tool for a lab, not as a supported product to standardize on across a managed fleet.

adb devices
adb shell getprop ro.build.version.release
gnirehtet run

Run adb devices first. A phone that has not accepted the host's debugging key reports as unauthorized, and the relay will not attach until the prompt on the device is accepted. gnirehtet run installs the client, starts the relay and activates the capture; on a version that separates the steps, use the documented install, relay and start subcommands instead.

ADB access is a device-control relationship, not a network setting. Authorize only a computer you control, and plan to revoke that authorization when the task is done.

Put the host VPN back in the path

The relay is an ordinary host process, so its onward connections follow the host's routing table. A full-tunnel profile carries them; a split tunnel may not. If the host VPN uses per-app controls, add the relay binary to the allowed set, otherwise the relay keeps using the physical interface while the browser looks protected.

ip route get 1.1.1.1
curl -4 https://ifconfig.me
sudo ss -tnp | grep -i relay

Run the first two commands before and after connecting the host VPN. If the address does not change, the relay is not on the tunnel, whatever the client window says. A private-only tunnel also leaves public destinations on the normal host exit, which looks like a leak but is the policy you configured.

DNS resolves on the host for relayed traffic, so the host's resolver decides which server sees the names. A private DNS setting on the phone does not carry across the relay, and a phone-side resolver test will not describe the host's lookups.

Verify each hop separately

Three checks, in this order: the phone reaches the relay, the relay reaches the destination under host policy, and the app resolves and uses that destination correctly. Stop at the first failure instead of reloading pages and guessing.

adb shell dumpsys connectivity | grep -i -A3 vpn
adb logcat -s GnirehtetRelay:V Gnirehtet:V

A VPN-network entry in the connectivity dump shows the capture service is active; the relay's own log shows whether flows are arriving. Absence in one of them splits the problem cleanly: no capture means the phone side, no flows means the host side.

A browser that works on the host proves the host browser's path, not the relay process's. Compare the addresses each one reports, and test a private resource as well as a public page, because a private-only tunnel can route one and not the other.

Tear down and choose the failure behaviour

Rollback is part of the runbook. Stop and remove the relay, uninstall the capture client, and revoke the host's debugging authorization from the phone's developer options when the task is finished.

gnirehtet stop
gnirehtet uninstall
adb kill-server

Decide what the phone should do when the relay disappears. Without an explicit choice it may fall back to mobile data and leak the traffic you were trying to route, so set the block-connections behaviour or the VPN policy deliberately and test the teardown before you rely on it.

Record the host that was authorized, the relay version, the host tunnel policy and the teardown steps. That record is what makes the next reverse-tethering setup repeatable instead of another afternoon of rediscovery.

Nuŋlɔɖi siwo ku ɖe eŋu