Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 15 additions & 17 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,42 @@ on:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
verify:
name: Verify
runs-on: ubuntu-latest
verify-windows:
runs-on: windows-latest
timeout-minutes: 20

steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7.0.1

- name: Setup Node.js
uses: actions/setup-node@v5
- name: Set up Node.js
uses: actions/setup-node@v7.0.0
with:
node-version: 24.x
node-version: 24
cache: npm

- name: Install dependencies
run: npm ci

- name: Audit dependencies
run: npm audit --audit-level=moderate
- name: Prepare pinned runtime
run: npm run runtime:prepare

- name: Lint
run: npm run lint -- --no-cache

- name: Typecheck
run: npm run typecheck

- name: Build
- name: Unit tests
run: npm test

- name: Build renderer and main process
run: npm run build

- name: Package smoke test
run: npx electron-builder --win --dir
74 changes: 74 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: Release

on:
push:
tags:
- 'v*'

permissions:
contents: write

jobs:
release-windows:
runs-on: windows-latest
timeout-minutes: 25

steps:
- name: Checkout
uses: actions/checkout@v7.0.1

- name: Set up Node.js
uses: actions/setup-node@v7.0.0
with:
node-version: 24
cache: npm

- name: Install dependencies
run: npm ci

- name: Verify tag matches package version
shell: pwsh
run: |
$version = (Get-Content package.json | ConvertFrom-Json).version
if ($env:GITHUB_REF_NAME -ne "v$version") {
throw "Tag $env:GITHUB_REF_NAME does not match package version v$version."
}

- name: Verify source
run: |
npm run lint -- --no-cache
npm run typecheck
npm test

- name: Build Windows installer
run: npm run build:win

- name: Generate release checksums
shell: pwsh
run: |
$installers = Get-ChildItem 'dist\*.exe'
if (-not $installers) { throw 'No Windows installer was produced.' }
$lines = $installers | ForEach-Object {
$hash = (Get-FileHash $_.FullName -Algorithm SHA256).Hash.ToLower()
"$hash $($_.Name)"
}
$lines | Set-Content 'dist\SHA256SUMS.txt'

- name: Publish installer to GitHub Release
shell: pwsh
env:
GH_TOKEN: ${{ github.token }}
run: |
$tag = $env:GITHUB_REF_NAME
$assets = @(
(Get-ChildItem 'dist\*.exe' | ForEach-Object { $_.FullName })
(Resolve-Path 'dist\SHA256SUMS.txt').Path
)

gh release view $tag *> $null
if ($LASTEXITCODE -eq 0) {
gh release upload $tag @assets --clobber
}
else {
gh release create $tag @assets --verify-tag --generate-notes --title $tag
}
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,8 @@ out
*.zip
*.7z
.vscode/

bin/platform-tools/**
bin/gnirehtet-rust-win64/**
bin/.runtime-versions
!bin/README.md
172 changes: 73 additions & 99 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,144 +1,118 @@
# Wirebound
# Wirebound

![Platform: Windows](https://img.shields.io/badge/Platform-Windows-0078D6?style=for-the-badge&logo=windows)
![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue?style=for-the-badge)
![Version: 1.0.1](https://img.shields.io/badge/Version-1.0.1-green?style=for-the-badge)
![Electron](https://img.shields.io/badge/Electron-v39.x-47848F?style=for-the-badge&logo=electron)
![React](https://img.shields.io/badge/React-v19.x-61DAFB?style=for-the-badge&logo=react)
![Electron](https://img.shields.io/badge/Electron-44.x-47848F?style=for-the-badge&logo=electron)
![React](https://img.shields.io/badge/React-19.x-61DAFB?style=for-the-badge&logo=react)

Wirebound is a Windows desktop GUI for [Gnirehtet](https://github.com/Genymobile/gnirehtet), providing a management interface for reverse tethering. It allows Android devices to use a computer's internet connection via USB without requiring root access.

## Why I built this

Reverse tethering is useful, but most existing workflows are terminal-based and confusing for non-technical users. I built Wirebound to provide a simple Windows interface for Android USB internet sharing, especially for practical situations like office work, device testing, repair desks, field support, or low-connectivity environments.

The goal is not to replace Gnirehtet, but to make its workflow easier to start, monitor, and troubleshoot on Windows.
Wirebound is a Windows desktop GUI for [Gnirehtet](https://github.com/Genymobile/gnirehtet). It lets an Android device use a Windows PC's internet connection over USB without root access.

Wirebound handles device detection, Gnirehtet process lifecycle, DNS and relay configuration, connection state, logs, and common ADB failure states so users do not need to memorize terminal commands.

## Project status

Wirebound is currently an early stable release. The core workflow is available, but the project still needs more testing across Windows versions, Android devices, USB drivers, and ADB edge cases.

Current maintainer focus:
Wirebound is currently in **beta**. The core Windows reverse-tethering workflow works, but real-world compatibility still depends on Windows USB drivers, Android versions, device firmware, ADB authorization, and Gnirehtet itself.

- Better troubleshooting documentation
- Clearer first-run onboarding
- Smaller and lighter Windows packaging
- Portable build investigation
- Improved connection diagnostics
A `Connected` state means the desktop relay is running and a Gnirehtet client is active on at least one Android device. It does **not** claim that end-to-end internet access has been independently measured. Use the built-in device speed-test action to verify actual connectivity.

---

## 📸 Preview
## Preview

<p align="center">
<img src="resources/dashboard.png" width="480" alt="Wirebound Dashboard">
<img src="resources/settings.png" width="480" alt="Wirebound Settings">
</p>

---

## ✨ Features

- **Auto-Run Engine**: Detects connected ADB devices and initiates reverse tethering automatically.
- **Traffic Monitor**: Visualizes data throughput with real-time charts.
- **Themed Interface**: Supports native Light and Dark modes.
- **DNS Configuration**: Includes presets (Google, Cloudflare) and custom DNS options.
- **Live Logs**: Real-time terminal output parser for debugging and status tracking.
- **Localization**: Available in English and Indonesian.
- **Bundled Binaries**: Includes Gnirehtet Rust and ADB binaries for immediate use in packaged builds.

---
## Features

## 💻 Relationship with Gnirehtet
- **Guided reverse tethering** — Start and stop the Gnirehtet relay from a desktop UI.
- **ADB-aware device status** — Distinguishes ready, unauthorized, offline, no-access, and ADB-unavailable states.
- **Connection state verification** — `Connected` requires both the PC relay process and an active Gnirehtet Android client.
- **DNS and relay settings** — Google, Cloudflare, custom IPv4 DNS, and configurable relay port.
- **Live engine logs** — Gnirehtet output stays visible for troubleshooting.
- **Device speed-test shortcut** — Opens Fast.com on an authorized Android device to verify real connectivity.
- **Light and dark themes** — With English and Indonesian localization.
- **Graceful cleanup** — Stopping or closing Wirebound also attempts to stop Gnirehtet clients on attached devices.

**Wirebound** is an independent Windows desktop GUI and automation layer built around [Gnirehtet](https://github.com/Genymobile/gnirehtet).
Wirebound intentionally does **not** show fabricated traffic telemetry. A real throughput monitor can be added later only when it is backed by measurable network counters.

It uses Gnirehtet as the underlying reverse tethering engine and provides a graphical interface for device detection, connection management, DNS/Port configuration, and traffic monitoring.
## Relationship with Gnirehtet

**Wirebound is not an official Gnirehtet project and is not affiliated with Genymobile.**
Wirebound is an independent GUI and automation layer around Gnirehtet. It is not an official Genymobile project and is not affiliated with Genymobile.

> **Note**: Gnirehtet runtime binaries (`.exe` and `.apk`) are bundled in the official release builds for convenience. If building from source, ensure the runtime files are placed in the `bin/` directory.
Gnirehtet creates a VPN interface on Android and forwards traffic to a TCP relay on the PC. Wirebound manages that lifecycle and the ADB interactions around it.

---
Gnirehtet upstream is lightly maintained, so Wirebound pins a known runtime version instead of silently following an unversioned latest binary.

## 💻 Technical Overview
## Runtime dependencies

The application establishes a per-device VPN tunnel on the Android side that routes network traffic through a TCP relay server running on the PC. It automates the lifecycle of this relay and the ADB connection.
Release builds currently pin:

### 1. Execution Mode
Wirebound uses the `autorun` mode to monitor the ADB bus for new connections and deploy the required services to multiple devices simultaneously.
- **Gnirehtet:** 2.5.1, Rust Windows build
- **Android SDK Platform Tools:** 37.0.1

### 2. Architecture
Built with **Electron + Vite**, utilizing a decoupled structure:
- **Main Process**: Manages binary lifecycle and process pipes.
- **Renderer Process**: Isolated React UI layer with Tailwind CSS.
- **Preload Layer**: Secure Context Bridge for IPC.
Runtime archives are downloaded by `scripts/prepare-runtime.ps1` and verified with SHA-256 before extraction. Generated runtime files are ignored by Git, so the repository does not rely on manually copied binaries.

### 3. Project Structure
```text
bin/ # Bundled binaries (Gnirehtet & ADB)
build/ # Installer assets & icons
resources/ # Dashboard screenshots
src/ # Application source code
package.json # Project manifest
LICENSE # Apache 2.0
```
Wirebound uses a dedicated local ADB server on port **5038**. The normal ADB server on port 5037 is left alone, so closing Wirebound does not intentionally stop an ADB server used by Android Studio or other tools.

### 4. Runtime Binaries
Wirebound release builds include the required Gnirehtet and ADB runtime files, so regular users do not need to download them manually.
## Usage

For development or source builds, make sure the following files exist in the `bin/` directory:
- `bin/gnirehtet-rust-win64/gnirehtet.exe`
- `bin/gnirehtet-rust-win64/gnirehtet.apk`
- `bin/gnirehtet-rust-win64/gnirehtet-run.cmd`
- `bin/platform-tools/adb.exe`
1. Enable **Developer options** and **USB debugging** on the Android device.
2. Connect the device to the PC with USB.
3. Accept the Android USB-debugging authorization prompt.
4. Open Wirebound.
5. Configure DNS or relay port only if needed.
6. Click **Start Connection**.
7. Accept the Gnirehtet VPN permission prompt on Android.
8. When Wirebound reports `Connected`, use **Speed Test** if you want to verify end-to-end internet access.

Some runtime binaries may be excluded from the source repository to keep the repository lightweight and cleaner.
If Wirebound reports `Unauthorized`, `Offline`, `No access`, or `ADB unavailable`, resolve that state before troubleshooting the relay itself.

Gnirehtet can be downloaded from the original [Genymobile release page](https://github.com/Genymobile/gnirehtet/releases).
## Development

---
Requirements: Windows, Node.js 24+, npm, PowerShell, and Git.

## 📖 Usage
```powershell
git clone https://github.com/man612/wirebound.git
cd wirebound
npm ci
npm run runtime:prepare
npm run dev
```

### Step 1: Device Preparation
1. Enable **Developer Options** on the Android device.
2. Enable **USB Debugging**.
Useful verification commands:

### Step 2: Connection
1. Connect the device via USB.
2. Authorize the ADB debugging prompt on the phone screen.
```powershell
npm run lint -- --no-cache
npm run typecheck
npm test
npm run build
npm run package:check
```

### Step 3: Execution
1. Run `Wirebound.exe`.
2. Configure DNS and Port in **Settings** if necessary.
3. Click **Start** in the Dashboard.
4. Accept the VPN request on the Android device.
`package:check` builds an unpacked Windows application and verifies that the packaged app can include the pinned runtime. `npm run build:win` produces the Windows installer.

---
## Architecture

## 🛠️ Development
- `src/main` — Electron main process, window hardening, IPC validation, ADB and Gnirehtet services.
- `src/preload` — Narrow context bridge exposed to the renderer.
- `src/renderer` — React/Tailwind interface.
- `src/shared` — Shared types, defaults, and settings normalization.
- `scripts` — Reproducible runtime preparation.
- `bin` — Generated runtime directory; only its documentation is tracked.

```bash
# Clone the repository
git clone https://github.com/man612/wirebound.git
Wirebound is intentionally Windows-only today. The runtime paths, ADB distribution, packaging, and CI are designed and verified for Windows rather than advertising unsupported macOS/Linux builds.

# Install dependencies
npm install
## Releases

# Run in development mode
npm run dev
CI runs on Windows and verifies linting, TypeScript, unit tests, production build, and an unpacked package smoke test. Tags matching `v*` trigger the Windows release workflow.

# Build for Windows
npm run build:win
```
Release artifacts should be treated as the canonical user distribution. Source checkouts fetch pinned runtime dependencies during development/build rather than storing executable binaries in Git.

---
## License and credits

## 📄 License & Credits
Wirebound is licensed under the **Apache License 2.0**.

- **Wirebound GUI & Integration**: Built by [man612](https://github.com/man612).
- **Engine**: Powered by [Gnirehtet](https://github.com/Genymobile/gnirehtet) by Genymobile.
- **License**: Both projects are licensed under the **Apache License 2.0**.
- **Third-Party**: Detailed notices are available in [THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md).
- Wirebound GUI and integration: [man612](https://github.com/man612)
- Reverse-tethering engine: [Gnirehtet](https://github.com/Genymobile/gnirehtet) by Genymobile
- Android device tooling: Android SDK Platform Tools / ADB by Google
- Third-party details: [THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md)
Loading