- Android: Dart FFI → Go c-shared (.so) in jniLibs (arm64-v8a + x86_64) - Linux: Dart FFI → Go c-shared (.so) via Docker cross-compilation (amd64) - Dart API: TsnetFlutter uses MethodChannel on iOS/macOS, FFI on Android/Linux - Add ffi package dependency for native function bindings - Build script: ./build_go.sh [ios|macos|android|linux|apple|all] - Android RegisterInterfaceGetter to bypass netlink CAP_NET_ADMIN restriction - Make TailscaleStart() idempotent and add GODEBUG=netdns=go for Android Known: Android tsnet tunnel blocked by Go stdlib net.Interfaces() netlink call — local gRPC works, Tailscale fallback needs libtailscale integration. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .gitea/workflows | ||
| android | ||
| ios | ||
| lib | ||
| linux | ||
| macos | ||
| test | ||
| .gitignore | ||
| .pubignore | ||
| build_go.sh | ||
| CHANGELOG.md | ||
| LICENSE | ||
| pubspec.lock | ||
| pubspec.yaml | ||
| README.md | ||
tsnet_flutter
Embed Tailscale's tsnet in Flutter apps. Provides a userspace WireGuard tunnel with a localhost TCP proxy — no VPN entitlement needed on iOS.
How it works
Flutter (Dart) → MethodChannel → Swift Plugin → Go static library (tsnet)
↓
WireGuard tunnel (userspace)
↓
Remote device (100.x.x.x)
The Go layer runs a local TCP proxy: your app connects to localhost:PORT, and traffic is forwarded through a WireGuard tunnel to the target device's Tailscale IP. Flutter doesn't know about Tailscale — it just sees a localhost port.
Usage
import 'package:tsnet_flutter/tsnet_flutter.dart';
final tsnet = TsnetFlutter();
// Join the Tailnet
await tsnet.start(authKey: 'tskey-auth-...');
// Create a local proxy to the remote device
final localPort = await tsnet.startProxy('100.64.0.5', port: 5050);
// Connect your client to the proxy
yourClient.connect('127.0.0.1', port: localPort);
// Clean up
await tsnet.stopProxy();
await tsnet.stop();
Platform support
| Platform | Status | Min version |
|---|---|---|
| iOS | Supported (arm64 device + simulator) | 14.0 |
| macOS | Supported (arm64 + x86_64 universal) | 12.0 |
| Android | Planned | — |
Platform setup
iOS
No special entitlements or permissions needed. No VPN entitlement required.
macOS
macOS apps run sandboxed. Add these entitlements to both DebugProfile.entitlements and Release.entitlements:
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
network.client allows the app to connect to the localhost proxy and external networks. network.server allows the Go layer to open a localhost listener for the proxy.
Requirements
- Tailscale auth key (generate at login.tailscale.com)
Building from source
The pre-built xcframeworks are included in the package. To rebuild from Go source:
# Prerequisites: Go 1.23+, Xcode with iOS + macOS SDKs
./build_go.sh # build all platforms
./build_go.sh ios # iOS only
./build_go.sh macos # macOS only
License
BSD-3-Clause. See LICENSE.