-
ET Phone Home v0.9.2
StableAll checks were successfulDesktop FreeBSD / macOS (Apple Silicon + Intel) and Windows e2e, on the GitHub mirror (push) Successful in 3sClaims ledger / Every README claim has a test (push) Successful in 4sRust CI / Format Check (push) Successful in 13sRust CI / Clippy (push) Successful in 51sAndroid CI / Lint (push) Successful in 2m5sRust CI / Security Audit (push) Successful in 2m44sAndroid CI / Build Debug APK (push) Successful in 2m32sAndroid CI / Unit Tests (push) Successful in 2m50sRust CI / Test (push) Successful in 2m7sDesktop FreeBSD / FreeBSD packages (amd64 + aarch64) (push) Successful in 3m21sRust CI / Build Linux (push) Successful in 3m18sOpenWrt router packages / Build router packages (5 CPU families, ipk + apk) (push) Successful in 7m1sRust CI / End-to-end (real client + TUN + phone core, real internet) (push) Successful in 6m11sRust CI / Build Windows (push) Successful in 1m48sRust CI / Build Desktop GUI (push) Successful in 5m43sDesktop FreeBSD / Real FreeBSD 14 VM against the phone core (push) Successful in 12m46sDesktop FreeBSD / Real OPNsense + pfSense CE VMs (plugin/package, phone as gateway, WAN failover) (push) Successful in 16m35sOpenWrt router packages / Real OpenWrt VMs (24.10 opkg + 25.12 apk) against the phone core (push) Successful in 6m46sRelease / Build Linux Release (push) Successful in 2m34sRelease / Build Windows Release (push) Successful in 3m2sRelease / Build FreeBSD Release (pkg, amd64 + aarch64) (push) Successful in 3m0sRelease / Build Desktop GUI (Linux) (push) Successful in 4m17sRelease / Build Android Release (push) Successful in 2m29sRelease / Build OpenWrt router packages (push) Successful in 7m7sRelease / Publish Forgejo release (push) Successful in 1m15sRelease / Sign the APK with the ETPH release key and attach it (push) Successful in 4sRelease / Attach the macOS package (built + tested on the GitHub mirror) (push) Successful in 3sRelease / SHA256SUMS over every release file (push) Successful in 29sRelease / Verify the published release (push) Successful in 5sreleased this
2026-10-21 21:13:57 -07:00 | 43 commits to main since this releaseFixed
- Installers, packages and docs no longer mention or contact the project's private git host: the OpenWrt/GL.iNet installer downloads from
https://errant.solutions/download/etphonehome/<tag>/<file>and finds the latest release through the public GitHub API; winget manifests, the README and the docs link errant.solutions or the public GitHub repository. CI now fails if the private host's name appears in a shipped file or in any release package.
Changed
etphonehome list-profilesprintsWARNING: connect will refuse this profile: ...under a profile whose enabled filter can't be sent to the phone (a rule with an address/port typo, more than 1024 rules, or rules too large for one message). This is the same checkconnectruns. Before, the listing looked normal and the problem only showed up when a connect attempt failed. The desktop app's profile list marks such a profile with "Filter problem: won't connect".
Downloads
-
Source code (ZIP)
2 downloads
-
Source code (TAR.GZ)
2 downloads
- Installers, packages and docs no longer mention or contact the project's private git host: the OpenWrt/GL.iNet installer downloads from
-
ET Phone Home v0.9.1
StableAll checks were successfulClaims ledger / Every README claim has a test (push) Successful in 4sDesktop FreeBSD / macOS (Apple Silicon + Intel) and Windows e2e, on the GitHub mirror (push) Successful in 6sRust CI / Format Check (push) Successful in 12sRust CI / Clippy (push) Successful in 50sAndroid CI / Lint (push) Successful in 1m37sRust CI / Security Audit (push) Successful in 2m53sAndroid CI / Unit Tests (push) Successful in 2m38sAndroid CI / Build Debug APK (push) Successful in 2m55sDesktop FreeBSD / FreeBSD packages (amd64 + aarch64) (push) Successful in 2m47sRust CI / End-to-end (real client + TUN + phone core, real internet) (push) Successful in 5m16sOpenWrt router packages / Build router packages (5 CPU families, ipk + apk) (push) Successful in 5m36sDesktop FreeBSD / Real FreeBSD 14 VM against the phone core (push) Successful in 13m8sRust CI / Test (push) Successful in 1m59sRust CI / Build Desktop GUI (push) Successful in 2m25sRust CI / Build Linux (push) Successful in 3m6sRust CI / Build Windows (push) Successful in 1m17sDesktop FreeBSD / Real OPNsense + pfSense CE VMs (plugin/package, phone as gateway, WAN failover) (push) Successful in 16m58sOpenWrt router packages / Real OpenWrt VMs (24.10 opkg + 25.12 apk) against the phone core (push) Successful in 6m55sRelease / Build FreeBSD Release (pkg, amd64 + aarch64) (push) Successful in 2m48sRelease / Build Linux Release (push) Successful in 3m18sRelease / Build Windows Release (push) Successful in 3m23sRelease / Build Desktop GUI (Linux) (push) Successful in 3m51sRelease / Build OpenWrt router packages (push) Successful in 7m22sRelease / Build Android Release (push) Successful in 3m3sRelease / Publish Forgejo release (push) Successful in 51sRelease / Sign the APK with the ETPH release key and attach it (push) Successful in 3sRelease / Attach the macOS package (built + tested on the GitHub mirror) (push) Successful in 9sRelease / SHA256SUMS over every release file (push) Successful in 19sRelease / Verify the published release (push) Successful in 1sPublish to Google Play / diagnose (push) Has been skippedPublish to Google Play / build-release-aab (push) Successful in 3m23sPublish to Google Play / sign-and-publish (push) Successful in 48sreleased this
2026-10-21 01:07:14 -07:00 | 52 commits to main since this releaseAdded
- macOS client:
etph-macos-<version>.pkg(Apple Silicon + Intel, macOS 11+): menu-bar app, CLI and a launchd service that owns the tunnel (utun, no kernel extension), DNS for the tunnel through scutil,etph-uninstall. Installed and tested in CI on an Apple Silicon and an Intel Mac (HTTPS, DNS and a 5 MB download through the phone core, the service andctl, clean uninstall). Not notarized yet: the first open needs Control-click > Open (docs/DESKTOP.md). - OPNsense plugin
os-etph: Interfaces > Phone uplink (ETPH) (settings, phone status, ETPH Pro, traffic), a configd-driven service, andetph0offered under Interfaces > Assignments even while the phone is away, so the phone can be a gateway in a gateway group (WAN failover). Tested on a real OPNsense 26.7 VM. - pfSense CE package
pfSense-pkg-etph: Interfaces > Phone uplink (ETPH) with a Status tab, the ETPH service under Status > Services,etph0assignable as an interface for gateways and gateway groups. Tested on a real pfSense CE 2.7.2 VM. - Both firewall tests run in CI (
firewall-vms): a LAN client keeps HTTPS through the phone when the primary WAN goes down, the firewall's own default route follows, the uplink survives the WAN coming back and the phone going away and returning, and the packages uninstall cleanly. - FreeBSD packages for FreeBSD 14 and 15 (
-freebsd14-,-freebsd15-): pkg(8) refuses a package built for another major version.
Fixed
- BSD firewalls: when the firewall reconfigures the assigned phone interface (pfSense "IPv4 Configuration Type: None" strips its addresses), the client puts the link address back within seconds and re-runs the up hook instead of leaving the uplink dead until the next reconnect.
- OPNsense: after the phone reconnects, its gateway comes back online (the link returns with the same address, and OPNsense's address-change hook skipped it as "no IP change", leaving gateway monitoring on the old device).
Known limits
- Firewalls: the phone connects over Wi-Fi (tested); USB to a phone plugged into the firewall is offered but not yet tested there.
- The macOS package is ad-hoc signed, not notarized (no Apple Developer ID yet).
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
4 downloads
- macOS client:
-
ET Phone Home v0.9.0
StableAll checks were successfulDesktop FreeBSD / macOS (Apple Silicon + Intel) and Windows e2e, on the GitHub mirror (push) Successful in 3sClaims ledger / Every README claim has a test (push) Successful in 55sDesktop FreeBSD / FreeBSD packages (amd64 + aarch64) (push) Successful in 4m31sRelease / Build Linux Release (push) Successful in 3m1sRelease / Build Windows Release (push) Successful in 3m2sRelease / Build FreeBSD Release (pkg, amd64 + aarch64) (push) Successful in 3m8sRelease / Build Desktop GUI (Linux) (push) Successful in 3m28sRelease / Build Android Release (push) Successful in 3m22sRelease / Build OpenWrt router packages (push) Successful in 8m43sDesktop FreeBSD / Real FreeBSD 14 VM against the phone core (push) Successful in 10m51sRelease / Publish Forgejo release (push) Successful in 46sRelease / Attach the macOS package (built + tested on the GitHub mirror) (push) Has been skippedRelease / Sign the APK with the ETPH release key and attach it (push) Successful in 4sRelease / Verify the published release (push) Successful in 0sreleased this
2026-10-20 23:05:42 -07:00 | 62 commits to main since this releaseAdded
- Free and Pro. One app, two tiers. Free: sharing over USB with one computer, no speed cap, no time limit, started and stopped on the phone. ETPH Pro, a one-time in-app purchase in the Google Play app (US$15 or Play's local price; no subscription), adds Wi-Fi and Bluetooth, routers, several computers and routers, auto-start when the computer asks over USB plus waiting for the computer after a disconnect, and a data usage history. "Upgrade to Pro" screen with the feature list and the Play price, Restore purchase; a quiet status line instead of pop-ups. Google Play Billing 9.1: purchases are acknowledged, restored on a reinstall or new phone, pending payments wait for Play, refunds and revocations take Pro away at the next check (every app start, every Start); purchase signatures are checked on the phone; no server (docs/pro.md).
- The phone enforces the split; computers and routers never need a licence. The handshake now carries who the client is (a random client id and its host name; routers say they are routers) and whether the phone has Pro. A refused client gets "Pro required on the phone: ..." and the desktop/router client prints it with "nothing needs to be bought or licensed on this computer or router", keeps retrying once a minute (so buying Pro on the phone just works), the GUI shows it, and LuCI shows whether the phone has Pro. Older clients still connect over USB as one computer.
- Paired computers and routers on the phone, each with Forget (Free works with the computer used last; forget it to switch).
- Auto-start on plug-in (Pro): when the computer finds the phone on USB with nothing listening, it asks the phone to start sharing (
adb shell am start ... AutoStartActivity, also through the routers' built-in ADB host), once per plug-in, so a Stop on the phone is respected until the cable is replugged. Switch "Start when the computer asks" on the phone. - Data usage (Pro): per computer/router (today, this month, 30 days) and by kind of traffic (web, QUIC, DNS, email, SSH, calls, VPN, NTP, ping), kept on the phone only.
- Desktop:
--router(set by OpenWrt'sproto etph),$ETPH_CLIENT_ID/$ETPH_CLIENT_NAME; the status file hasphone_pro. - USB without Developer options (routers and Linux computers). The client talks to the phone as an Android Open Accessory: plug the phone in, tap OK on "Open ETPH ...?" once, and the link comes up; no USB debugging, no adb. The ADB route stays as a fallback (
--usb-link auto|aoa|adb, LuCI "USB link"). The phone coalesces frames into 16 KiB accessory transfers. - USB works in every app mode: a phone in Wi-Fi or Bluetooth mode still accepts a computer or router on USB.
- The phone names what it shares with ("Router: slate (GL.iNet GL-AR750S, OpenWrt)", or the computer's host name).
- Windows installer:
etph-windows-<version>.msi(CLI, tray app, the ETPH tethering service, bundled Wintun) and winget manifests (etph-winget-<version>.zip). - ETPH Pro purchases are checked on the phone against the app's Play licence key: an unsigned or wrongly signed purchase never unlocks Pro.
- FreeBSD 14 packages (amd64, aarch64):
pkg add, an rc.d service andetphonehome ctl, tun(4) + resolvconf(8); tested on a real FreeBSD 14.4 VM.
Known limits
- macOS, pfSense and OPNsense clients come in a 0.9.x update.
- Windows USB still needs USB debugging (the accessory link is Linux/router only).
Changed
- Free: when the computer disconnects, sharing stops (tap Start again); Pro keeps waiting for it.
Fixed
- Desktop/router: a filter rule with an address or port typo (
dest_ip = "10.0.0.0/24/8","010.0.0.1",dest_port = "443-80"or"8o") silently did nothing: the computer never matched it and the phone dropped it, so a BLOCK rule blocked nothing. A profile with such an enabled rule is now refused before connecting, with the rule and field named.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
2 downloads
-
ET Phone Home v0.8.0
StableAll checks were successfulClaims ledger / Every README claim has a test (push) Successful in 3sAndroid CI / Lint (push) Successful in 2m1sAndroid CI / Unit Tests (push) Successful in 2m41sAndroid CI / Build Debug APK (push) Successful in 2m59sRelease / Build Windows Release (push) Successful in 2m4sRelease / Build Linux Release (push) Successful in 2m23sRelease / Build Android Release (push) Successful in 3m9sRelease / Build Desktop GUI (Linux) (push) Successful in 3m47sRelease / Build OpenWrt router packages (push) Successful in 8m40sRelease / Publish Forgejo release (push) Successful in 40sRelease / Sign the APK with the ETPH release key and attach it (push) Successful in 3sRelease / Verify the published release (push) Successful in 0sreleased this
2026-10-20 16:28:41 -07:00 | 87 commits to main since this releaseAdded
- Routers: the phone as a router's internet (OpenWrt, GL.iNet). New packages put the ETPH client on an OpenWrt router (official OpenWrt and GL.iNet firmware), so every device behind the router gets the phone's connection. Over a USB cable or Wi-Fi (TLS, the token the app shows), or
auto(USB when a phone is plugged in, else Wi-Fi). For USB the client has its own ADB host (usbfs, no adb package or server, so it fits small routers); the phone's "Allow USB debugging?" prompt is the pairing, and LuCI says "Unlock your phone and tap Allow" while it waits. The uplink is a normal network interface,option proto 'etph': netifd adds the default route with the interface's metric and gives dnsmasq the phone's DNS, so firewall zones and mwan3 failover/load balancing work as with any WAN. It reconnects by itself when the phone goes away and comes back, and right away when a phone is plugged into the router's USB port. LuCI page Network > Phone uplink: status (phone model, connection, speed, data), one-step setup into the wan zone, pairing/unpairing, USB phones and the router's adb key fingerprint. Packages:.ipkfor OpenWrt 24.10 and older and GL.iNet 4.x,.apkfor OpenWrt 25.x, for aarch64, ARMv7 (with FPU), MIPS 24Kc, MIPSel and x86_64; an installer script picks the right one. Guide: docs/OPENWRT.md. - Desktop client:
usb --native(built-in ADB host on Linux: no adb tool needed),usb --adb-tcp HOST:PORT,auto,usb-list,adb-keygen,--no-routes,--up-script/--down-script(pppd-style hooks),--status-file(JSON status),--tun-address/--tun-peer,--adb-serial,discover-wifi --json,adb-fingerprint; the WiFi/Bluetooth token can come from$ETPH_TOKEN(keeps it out ofps); SIGUSR1 skips the reconnect wait; SIGTERM disconnects cleanly like Ctrl-C. - The phone tells the computer its name (e.g. "samsung SM-N986U") in the handshake; older desktops ignore it.
Known limits
- Routers over USB are tested in CI against the real app's adbd on Android emulators and against a fake adbd, and over Wi-Fi on a real GL.iNet GL-AR750S with a real phone; USB with a phone plugged into real router hardware is not verified yet.
- ARMv7 routers without an FPU (e.g. Broadcom bcm53xx) and MIPS64 are not supported.
Fixed
- Desktop: a large traffic filter put the connection in a reconnect loop. A profile whose filter rules came to more than 65535 bytes (the most one message to the phone can carry) brought the tunnel up and dropped it straight away, then retried every second forever, with the default route coming and going each time. Such a profile, or an enabled filter with more than 1024 rules (the most the phone takes; it silently dropped the rest), is now refused before connecting, with an error that says why.
- Android: a router using the phone over the router's own Wi-Fi made traffic loop. When the phone is joined to the Wi-Fi of a router whose internet is the phone, Android eventually treats that Wi-Fi as the phone's internet (its check passes through the tunnel), and the relay's connections went phone -> router -> phone. When the computer is the router of the Wi-Fi the phone is on, the relay now pins its sockets to another network (mobile data first), keeps mobile data up for it, and refuses connections rather than loop when there is no other network. A computer that is just another device on the phone's Wi-Fi is not affected.
- The router build has no Bluetooth/D-Bus and uses only the ring TLS backend (no aws-lc), which also makes the desktop binary smaller.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
2 downloads
- Routers: the phone as a router's internet (OpenWrt, GL.iNet). New packages put the ETPH client on an OpenWrt router (official OpenWrt and GL.iNet firmware), so every device behind the router gets the phone's connection. Over a USB cable or Wi-Fi (TLS, the token the app shows), or
-
ET Phone Home v0.7.1
StableAll checks were successfulClaims ledger / Every README claim has a test (push) Successful in 2sRelease / Build Linux Release (push) Successful in 2m9sRelease / Build Windows Release (push) Successful in 2m29sRelease / Build Android Release (push) Successful in 3m20sRelease / Build Desktop GUI (Linux) (push) Successful in 5m28sRelease / Publish Forgejo release (push) Successful in 22sRelease / Sign the APK with the ETPH release key and attach it (push) Successful in 5sRelease / Verify the published release (push) Successful in 11sreleased this
2026-10-18 20:21:03 -07:00 | 112 commits to main since this releaseChanged
- Android: targets Android 16 (API 36), which Google Play requires for new apps. The app now draws edge to edge on every Android version, with its content kept clear of the status bar, navigation bar, camera cutout and keyboard (Android 15+ forces edge-to-edge for apps targeting it). Back navigation uses the system's predictive back. Still runs on Android 8.0 and newer.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
2 downloads
-
ET Phone Home v0.7.0
StableAll checks were successfulClaims ledger / Every README claim has a test (push) Successful in 9sRelease / Build Linux Release (push) Successful in 2m6sRelease / Build Windows Release (push) Successful in 1m44sRelease / Build Android Release (push) Successful in 2m5sRelease / Build Desktop GUI (Linux) (push) Successful in 4m2sRelease / Publish Forgejo release (push) Successful in 14sRelease / Sign the APK with the ETPH release key and attach it (push) Successful in 3sRelease / Verify the published release (push) Successful in 0sreleased this
2026-10-18 18:46:14 -07:00 | 115 commits to main since this releaseChanged
- New app id and name: "Errant Solutions ETPH" (
solutions.errant.etph). This is the name and id the app will have on Google Play (ETPH = ET Phone Home); the launcher icon is labelled "ETPH". Android treats a new app id as a different app, so 0.7.0 installs next to an older ET Phone Home (com.etphonehome) instead of updating it. While the old app is still installed, the new one says so on its main screen, with a button that opens the old app's App info page (Uninstall is there). Uninstall the old app afterwards, and re-pair WiFi/Bluetooth desktops with the token the new app shows (the tokens belong to the app, so they did not carry over). USB needs nothing new. Settings such as the connection mode start fresh too. - The APK on the releases page is signed with the ETPH release key (the key registered for
solutions.errant.etphwith Google's Android developer verification, SHA-25601:11:AF:00:57:D7:E9:28:90:FB:CE:02:E9:92:7A:85:E5:EA:B2:AD:AC:2C:00:76:55:E1:7C:B0:CF:7F:68:40). Releases up to 0.6.1 carried a public debug key. - Google Play release pipeline: the Play bundle is built unsigned on a normal runner and signed with the upload key on a dedicated signer, then uploaded to the internal testing track (
release-play-*tags; a manual run is a dry run that changes nothing in Play). Store listing text and the Data safety answers live instore/.
Fixed
- A connection that stalled mid-handshake locked every desktop out of the phone. The phone serves one desktop at a time, and once a connection had sent its first byte nothing timed out until the handshake finished. So a connection that sent one byte, or a TLS ClientHello, and then went quiet held the session slot indefinitely, before any token check. Anyone on the same WiFi, or any app on the phone for the USB port, could do this. The whole handshake now has to finish within 15 s, otherwise the connection is dropped.
- A phone-side filter rule with an invalid IPv4 address triggered a DNS lookup. Rule addresses like
256.1.1.1were handed to the system resolver as hostnames, which blocked the session while the lookup ran, and on networks whose DNS answers every name the rule ended up applying to an unrelated address. Rule addresses are now parsed as numeric IPv4/IPv6 literals only, and anything else drops the rule. - A phone-side filter rule naming one IPv6 host covered its whole /32. A rule address with no
/prefixdefaulted to /32 for IPv6 as well as IPv4, so blocking2001:db8::1blocked all of2001:db8::/32, and in whitelist mode allowing it allowed the whole /32. A bare IPv6 address is now /128. - IPv6 packets could slip past the phone's protocol and port rules. The packet parser stopped walking IPv6 extension headers after 8, and didn't know the Authentication Header, so TCP behind 9+ extension headers or an AH header came out as "any protocol, no ports" and a rule like
block tcp 443didn't match it. The parser now walks the whole chain (always bounded by the packet length) and understands AH.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
2 downloads
- New app id and name: "Errant Solutions ETPH" (
-
ET Phone Home v0.6.1
StableAll checks were successfulClaims ledger / Every README claim has a test (push) Successful in 10sRelease / Build Windows Release (push) Successful in 1m42sRelease / Build Linux Release (push) Successful in 4m27sRelease / Build Android Release (push) Successful in 1m52sRelease / Build Desktop GUI (Linux) (push) Successful in 3m10sRelease / Publish Forgejo release (push) Successful in 10sreleased this
2026-10-17 04:42:50 -07:00 | 143 commits to main since this releaseFixed
- USB tethering on Android 8-10. The app's USB server listened on
::1; adbd before Android 11 forwardsadb forwardconnections to127.0.0.1only, so every USB connection was refused on those versions (found by the new API 26 emulator test). It now listens on 127.0.0.1. - Linux release binary ran only on the newest distros. It needed glibc 2.39 (the CI image's), so it did not even start on Debian 12 or Ubuntu 22.04. Releases are now linked against glibc 2.31 with libdbus built in (no system libdbus needed); the nightly distro matrix runs a real tunnel on Debian 11-13, Ubuntu 20.04-24.04, Fedora, Arch and openSUSE.
- A dropped WiFi link left a dead tunnel behind. The desktop kept the TUN device and default route for 90 s, and the phone held the dead session until TCP gave up (~15 min), refusing the desktop when it came back. The desktop now sends keepalives and gives up after 30 s; the phone ends a session whose (keepalive-sending) desktop has been silent for 30 s.
- WiFi crashed the app on Android 8 and 9. The first encrypted WiFi connection crashed the app with
NoSuchMethodError(the TLS layer called a Java 8SSLSocketFactorymethod these Android versions lack); found by the API 26 emulator test. TLS is now layered through Bouncy Castle's own implementation of that method. - Bluetooth could never connect to a real phone. The desktop always dialed RFCOMM channel 1, but Android assigns channels dynamically (the app was on channel 6 on a Galaxy Note20), and the app told users to connect to
02:00:00:00:00:00(Android hides the real Bluetooth address from apps). The app now listens on its own service UUID and shows its name; the desktop asks BlueZ to connect that service (BlueZ looks the channel up over SDP and hands over the socket, which also works from a container) and--addressaccepts the phone's name as paired. Verified on a Samsung Galaxy Note20 (Android 13): public HTTPS, DNS and a byte-identical download over Bluetooth, from a desktop whose only way out was the tunnel. - The desktop client no longer sets
net.ipv4.ip_forward=1on the computer (it never needed it and never undid it). --reconnectno longer retries a protocol-version mismatch or a rejected token forever; it stops with the reason. The retry budget and backoff count failures since the last working session, not over the client's lifetime.
Added
- Nightly CI: integrity at scale (256 MiB both ways with digests, 100 parallel TCP + 50 UDP flows), failure and recovery (USB unplug, WiFi drop, app killed, Ctrl-C, crash, lossy link), throughput/latency baseline, upgrade compatibility with the previous release, a Linux distro matrix, arm64, the Windows client under wine, and the real APK on Android 8 and 14 emulators. Weekly mutation testing of the desktop and phone cores.
Fixed
- USB tethering on Android 8-10. The app's USB server listened on
::1; adbd before Android 11 forwardsadb forwardconnections to127.0.0.1only, so every USB connection was refused on those versions (found by the new API 26 emulator test). It now listens on 127.0.0.1. - Linux release binary ran only on the newest distros. It needed glibc 2.39 (the CI image's), so it did not even start on Debian 12 or Ubuntu 22.04. Releases are now linked against glibc 2.31 with libdbus built in (no system libdbus needed); the nightly distro matrix runs a real tunnel on Debian 11-13, Ubuntu 20.04-24.04, Fedora, Arch and openSUSE.
- A dropped WiFi link left a dead tunnel behind. The desktop kept the TUN device and default route for 90 s, and the phone held the dead session until TCP gave up (~15 min), refusing the desktop when it came back. The desktop now sends keepalives and gives up after 30 s; the phone ends a session whose (keepalive-sending) desktop has been silent for 30 s.
- The desktop client no longer sets
net.ipv4.ip_forward=1on the computer (it never needed it and never undid it). --reconnectno longer retries a protocol-version mismatch or a rejected token forever; it stops with the reason. The retry budget and backoff count failures since the last working session, not over the client's lifetime.
Added
- Nightly CI: integrity at scale (256 MiB both ways with digests, 100 parallel TCP + 50 UDP flows), failure and recovery (USB unplug, WiFi drop, app killed, Ctrl-C, crash, lossy link), throughput/latency baseline, upgrade compatibility with the previous release, a Linux distro matrix, arm64, the Windows client under wine, and the real APK on Android 8 and 14 emulators. Weekly mutation testing of the desktop and phone cores.
Planned for v0.5.0
- TLS encryption for WiFi/Bluetooth modes
- Desktop GUI application
- Traffic statistics and graphs
- Root mode with iptables routing for better performance
- Advanced routing and traffic filtering rules
Planned for v1.0.0+
- Multiple device support
- Data usage limits and alerts
- Traffic compression for bandwidth optimization
- Custom DNS server configuration
- Mobile data usage tracking
Release Notes
v0.4.0 Highlights
Version 0.4.0 represents a major milestone, elevating ET Phone Home from Alpha to Beta status. All three tethering modes (USB, WiFi, Bluetooth) are now fully functional with enterprise-grade features:
- Complete Bluetooth Support: Both Android and Desktop implementations finished
- Security: Token-based authentication protects WiFi and Bluetooth connections
- Reliability: Auto-reconnect ensures connections stay active
- Convenience: Connection profiles and mDNS discovery simplify usage
- Production Ready: Comprehensive testing and documentation
Migration Guide: v0.3.0 → v0.4.0
Breaking Changes
None. Version 0.4.0 is fully backward compatible with v0.3.0.
New Optional Features
Token Authentication:
- WiFi and Bluetooth connections now support (but don't require) authentication tokens
- Old command:
sudo etphonehome wifi --host 192.168.1.100 - New command:
sudo etphonehome wifi --host 192.168.1.100 --token AbC123XyZ - USB mode unchanged (no tokens needed)
Connection Profiles:
# Old way - manual command every time sudo etphonehome wifi --host 192.168.1.100 # New way - save once, use forever etphonehome save-profile home --type wifi --host 192.168.1.100 sudo etphonehome connect homeAuto-Reconnect:
# Add --reconnect to any connection command sudo etphonehome wifi --host 192.168.1.100 --reconnectmDNS Discovery:
# New discover-wifi command replaces manual IP finding sudo etphonehome discover-wifiAndroid App Changes
- WiFi and Bluetooth modes now display authentication tokens
- Copy the displayed token for desktop connection
- Tokens are automatically generated on first use
- Same tokens persist across app restarts
Known Issues
- Windows Bluetooth: Some configurations may require manual COM port setup
- Linux Bluetooth: Requires
libdbus-1-devpackage for compilation - mDNS Discovery: May not work across different network subnets (by design)
Future Roadmap
v0.5.0 (Planned):
- TLS encryption for WiFi/Bluetooth modes
- Desktop GUI application
- Traffic statistics and graphs
- Root mode with iptables routing
v1.0.0 (Planned):
- Multiple device support
- Data usage limits and alerts
- Traffic compression
- Custom DNS configuration
How to Read This Changelog
- Added - New features
- Changed - Changes in existing functionality
- Deprecated - Soon-to-be removed features
- Removed - Removed features
- Fixed - Bug fixes
- Security - Security improvements
- Documentation - Documentation updates
Links
- Repository: https://git.canutethegreat.com/CanuteTheGreat/etphonehome
- Documentation: docs/
- Issue Tracker: https://git.canutethegreat.com/CanuteTheGreat/etphonehome/issues
Contributing
See CONTRIBUTING.md for how to contribute to this project.
License
This project is licensed under the MIT License. See LICENSE for details.
For more details on any release, see the corresponding version tag in the repository.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
2 downloads
- USB tethering on Android 8-10. The app's USB server listened on
-
ET Phone Home v0.6.0
StableAll checks were successfulAndroid CI / Unit Tests (push) Successful in 1m33sAndroid CI / Lint (push) Successful in 2m35sAndroid CI / Build Debug APK (push) Successful in 4m8sRelease / Build Windows Release (push) Successful in 1m49sRelease / Build Linux Release (push) Successful in 2m11sRelease / Build Desktop GUI (Linux) (push) Successful in 2m49sRelease / Build Android Release (push) Successful in 3m18sRelease / Publish Forgejo release (push) Successful in 13sreleased this
2026-10-16 21:00:03 -07:00 | 159 commits to main since this releaseAdded
- The computer really gets the phone's internet, without root. The Android app now has a userspace relay (
android/core/.../relay/UserspaceRelay.kt): it terminates the desktop's TCP connections and UDP flows itself and re-opens them as ordinary phone sockets (with sequence/ACK handling, flow control, retransmission, FIN/RST), answers ping for the phone and relays ping to other hosts. Before this the app only copied raw packets into a phone VPN, which Android never forwards, so no traffic ever reached the internet. - The phone keeps its own internet. The phone VPN is gone: nothing on the phone is captured, and the app no longer asks for VPN permission.
- Encrypted WiFi by default. The app serves cert-pinned TLS 1.3 (same token-derived Ed25519 pinning as the desktop, via Bouncy Castle) and auto-detects TLS vs. plaintext.
etphonehome wifiand WiFi profiles use TLS by default (--no-tlsto opt out); the app refuses plaintext WiFi unless "Require encryption" is switched off. - Live status and statistics on the phone: "Waiting for desktop" until a desktop has actually completed the handshake, then the desktop's address, encryption, data each way, open/total connections, uptime and filter state; the notification shows the same and has a Stop button.
- Traffic filter on the phone: right after the handshake the desktop sends the profile's filter (mode and every rule) to the phone, which enforces it on the connections it opens and resets connections a new rule blocks.
- DNS on the desktop: the client points DNS for the tunnel at the phone's DNS server (
resolvectlon Linux,netshon Windows). - Real-internet end-to-end CI: the e2e job now runs the app's actual networking core (
android/core, as the JVMstandin) and checks, from a desktop container whose only way out is the tunnel: public HTTPS and HTTP, DNS, a 5 MiB download, TCP echo both ways, UDP, ICMP, 20 parallel connections, USB, filter rules, wrong tokens, plaintext refusal, reconnects. - Releases are published on Forgejo (the workflow used a GitHub-only action and never created one) and checked to contain all four packages.
Removed
- Root mode. It was claimed as implemented, but nothing could start it, and its iptables rules redirected all of the phone's own traffic to the desktop. Removed until a correct kernel-NAT design exists.
- Dead Android TLS/connection classes that were never wired in.
Changed
- Android 8.0+ is now required (was 5.0).
Fixed
- USB tethering never connected: the desktop client (and
setup-adb,quick-start-linux.sh, and every doc) usedadb reverse, which maps a phone port to the computer. The app's USB server listens on the phone's loopback, so the client needsadb forward(computer port -> phone port); with the app running,adb reversefailed with "cannot bind listener: Address already in use". Confirmed against a real phone. The e2e adb stand-in now emulates both directions faithfully, so the wrong one fails the test. - Android: the phone lost its internet after a desktop session, and Stop didn't fix it: when the desktop disconnected, the VPN stayed established (all phone traffic routed into a dead tunnel), the app never accepted another connection (so desktop auto-reconnect could not work) and kept showing "Connected". The Stop button used
stopService(), which cannot stop a VpnService whose VPN is up, so only force-stopping the app restored the phone's network. Sessions now run in a loop that tears the VPN down after every session and waits for the next desktop; Stop sends an explicit stop action. The VPN is also only established after a successful handshake, so a client with a wrong token no longer touches the phone's routing. Found on a real phone (Android 13). - Ctrl-C raced the Disconnect message: the retry loop could drop the live session before it told the phone it was leaving; it now lets the session finish (up to 3 s) and never reconnects once stopping.
- Desktop forwarding stall: the TUN reader held the device mutex during its blocking read, so packets from the phone were only written to the TUN device when the desktop happened to send something. The forwarding loop now uses the async TUN device with independent read/write halves (shared
sessionmodule). - GUI Connect did nothing: the button only changed the status label. It now runs a real session (same runner as the CLI) with live state, stats and logs; Disconnect stops it. GUI-created profiles defaulted to port 8765 instead of 8888.
- Bluetooth (Linux): the RFCOMM connection was opened and then abandoned with "integration incomplete"; it now completes the handshake (with
--token/auth.bluetooth_token) and forwards packets. - CLI:
--reconnectcould not be turned off (it defaulted to true);save-profile --typefrom the README was rejected;sudo etphonehome connectlooked in root's config instead of the invoking user's; WiFi hosts had to be IP literals; Ctrl-C now sends Disconnect; wrong-token rejections now show the phone's reason instead of "Unexpected message type"; saving a profile from the CLI no longer wipes its filter rules;list-profilesoutput goes to stdout; a silent phone is detected after 90 s so auto-reconnect can kick in. - Android: stats, keepalive and packet writers shared one socket stream without locking (frames could interleave); StatsUpdate was 20 bytes instead of the specified 24. One shared
ServerHandshakereplaces three copies. - Release packaging: release.yml stripped/zipped binaries that don't exist (
etphonehome-linux,etphonehome-windows.exe) and expected an unsigned APK; CI artifact uploads pointed at the same wrong names. - quick-start-linux.sh: failed on kernels with built-in tun (modprobe under
set -e) and required Rust even when the client was already built. - Docs: Windows needs
wintun.dll, not TAP-Windows; Windows Bluetooth is not supported yet.
Tests / CI
- New end-to-end CI job runs the real client through a real TUN device against an Android-protocol stand-in (plaintext, TLS, wrong tokens, USB via adb, filters, auto-reconnect, quick-start script).
- Shared Rust/Kotlin golden wire vectors (
protocol/test-vectors.txt); 13 orphaned protocol tests that never compiled now run; TUN tests run with CAP_NET_ADMIN in CI.
Downloads
-
Source code (ZIP)
1 download
-
Source code (TAR.GZ)
2 downloads
- The computer really gets the phone's internet, without root. The Android app now has a userspace relay (