Skip to content

About

Tunly Mobile — SSH SOCKS5 tunnels routing all device traffic, via Android VpnService. Shared Go core (gomobile), Flutter UI. iOS planned.

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

50 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tunly logo

Tunly Mobile

Quick SSH tunnels, in your pocket.

CI Latest release License: MIT Android Flutter Go core

Mobile port of tunly — manage named SSH dynamic (SOCKS5) tunnels and route all device traffic through the one you pick. Android first; iOS planned (the core is already portable).

A mole digs tunnels — so does this.

🖥️ On Linux? The original tunly is a GNOME tray applet that drives the system proxy.

What it does

  • Named tunnels — save several SSH endpoints, start one with a tap. One active at a time.
  • Whole-device VPN — an Android VpnService captures all traffic and forwards it through the SSH tunnel via a userspace netstack (tun2socks). No root.
  • Reconnect + fail-closed — survives network switches (Wi-Fi ↔ cellular). While reconnecting, traffic is blocked rather than leaked; a watchdog restores normal networking if the tunnel can't recover, so you're never stranded offline.
  • Key or password auth — imported private key (passphrase-capable) or password.

You need an SSH server

Tunly is a client. It doesn't provide servers — it tunnels your traffic through an SSH server you control and then out to the internet. So your exit IP becomes that server's IP. You need a Linux box you can SSH into with outbound internet; almost any small VPS works (the tunnel only needs sshd + bandwidth — no special software on the server).

Getting one

Create a small Linux VM, note its public IP, and you're the root/sudo user. Popular options (prices/tiers change — verify before signing up):

Provider Cheapest Free tier Notes
Google Cloud — 1× e2-micro/month free in select US regions Free-tier VM is enough for a tunnel
AWS Lightsail ~$3.50/mo EC2 t3.micro free for 12 months Lightsail is the simplest AWS path
Hetzner Cloud ~€4/mo (CX22) — Cheapest reliable paid VPS; EU + US regions
Vultr ~$2.50–5/mo — Many regions, hourly billing
DigitalOcean $4/mo droplet Signup credit (often $200/60 days) Beginner-friendly
Linode (Akamai) $5/mo Signup credit Simple, well-documented
Fly.io small VMs, usage-based limited free allowance Container-style, quick to spin up

Point Tunly at it

  1. Spin up the smallest Linux VM (Ubuntu/Debian is fine).
  2. Add your public key to the server: ssh-copy-id user@SERVER_IP (or paste it into ~/.ssh/authorized_keys).
  3. In Tunly: New tunnel → host = SERVER_IP, user = your login, Key = paste the matching private key (stored encrypted; never shown again).
  4. Tap ▶ and allow the VPN prompt.

Server hardening (recommended): use key auth and disable SSH passwords (PasswordAuthentication no in /etc/ssh/sshd_config), keep the box patched, and restrict the firewall to port 22.

Security model

  • Secrets at rest — tunnel configs, including the private key/password, are stored in Android Keystore-backed EncryptedSharedPreferences (AES-GCM), never in plaintext. allowBackup is off, so they don't leave the device.
  • Host keys — trust-on-first-use: the server's key is pinned on first connect; a later mismatch is treated as a possible MITM and terminates the tunnel (no silent re-pin).
  • No self-capture — the app excludes itself from its own VPN so the SSH uplink bypasses the tun (a full tunnel would otherwise trap its own bootstrap).
  • The core never touches disk — secrets are passed in at connect time; the Go core reads no files and persists nothing.

Architecture

Three layers; the Go core is the only shared/portable code.

Flutter (Dart)        UI, tunnel list, encrypted config store
  └ MethodChannel/EventChannel
Native shell (Kotlin) VpnService, tun fd, notification, reconnect watchdog,
  └ gomobile .aar     network-change nudge, Keystore secret store
Go core (.aar)        SSH client + keepalive, tun2socks, DNS-over-TCP,
                      host-key TOFU, reconnect supervisor, state machine
  • core/ — Go module (go test ./... runs on desktop; no mobile toolchain needed). See core/cmd/tunlye2e for a real end-to-end harness.
  • app/ — Flutter app + Kotlin VpnService shell.
  • docs/superpowers/ — design spec and implementation plan.

Build

Requires Go 1.25, the Flutter SDK, the Android SDK + NDK, and gomobile.

# 1. Build the Go core into an Android .aar
cd core
gomobile bind -target=android/arm64 -androidapi 23 \
  -o ../app/android/app/libs/tunlycore.aar ./mobile

# 2. Build + install the app
cd ../app
flutter build apk --debug
flutter install

The .aar is a generated build artifact and is not committed.

Status

Android: working end-to-end (SSH auth, host-key pinning, whole-device routing, reconnect). iOS: the Go core is portable via gomobile's xcframework target; the PacketTunnel shell is not built yet.

License

MIT © Ahmed Toulan

About

Tunly Mobile — SSH SOCKS5 tunnels routing all device traffic, via Android VpnService. Shared Go core (gomobile), Flutter UI. iOS planned.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages