usb-reverse-tether
Disclaimer. Provided AS IS, without warranty of any kind, express or implied. Use entirely at your own risk. The author accepts no liability for data loss, security incidents, policy violations, business interruption or any consequential damages. While it runs, every packet the phone sends leaves as this PC's own traffic, so the PC's network policy and monitoring apply to it. You are responsible for verifying which device you target, for being authorised to share this PC's network connection, and for the phone you connect. Not certified for regulated, forensic, safety-critical or high-assurance use. The LICENSE (MIT) is the governing text and prevails where it differs from this notice; see also DISCLAIMER.md.
Give an Android phone internet access through your PC over a USB cable (reverse tethering). The phone needs USB debugging. No root is needed on the phone or the PC.
This is useful when the phone has no working Wi-Fi or SIM data, for example a test phone with broken Wi-Fi.
Android's "USB tethering" goes the other way: the phone shares its internet with the PC. Windows Internet Connection Sharing over USB needs a rooted phone. This tool drives gnirehtet v2.5.1 instead, from the authors of scrcpy. gnirehtet is not bundled: it is downloaded from its GitHub release on first use and refused unless its SHA-256 matches the value pinned in this package.
Pure Python, standard library only. Works on Windows, Linux and macOS.
Contents
- Install
- Quick start
- 1. PC setup (once per PC)
- 2. Phone setup (once per phone)
- 3. Commands
- 4. Check that it works
- Troubleshooting
- How it works
- Limits and security
- Uninstall
- Measured results
- Third-party software
- License
Install
pipx install usb-reverse-tether # recommended: an isolated install with the command on PATH
pip install usb-reverse-tether # or into the current environment
Needs Python 3.11 or newer. There are no Python dependencies. python -m usb_reverse_tether works
as well as the usb-reverse-tether command.
Quick start
usb-reverse-tether doctor # read-only checks: adb, phone, settings, cached gnirehtet, java
usb-reverse-tether run # one phone attached; Ctrl+C stops it
usb-reverse-tether stop # stop the phone client and remove the adb tunnel
The first run downloads gnirehtet (a zip under 1 MB), installs the small Gnirehtet app on
the phone and asks once, on the phone, to allow a VPN connection. Tap OK.
1. PC setup (once per PC)
1.1 Requirements
- Windows 10 or 11, Linux (x86-64 for the default build) or macOS.
- Python 3.11 or newer.
- A data-capable USB cable. Charge-only cables are common and adb will not see the phone through them.
- The PC has working internet: Wi-Fi, Ethernet or VPN.
- macOS, ARM Linux, or
--java: a Java 8+ runtime (javaonPATH). gnirehtet publishes no Rust build for those platforms, so the Java build is used automatically there.
1.2 Install adb (Android platform-tools)
The tool looks for adb in this order:
- the
ADBenvironment variable (full path to the adb executable); $ANDROID_HOME/platform-toolsand$ANDROID_SDK_ROOT/platform-tools;- the Android SDK default location, where Android Studio installs it:
- Windows:
%LOCALAPPDATA%\Android\Sdk\platform-tools\adb.exe - macOS:
~/Library/Android/sdk/platform-tools/adb - Linux:
~/Android/Sdk/platform-tools/adb
- Windows:
adbonPATH.
Without Android Studio:
- Windows: download SDK Platform-Tools for Windows from
https://developer.android.com/tools/releases/platform-tools, extract it (for example to
C:\platform-tools), then add that folder toPATH: Start, "Edit environment variables for your account",Path, New,C:\platform-tools. Open a new terminal afterwards. - macOS:
brew install --cask android-platform-tools, or the zip from the page above. - Linux: your distribution's package (
sudo apt install adb,sudo dnf install android-tools), or the zip from the page above.
Check it: adb version.
1.3 USB driver and permissions
- Windows, most phones: Windows 10/11 installs a working driver automatically. Check with
adb devicesonce the phone is set up (step 2). - Windows, phone never appears (a Samsung, or an older phone): install the maker's USB driver, or the Google USB Driver from Android Studio's SDK Manager. In Device Manager, the phone should show under "Android Device" as Android Composite ADB Interface.
- Linux: if
adb devicesshowsno permissions, install your distribution'sandroid-udev-rules(or add a udev rule for the phone's vendor ID), add yourself to theplugdevgroup, log out and in, and replug. - macOS: no driver needed.
1.4 Fetch gnirehtet ahead of time (optional)
usb-reverse-tether fetch # the build for this platform
usb-reverse-tether fetch --java # the Java build
run does this automatically when needed. Builds are kept in the per-user cache:
| OS | Cache folder |
|---|---|
| Windows | %LOCALAPPDATA%\usb-reverse-tether\Cache |
| macOS | ~/Library/Caches/usb-reverse-tether |
| Linux | $XDG_CACHE_HOME/usb-reverse-tether, else ~/.cache/usb-reverse-tether |
1.5 Desktop shortcuts (Windows only)
usb-reverse-tether shortcuts
This creates two icons on your desktop:
- USB Reverse Tether (globe icon): opens a console window that runs the tether. Leave the window open while you need internet on the phone. Closing it, or pressing Ctrl+C, ends the tether. Errors stay readable in the window.
- USB Reverse Tether - Stop (red X icon): stops the tether on the phone, then closes after 5 seconds.
Options:
- Several phones attached: bake one in with
usb-reverse-tether shortcuts --serial <serial>. Find the serial withadb devices. - Remove the shortcuts:
usb-reverse-tether shortcuts --remove. - Another folder:
--dir <folder>instead of the desktop. - After reinstalling Python or moving the environment: run it again. The shortcuts run the
Python interpreter that created them (
<python> -m usb_reverse_tether) by absolute path.
The shortcuts are written through Windows PowerShell and the WScript.Shell COM object; nothing else is installed and the execution policy is not changed.
1.6 Firewall
Nothing to open. The relay listens on 127.0.0.1:31416 (this PC only), and the phone reaches it
through adb, not through the network.
2. Phone setup (once per phone)
2.1 Turn on Developer options
- Open Settings, then About phone.
- Tap Build number 7 times. On Xiaomi/Redmi/POCO, tap MIUI version (or OS version) instead. Enter your PIN if asked.
- You will see "You are now a developer".
Where Developer options lives:
| Phone | Path |
|---|---|
| Pixel, Nothing, most phones | Settings, System, Developer options |
| Xiaomi / Redmi / POCO | Settings, Additional settings, Developer options |
| Samsung | Settings, Developer options (near the bottom) |
2.2 Turn on USB debugging
- In Developer options, turn on USB debugging.
- Plug the phone into the PC.
- On the phone, the "Allow USB debugging?" prompt appears. Tick Always allow from this computer, then tap Allow.
- Check on the PC:
adb devices(orusb-reverse-tether doctor) must list the phone asdevice.unauthorizedmeans the prompt was not accepted. Unplug, plug back in, and accept it.offlinemeans adb lost the connection. Replug, or runadb kill-serverand try again.- Nothing listed means a cable or driver problem (see 1.1 and 1.3).
2.3 Xiaomi / Redmi / POCO only (MIUI, HyperOS)
In Developer options, also turn on:
- Install via USB. Without it, the first run fails with
INSTALL_FAILED_USER_RESTRICTED: Install canceled by user. - USB debugging (Security settings). Without it, starting fails with a
WRITE_SECURE_SETTINGSpermission denial.
MIUI allows these only with a SIM card inserted and a Mi account signed in. Each one shows a
warning with a countdown; accept it. run and doctor detect MIUI and HyperOS and remind you.
2.4 Android 14 and newer (other makers)
If starting fails with WRITE_SECURE_SETTINGS, turn off Disable permission monitoring in
Developer options, if your phone has it.
2.5 First run on a phone
- Start the tether (section 3).
- gnirehtet installs the small Gnirehtet app on the phone.
- The phone asks "Connection request: Gnirehtet wants to set up a VPN connection". Tap OK. This happens only once per phone, or again after the app is reinstalled.
- A key or VPN icon appears in the status bar, plus a "Reverse tethering enabled" notification.
2.6 Optional, for apps that wait for Wi-Fi
Android treats this connection as metered, like mobile data (see Limits). Apps that only download "over Wi-Fi" will wait. For the Play Store: Play Store, profile picture, Settings, Network preferences, App download preference, then choose Over any network. Do the same for auto-update if you want updates to run.
3. Commands
usb-reverse-tether run # exactly one phone attached; Ctrl+C stops it
usb-reverse-tether run --serial 6b8396a30406 # pick a phone when several are attached
usb-reverse-tether run --dns 10.0.0.53 # other DNS server(s), comma-separated IPv4
usb-reverse-tether run --java # Java relay instead of Rust (needs java on PATH)
usb-reverse-tether stop [--serial S] [--java] # stop the phone client and remove the tunnel
usb-reverse-tether doctor [--serial S] # read-only checks
usb-reverse-tether fetch [--java] # download and verify gnirehtet ahead of time
usb-reverse-tether shortcuts [--serial S] [--remove] [--dir D] # Windows desktop shortcuts
usb-reverse-tether --help # full help, with the disclaimer
Add -v before the command for debug logging (usb-reverse-tether -v run).
run picks the only attached device unless --serial is given, prints a notice that the phone's
traffic will leave as the PC's traffic, detects MIUI/HyperOS and prints the two-toggle hint, then
runs gnirehtet run <serial> -d <dns> with its output streamed to the console. Ctrl+C stops the
relay and the phone client.
DNS: the default is 8.8.8.8 (Google). Use --dns with your network's DNS server if public
DNS is blocked, for example on some company networks.
doctor never changes anything on the phone. It reports: adb path and version; every attached
device and its state, with what to do about unauthorized, offline and no permissions; the
Android version; MIUI/HyperOS with the two toggles; whether the Gnirehtet app is installed; whether
the cached gnirehtet build is present and still matches its verified zip; and whether java is
available. It exits 1 if anything is marked FAIL.
Exit codes: 0 ok (including Ctrl+C after a run), 1 adb or device not found, 2 download, checksum or extract failure, or unsupported on this platform. Any other code is gnirehtet's own.
After a phone reboot or unplug
The tunnel does not survive a reboot or unplug. Start it again (shortcut, or Ctrl+C and run).
Once the app is installed this takes about 2 seconds.
4. Check that it works
- For a clean test, turn off the phone's Wi-Fi and mobile data so the tether is its only
network. On a dual-SIM phone, LTE can stay up even when one SIM's data looks off. Run
adb shell svc data disableto be sure, andadb shell svc data enableafterwards. - Open a website in the phone's browser. It should load, and the console on the PC logs lines
like
TcpConnection: 10.0.0.2:xxxxx -> <server>:443 Open. - Do not test with
ping. ICMP is not relayed, sopingfails even when the tether works.
Check from the PC:
adb shell dumpsys connectivity | grep "type: VPN" # tunnel network is up (PowerShell: Select-String)
adb reverse --list # shows localabstract:gnirehtet tcp:31416
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
Need exactly one attached device, found 0 |
Phone not visible to adb | Check the cable, the USB debugging prompt and adb devices (2.2); doctor explains each state |
Need exactly one attached device, found 2 |
Several phones or emulators | Use --serial, or shortcuts --serial |
adb not found |
adb not installed or not where the tool looks | Section 1.2, or set ADB to its full path |
no permissions (Linux) |
No udev rule for the phone | Section 1.3 |
INSTALL_FAILED_USER_RESTRICTED |
MIUI blocks installs over USB | Turn on Install via USB (2.3) |
WRITE_SECURE_SETTINGS / Permission Denial |
MIUI security setting, or Android 14 permission monitoring | 2.3 or 2.4 |
Checksum mismatch |
The download was corrupted or replaced | It was deleted; run again. If it repeats, do not work around it |
java not found on PATH |
macOS, ARM Linux or --java without Java |
Install a Java 8+ runtime |
| Hangs at "Starting client", no VPN prompt | Known gnirehtet issue #515 | adb uninstall com.genymobile.gnirehtet, then start again and accept the prompt |
| VPN icon shows but nothing loads | Issues #531/#587, or a stale tunnel after replugging | stop, start again; if it persists, use --java |
device '<serial>' not found while running |
The phone rebooted or was unplugged | Plug in, wait for boot, start again |
| Play Store says Pending or "Waiting for Wi-Fi" | The tether counts as metered | 2.6: App download preference "Over any network" |
An app shows a server error such as YouTube [400], but the browser works |
The app itself is outdated; the network is fine | Update the app from the Play Store (after 2.6) |
| Certificate errors on every HTTPS site | The PC is behind a TLS-inspecting proxy (company network) | Use a network without inspection, or install that proxy's root CA on the phone (issue #586) |
| Some sites fail, others load | IPv6-only sites (the tether is IPv4 only) or blocked public DNS | Try --dns <your DNS> |
How it works
phone app (VpnService, "Gnirehtet")
| captures all phone traffic as IP packets
v
adb reverse localabstract:gnirehtet -> tcp:31416 (over the USB cable)
|
v
relay on this PC, 127.0.0.1:31416 (gnirehtet)
| opens ordinary TCP/UDP sockets
v
the PC's own internet connection (Wi-Fi, Ethernet, VPN)
The phone's traffic leaves as this PC's own traffic, so no routing or Internet Connection Sharing is set up on the PC. The tool:
- finds adb and the phone;
- makes sure the pinned gnirehtet build is in the cache: it downloads the release zip to a temporary folder, checks its SHA-256 against the pinned value (and deletes it on a mismatch), checks that no zip entry would land outside the target folder, extracts it, and only then moves it into place;
- runs
gnirehtet run <serial> -d <dns>withADBandGNIREHTET_APKset. That installs the app if needed, sets upadb reverse, starts the VPN on the phone and runs the relay until Ctrl+C. Ctrl+C stops both.
Which gnirehtet build is used:
| Platform | Build |
|---|---|
| Windows (x64; ARM64 through emulation) | gnirehtet-rust-win64-v2.5.1.zip |
| Linux x86-64 | gnirehtet-rust-linux64-v2.5.1.zip |
macOS, other Linux CPUs, --java anywhere |
gnirehtet-java-v2.5.1.zip (runs with java -jar) |
Limits and security
-
IPv4 only: TCP and UDP, no IPv6, no ICMP (
ping). There is no inbound port forwarding to the phone. -
Always metered, cannot be changed without root. "Wi-Fi only" downloads wait (see 2.6). Android (AOSP) marks any VPN with no physical network underneath as metered. The code checked was
Vpn.applyUnderlyingCapabilitieson Android 10 andConnectivityService.applyUnderlyingCapabilitieson Android 12 to 15. With no underlying network, both take theif (!hadUnderlyingNetworks) { metered = true; }branch. So these do not help:- patching gnirehtet to call
setMetered(false)orsetUnderlyingNetworks(...); cmd netpolicy set metered-network, which only applies to saved Wi-Fi networks.
The fix has to be per app, such as the Play Store's "Over any network" setting.
- patching gnirehtet to call
-
Needs the cable and the console: the tunnel exists only while the relay runs and the cable is in. A reboot or unplug drops it, and with the phone's own Wi-Fi and data off it then has no internet at all.
-
PC network policy applies: all of the phone's traffic leaves as this PC's traffic, so your network's proxy, TLS inspection, monitoring and acceptable-use rules cover it. Check that you are allowed to do this on a company network.
-
The phone can reach this PC's localhost:
10.0.2.2on the phone maps tolocalhoston this PC, so any service bound to loopback here is reachable from the phone. -
Unauthenticated relay: it listens on
127.0.0.1:31416only, so the LAN cannot reach it, but any local process on the PC could use it while it runs. -
Unmaintained upstream: gnirehtet's last release (v2.5.1) was in 2023. It still works, but bugs on new Android versions will not be fixed upstream.
Uninstall
usb-reverse-tether stop
adb uninstall com.genymobile.gnirehtet # removes the app from the phone
usb-reverse-tether shortcuts --remove # Windows, if you created them
pipx uninstall usb-reverse-tether # or: pip uninstall usb-reverse-tether
Then delete the cache folder (see 1.4). Optionally turn off USB debugging on the phone.
Measured results
Measured on Oct-21-2026 with a Redmi 7A (Android 10, MIUI 12.5), PC on Wi-Fi (Windows 11), with the pinned gnirehtet v2.5.1 Rust build. Most results come from this tool's PowerShell predecessor, which runs the same gnirehtet commands.
This package on the same phone: usb-reverse-tether 0.1.0 was installed from the wheel and run
against the phone.
runconnected in 3 s.- With the tunnel as the phone's only network, a Wikipedia page loaded over HTTPS. The relay log showed the connection.
stopexited 0, removed theadb reverseforward and closed the VPN.doctorpassed every check.
Setup
- First run: failed with
INSTALL_FAILED_USER_RESTRICTEDuntil both MIUI toggles (2.3) were on. - After that: the app install, start and first connection took 14 s. Later starts took about 2 s.
What worked
- Browser: with the phone's Wi-Fi and mobile data off, https://www.wikipedia.org loaded and a YouTube video played in Chrome.
- Downloads: Play Store and MIUI app updates downloaded.
- Shortcuts: both desktop shortcuts of the PowerShell version worked.
What needed attention
- YouTube app: version 16.06.34 (2021) showed "There was a problem with the server [400]". The network was fine; the app was too old. Its Play Store update sat at Pending for about 2 minutes, then installed (21.40.165). After that the app loaded normally over the tether.
Third-party software
gnirehtet by Genymobile, licensed under the Apache License 2.0. It is not bundled with this package. On first use the tool downloads the official v2.5.1 release asset from https://github.com/Genymobile/gnirehtet/releases/tag/v2.5.1 and verifies it against these SHA-256 values:
| File | SHA-256 |
|---|---|
gnirehtet-rust-win64-v2.5.1.zip |
7f5b1063e7895182aa60def1437e50363c3758144088dcd079037bb7c3c46a1c |
gnirehtet-rust-linux64-v2.5.1.zip |
dee55499ca4fef00ce2559c767d2d8130163736d43fdbce753e923e75309c275 |
gnirehtet-java-v2.5.1.zip |
816748078fa6a304600a294a13338a06ac778bcc0e57b62d88328c7968ad2d3a |
This project is not affiliated with or endorsed by Genymobile.
License
MIT, see LICENSE. The LICENSE is the governing text; DISCLAIMER.md is a plain-language summary of it and of the risks.
Metadata
Release files for usb-reverse-tether 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| usb_reverse_tether-0.1.0.tar.gz | 35.2 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| usb_reverse_tether-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 66.4 kB
Release files / usb_reverse_tether-0.1.0.tar.gz
| Download URL | usb_reverse_tether-0.1.0.tar.gz |
|---|---|
| Size | 35.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
42c411cedd355b2b57e8539ef095e4fea123d9f5761301a4286af882f8435307
|
|
BLAKE2b-256 checksum How to use checksums |
be41c5bae4ffd5f67d03e3746933ca0562028216e8b89d80b10261502e446dc4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.5
|
Release files / usb_reverse_tether-0.1.0-py3-none-any.whl
| Download URL | usb_reverse_tether-0.1.0-py3-none-any.whl |
|---|---|
| Size | 31.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ca2751501e67b994240334f37efb7cbc29fd6329d44ac49ed906577d00c8f0aa
|
|
BLAKE2b-256 checksum How to use checksums |
5a53fe9f257fe4614e7a58fe2d529d6ad845de2703a43787803af34ce0eeea2e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.5
|
Security for usb-reverse-tether 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.