flutter_netbird 1.0.1 copy "flutter_netbird: ^1.0.1" to clipboard
flutter_netbird: ^1.0.1 copied to clipboard

A Flutter FFI plugin for NetBird mesh VPN, providing secure peer-to-peer connectivity, DNS resolution, and HTTP proxy across Android, iOS, macOS, Windows, and Linux.

flutter_netbird #

A Flutter FFI plugin for NetBird, providing secure mesh VPN connectivity for Flutter applications across Android, iOS, macOS, Windows, and Linux.

Features #

  • 🌐 Cross-Platform: Android, iOS, macOS, Windows, and Linux support
  • 🔒 Secure Mesh VPN: Peer-to-peer encrypted connections using WireGuard
  • 📱 Userspace Networking: No root/admin privileges required on mobile
  • 🎯 Type-Safe API: Strongly typed Dart models for all operations
  • 📊 Real-time Status: Stream-based event and log monitoring
  • 🔧 Flexible Configuration: Comprehensive configuration options
  • 🌍 HTTP Proxy with DNS: HTTP requests through NetBird tunnel with in-process DNS resolution for Custom Zone domains

Installation #

Add this to your package's pubspec.yaml file:

dependencies:
  flutter_netbird:
    path: ../flutter_netbird  # Adjust path as needed

Quick Start #

import 'package:flutter_netbird/flutter_netbird.dart';
import 'package:path_provider/path_provider.dart';

// 1. Get the SDK instance
final sdk = NetbirdSDK();

// 2. Set up event listeners
sdk.events.listen((event) {
  print('NetBird Event: ${event.type} - ${event.data}');
});

sdk.logs.listen((log) {
  print('${log.levelName}: ${log.message}');
});

// 3. Initialize with configuration
final docDir = await getApplicationDocumentsDirectory();
final config = NetbirdConfig(
  configPath: "${docDir.path}/netbird_config.json",
  statePath: "${docDir.path}/netbird_state.json",
  managementURL: "https://api.netbird.io",
  deviceName: "my-flutter-device",
  logLevel: "info",
);

sdk.initialize(config);

// 4. Connect with credentials
final auth = NetbirdAuth(setupKey: "YOUR-SETUP-KEY");
sdk.up(auth: auth);

// 5. Monitor status
Timer.periodic(Duration(seconds: 2), (timer) {
  final status = sdk.getFullStatus();
  print('Status: ${status.status}, IP: ${status.ip}');
});

API Reference #

NetbirdSDK #

The main SDK class providing all NetBird functionality.

Methods

initialize(NetbirdConfig config) → int

Initializes the NetBird SDK with configuration. Must be called before up().

Returns: 0 on success, non-zero on error.

final config = NetbirdConfig(
  configPath: "/path/to/config.json",
  statePath: "/path/to/state.json",
  managementURL: "https://api.netbird.io",
  deviceName: "my-device",
  logLevel: "info",
  setupKey: "optional-setup-key",  // Can be provided here or in up()
);

final result = sdk.initialize(config);
if (result != 0) {
  print('Initialization failed: $result');
}
up({NetbirdAuth? auth}) → int

Starts the NetBird connection.

Returns:

  • 0 on success
  • 1 on error
  • 2 if already running
final auth = NetbirdAuth(setupKey: "YOUR-SETUP-KEY");
final result = sdk.up(auth: auth);
down() → int

Stops the NetBird connection.

Returns: 0 on success, non-zero on error.

sdk.down();
getStatus() → String

Returns a simple status string.

Possible values: "Stopped", "Connecting", "Connected", "Disconnected", "Error"

final status = sdk.getStatus();
print('Current status: $status');
getFullStatus() → NetbirdFullStatus

Returns detailed status information as a typed object.

final status = sdk.getFullStatus();
print('Status: ${status.status}');
print('IP: ${status.ip}');
print('Peers: ${status.peersCount}');

for (var peer in status.peers) {
  print('Peer: ${peer.fqdn} (${peer.ip}) - ${peer.direct ? "Direct" : "Relayed"}');
}
setLogLevel(String level) → int

Changes the log level at runtime.

Valid levels: "trace", "debug", "info", "warn", "error"

sdk.setLogLevel("debug");
cleanup() → void

Cleans up all resources. Call this when shutting down the app.

@override
void dispose() {
  sdk.cleanup();
  super.dispose();
}

Properties

events → Stream<NetbirdEvent>

Stream of NetBird events (state changes, errors, etc.).

sdk.events.listen((event) {
  print('Event type: ${event.type}');
  print('Event data: ${event.data}');

  // Parse as JSON if needed
  final json = event.dataAsJson;
  if (json?['error'] != null) {
    print('Error occurred: ${json!['error']}');
  }
});
logs → Stream<NetbirdLog>

Stream of NetBird log messages.

sdk.logs.listen((log) {
  print('[${log.levelName}] ${log.message}');
});
isInitialized → bool

Whether the SDK has been initialized.

if (sdk.isInitialized) {
  // Safe to call up()
}

Configuration Classes #

NetbirdConfig

Configuration for initializing NetBird.

NetbirdConfig({
  String? deviceName,           // Device identifier in the network
  String? managementURL,        // Management server URL
  String? configPath,           // Path to config file (for persistence)
  String? statePath,            // Path to state file
  String logLevel = 'info',     // Log level
  String? setupKey,             // Setup key (can be provided in up() instead)
  String? jwtToken,             // JWT token (alternative to setupKey)
  String? privateKey,           // Private key (alternative to setupKey)
  String? preSharedKey,         // WireGuard pre-shared key
  bool disableClientRoutes = false,  // Disable client routes
  bool blockInbound = false,    // Block inbound connections
  int? wireguardPort,           // WireGuard port (null = random)
})

Important: configPath is highly recommended for mobile apps to persist the device identity across restarts.

NetbirdAuth

Authentication credentials for connecting.

NetbirdAuth({
  String? setupKey,     // Setup key from NetBird management portal
  String? jwtToken,     // JWT token
  String? privateKey,   // Private key
})

Note: Only one authentication method should be provided.

Status Classes #

NetbirdFullStatus

Comprehensive status information.

Properties:

  • String status - Connection status
  • String? error - Error message if any
  • Map<String, dynamic>? managementState - Management server state
  • Map<String, dynamic>? signalState - Signal server state
  • NetbirdPeerInfo? localPeer - Local peer information
  • int peersCount - Number of connected peers
  • List<NetbirdPeerInfo> peers - List of connected peers
  • int? forwardingRules - Number of forwarding rules
  • String? ip - Local NetBird IP address
  • String? publicKey - Public key
  • String? fqdn - Fully qualified domain name

NetbirdPeerInfo

Information about a peer.

Properties:

  • String? ip - Peer IP address
  • String? fqdn - Peer FQDN
  • String? connectionType - Connection type
  • bool? direct - Whether connection is direct (not relayed)
  • String? latency - Connection latency
  • int? bytesRx - Bytes received
  • int? bytesTx - Bytes transmitted

Memory Management #

Critical: Callback Memory Safety ⚠️ #

This plugin has been designed with careful attention to memory management:

Callbacks (Events and Logs):

  • Safe: The Go side automatically frees memory after callbacks return
  • No action needed: Dart code should NOT call FreeString on callback data
  • Just read: Simply call toDartString() to copy the data to Dart

Return Values (Status Methods):

  • ⚠️ Dart must free: Strings returned from getStatus() and getFullStatus()
  • Handled internally: The SDK automatically calls FreeString - you don't need to worry about it
// ✅ CORRECT: Events are auto-freed
sdk.events.listen((event) {
  final data = event.data;  // Safe, memory auto-freed
});

// ✅ CORRECT: Status is auto-freed
final status = sdk.getFullStatus();  // Safe, SDK handles cleanup

Platform-Specific Notes #

Android #

  • Add the following to android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

iOS #

  • Add the following to ios/Runner/Info.plist:
<key>NSLocalNetworkUsageDescription</key>
<string>NetBird needs access to local network for VPN connections</string>

macOS #

  • Enable network entitlements in macos/Runner/DebugProfile.entitlements and Release.entitlements:
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>

Building Native Libraries #

The native NetBird libraries are built from the netbird_core Go package:

cd ../netbird_core
./build_all.sh

This generates platform-specific binaries:

  • Android: libnetbird.so
  • iOS/macOS: libnetbird.xcframework / libnetbird.dylib
  • Windows: libnetbird.dll
  • Linux: libnetbird.so

Place these in the appropriate directories as specified in the plugin structure.

Example App #

See the example/ directory for a complete Flutter application demonstrating:

  • ✅ Connection management
  • ✅ Real-time status monitoring
  • ✅ Peer list display
  • ✅ Log viewer
  • ✅ Settings configuration

Run the example:

cd example
flutter run

Troubleshooting #

"Failed to load dynamic library" #

Ensure the native library is properly included in your build:

  • Android: Check android/app/src/main/jniLibs/
  • iOS: Check Xcode framework embedding
  • macOS: Check that the library is in the bundle

DNS Resolution Fails ("server misbehaving") #

If HTTP requests to custom domains fail with server misbehaving but IP access works:

  1. Verify the domain is configured as a DNS Zone (not Nameserver Group) in NetBird management
  2. Ensure the zone is Active and the A record is correctly configured
  3. The plugin resolves custom domains in-process from the management server's SyncResponse, bypassing netstack UDP DNS

Connection Fails #

  1. Check your setup key is valid
  2. Verify the management URL is accessible
  3. Check logs for specific errors:
sdk.logs.listen((log) {
  if (log.level <= 2) {  // ERROR or FATAL
    print('ERROR: ${log.message}');
  }
});

Device Not Persisting #

Make sure configPath is set to a writable location:

final docDir = await getApplicationDocumentsDirectory();
final config = NetbirdConfig(
  configPath: "${docDir.path}/netbird_config.json",  // Important!
  // ...
);

Contributing #

Contributions are welcome! Please feel free to submit a Pull Request.

License #

This project is part of the NetBird ecosystem. See the main NetBird repository for licensing information.

Credits #

Built on top of NetBird - Open-source mesh VPN platform.

0
likes
135
points
54
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter FFI plugin for NetBird mesh VPN, providing secure peer-to-peer connectivity, DNS resolution, and HTTP proxy across Android, iOS, macOS, Windows, and Linux.

Documentation

API reference

License

MIT (license)

Dependencies

ffi, flutter, plugin_platform_interface

More

Packages that depend on flutter_netbird

Packages that implement flutter_netbird