Skip to main content

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

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 (java on PATH). 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:

  1. the ADB environment variable (full path to the adb executable);
  2. $ANDROID_HOME/platform-tools and $ANDROID_SDK_ROOT/platform-tools;
  3. 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
  4. adb on PATH.

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 to PATH: 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 devices once 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 devices shows no permissions, install your distribution's android-udev-rules (or add a udev rule for the phone's vendor ID), add yourself to the plugdev group, 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 with adb 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

  1. Open Settings, then About phone.
  2. Tap Build number 7 times. On Xiaomi/Redmi/POCO, tap MIUI version (or OS version) instead. Enter your PIN if asked.
  3. 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

  1. In Developer options, turn on USB debugging.
  2. Plug the phone into the PC.
  3. On the phone, the "Allow USB debugging?" prompt appears. Tick Always allow from this computer, then tap Allow.
  4. Check on the PC: adb devices (or usb-reverse-tether doctor) must list the phone as device.
    • unauthorized means the prompt was not accepted. Unplug, plug back in, and accept it.
    • offline means adb lost the connection. Replug, or run adb kill-server and 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_SETTINGS permission 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

  1. Start the tether (section 3).
  2. gnirehtet installs the small Gnirehtet app on the phone.
  3. 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.
  4. 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

  1. 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 disable to be sure, and adb shell svc data enable afterwards.
  2. 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.
  3. Do not test with ping. ICMP is not relayed, so ping fails 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:

  1. finds adb and the phone;
  2. 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;
  3. runs gnirehtet run <serial> -d <dns> with ADB and GNIREHTET_APK set. That installs the app if needed, sets up adb 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.applyUnderlyingCapabilities on Android 10 and ConnectivityService.applyUnderlyingCapabilities on Android 12 to 15. With no underlying network, both take the if (!hadUnderlyingNetworks) { metered = true; } branch. So these do not help:

    • patching gnirehtet to call setMetered(false) or setUnderlyingNetworks(...);
    • 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.

  • 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.2 on the phone maps to localhost on this PC, so any service bound to loopback here is reachable from the phone.

  • Unauthenticated relay: it listens on 127.0.0.1:31416 only, 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.

  • run connected in 3 s.
  • With the tunnel as the phone's only network, a Wikipedia page loaded over HTTPS. The relay log showed the connection.
  • stop exited 0, removed the adb reverse forward and closed the VPN.
  • doctor passed every check.

Setup

  • First run: failed with INSTALL_FAILED_USER_RESTRICTED until 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)

Source distribution for usb-reverse-tether 0.1.0
File Size Uploaded Provenance
usb_reverse_tether-0.1.0.tar.gz 35.2 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for usb-reverse-tether 0.1.0
File Interpreter ABI Platform
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.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page