Flutter VPN配置插件wireguard_2govpn的使用
Flutter VPN配置插件wireguard_2govpn的使用
介绍
wireguard_2govpn
是一个用于通过 WireGuard 隧道设置和控制VPN连接的 Flutter 插件。
使用
初始化
首先,在你的项目中添加 wireguard_2govpn
依赖:
flutter pub add wireguard_2govpn
初始化 WireGuard 实例:
final wireguard = WireGuardFlutter.instance;
// 初始化接口
await wireguard.initialize(interfaceName: 'wg0');
然后声明 .conf
数据:
const String conf = '''[Interface]
PrivateKey = 0IZmHsxiNQ54TsUs0EQ71JNsa5f70zVf1LmDvON1CXc=
Address = 10.8.0.4/32
DNS = 1.1.1.1
[Peer]
PublicKey = 6uZg6T0J1bHuEmdqPx8OmxQ2ebBJ8TnVpnCdV8jHliQ=
PresharedKey = As6JiXcYcqwjSHxSOrmQT13uGVlBG90uXZWmtaezZVs=
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 0
Endpoint = 38.180.13.85:51820''';
更多关于配置数据的信息,可以参见 文档 中的例子。
连接
初始化后,使用 startVpn
方法进行连接:
await wireguard.startVpn(
serverAddress: address, // 例如 'demo.wireguard.com:51820'
wgQuickConfig: conf, // 快速配置文件
providerBundleIdentifier: 'com.example', // 你的应用标识符
);
断开连接
连接后,使用 stopVpn
方法断开连接:
await wireguard.stopVpn();
监听阶段变化
监听阶段变化使用 vpnStageSnapshot
:
wireguard.vpnStageSnapshot.listen((event) {
debugPrint("状态改变 $event");
});
或者获取当前阶段使用 getStage
:
final stage = await wireguard.stage();
可用阶段包括:
代码 | 描述 |
---|---|
connecting | 接口正在连接 |
connected | 接口已连接 |
disconnecting | 接口正在断开连接 |
disconnected | 接口已断开连接 |
waitingConnection | 等待用户交互 |
authenticating | 正在与服务器认证 |
reconnect | 重新连接接口 |
noConnection | 任何连接都没有建立 |
preparing | 准备连接 |
denied | 连接被系统拒绝,通常是权限问题 |
exiting | 接口退出 |
支持的平台
平台 | Android | iOS | macOS | Windows | Linux |
---|---|---|---|---|---|
版本 | SDK 21+ | 15.0+ | 12+ | 7+ | 任意 |
Windows
在 Windows 上,应用必须以管理员身份运行才能创建和操作隧道。要调试应用,请从提升后的命令提示符运行 flutter run
。要正常运行应用,系统会请求你以管理员身份运行应用。无需进行代码更改或外部依赖。
Linux
安装依赖
需要安装以下依赖:wireguard
和 wireguard-tools
。
在 Ubuntu/Debian 上,使用以下命令安装依赖:
sudo apt install wireguard wireguard-tools openresolv
对于其他 Linux 发行版,请参阅 这里。
注意: 如果系统中未安装 openresolv
,配置文件中的 DNS 可能无法连接。更多信息请参阅 此问题。
初始化
当调用 wireguard.initialize
时,应用程序将请求用户密码([sudo] password for <user>:
)。这是必要的,因为 WireGuard 必须以 root 身份运行才能创建和操作隧道。这适用于调试模式、发布模式或分布式可执行文件。
警告: 不要在 root 模式下运行应用(例如 sudo ./executable
或 sudo flutter run
),否则连接将无法建立。
常见问题及故障排除
Linux 错误 resolvconf: command not found
在 Linux 上,可能会收到错误 resolvconf: command not found
。这是因为 WireGuard 尝试调整名称服务器。确保安装了 openresolv
或不提供 “DNS” 字段。
示例代码
以下是一个完整的示例代码,展示了如何使用 wireguard_2govpn
插件:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:wireguard_2govpn/wireguard_2govpn.dart';
void main() {
runApp(
MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('WireGuard 示例应用'),
),
body: const MyApp(),
),
),
);
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final wireguard = WireGuardFlutter.instance;
late String name;
[@override](/user/override)
void initState() {
super.initState();
wireguard.vpnStageSnapshot.listen((event) {
debugPrint("状态改变 $event");
if (mounted) {
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('状态改变: $event'),
));
}
});
name = 'my_wg_vpn';
}
Future<void> initialize() async {
try {
await wireguard.initialize(interfaceName: name);
debugPrint("初始化成功 $name");
} catch (error, stack) {
debugPrint("初始化失败: $error\n$stack");
}
}
void startVpn() async {
try {
await wireguard.startVpn(
serverAddress: '167.235.55.239:51820',
wgQuickConfig: conf,
providerBundleIdentifier: 'com.billion.wireguardvpn.WGExtension',
);
} catch (error, stack) {
debugPrint("启动失败 $error\n$stack");
}
}
void disconnect() async {
try {
await wireguard.stopVpn();
} catch (e, str) {
debugPrint('断开失败 $e\n$str');
}
}
void getStatus() async {
debugPrint("获取状态");
final stage = await wireguard.stage();
debugPrint("阶段: $stage");
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('阶段: $stage'),
));
}
}
[@override](/user/override)
Widget build(BuildContext context) {
return Container(
constraints: const BoxConstraints.expand(),
padding: const EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 20),
TextButton(
onPressed: initialize,
style: ButtonStyle(
minimumSize: MaterialStateProperty.all<Size>(const Size(100, 50)),
padding: MaterialStateProperty.all(const EdgeInsets.fromLTRB(20, 15, 20, 15)),
backgroundColor: MaterialStateProperty.all<Color>(Colors.blueAccent),
overlayColor: MaterialStateProperty.all<Color>(Colors.white.withOpacity(0.1))),
child: const Text(
'初始化',
style: TextStyle(color: Colors.white),
),
),
const SizedBox(height: 20),
TextButton(
onPressed: startVpn,
style: ButtonStyle(
minimumSize: MaterialStateProperty.all<Size>(const Size(100, 50)),
padding: MaterialStateProperty.all(const EdgeInsets.fromLTRB(20, 15, 20, 15)),
backgroundColor: MaterialStateProperty.all<Color>(Colors.blueAccent),
overlayColor: MaterialStateProperty.all<Color>(Colors.white.withOpacity(0.1))),
child: const Text(
'连接',
style: TextStyle(color: Colors.white),
),
),
const SizedBox(height: 20),
TextButton(
onPressed: disconnect,
style: ButtonStyle(
minimumSize: MaterialStateProperty.all<Size>(const Size(100, 50)),
padding: MaterialStateProperty.all(const EdgeInsets.fromLTRB(20, 15, 20, 15)),
backgroundColor: MaterialStateProperty.all<Color>(Colors.blueAccent),
overlayColor: MaterialStateProperty.all<Color>(Colors.white.withOpacity(0.1))),
child: const Text(
'断开连接',
style: TextStyle(color: Colors.white),
),
),
const SizedBox(height: 20),
TextButton(
onPressed: getStatus,
style: ButtonStyle(
minimumSize: MaterialStateProperty.all<Size>(const Size(100, 50)),
padding: MaterialStateProperty.all(const EdgeInsets.fromLTRB(20, 15, 20, 15)),
backgroundColor: MaterialStateProperty.all<Color>(Colors.blueAccent),
overlayColor: MaterialStateProperty.all<Color>(Colors.white.withOpacity(0.1))),
child: const Text(
'获取状态',
style: TextStyle(color: Colors.white),
),
),
],
),
);
}
}
const String conf = '''[Interface]
PrivateKey = 0IZmHsxiNQ54TsUs0EQ71JNsa5f70zVf1LmDvON1CXc=
Address = 10.8.0.4/32
DNS = 1.1.1.1
[Peer]
PublicKey = 6uZg6T0J1bHuEmdqPx8OmxQ2ebBJ8TnVpnCdV8jHliQ=
PresharedKey = As6JiXcYcqwjSHxSOrmQT13uGVlBG90uXZWmtaezZVs=
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 0
Endpoint = 38.180.13.85:51820''';
更多关于Flutter VPN配置插件wireguard_2govpn的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter VPN配置插件wireguard_2govpn的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中配置和使用wireguard_2govpn
插件的示例代码。这个插件允许你在Flutter应用中配置和使用WireGuard VPN。
首先,你需要在你的pubspec.yaml
文件中添加wireguard_2govpn
依赖:
dependencies:
flutter:
sdk: flutter
wireguard_2govpn: ^最新版本号 # 请替换为实际的最新版本号
然后运行flutter pub get
来获取依赖。
接下来,你需要在你的Flutter应用中配置和使用WireGuard。以下是一个简单的示例,展示如何初始化WireGuard配置并启动VPN连接。
主应用代码(main.dart
)
import 'package:flutter/material.dart';
import 'package:wireguard_2govpn/wireguard_2govpn.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late WireGuard2GoVpn _wireguard;
bool _isConnected = false;
@override
void initState() {
super.initState();
_wireguard = WireGuard2GoVpn();
_initializeWireGuard();
}
Future<void> _initializeWireGuard() async {
try {
// 配置WireGuard,例如接口名称、私钥、公钥、服务器地址等
String interfaceName = "wg0";
String privateKey = "你的私钥";
List<Map<String, String>> peers = [
{
"publicKey": "服务器的公钥",
"endpoint": "服务器的地址:端口",
"allowedIPs": "0.0.0.0/0, ::/0", // 允许的IP范围
"persistentKeepalive": "25", // 持久性保活时间(秒)
},
// 可以添加更多peer配置
];
// 设置配置
await _wireguard.setConfig(
interfaceName: interfaceName,
privateKey: privateKey,
peers: peers,
);
// 启动VPN连接
bool success = await _wireguard.start();
if (success) {
setState(() {
_isConnected = true;
});
} else {
// 处理启动失败的情况
print("Failed to start WireGuard");
}
} catch (e) {
print("Error initializing WireGuard: $e");
}
}
Future<void> _stopWireGuard() async {
try {
bool success = await _wireguard.stop();
if (success) {
setState(() {
_isConnected = false;
});
} else {
// 处理停止失败的情况
print("Failed to stop WireGuard");
}
} catch (e) {
print("Error stopping WireGuard: $e");
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('WireGuard VPN Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Connection Status: $_isConnected',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _isConnected ? _stopWireGuard : () async {
await _initializeWireGuard();
},
child: Text(_isConnected ? 'Stop VPN' : 'Start VPN'),
),
],
),
),
),
);
}
}
注意事项
-
权限:在Android上,你可能需要在
AndroidManifest.xml
中添加必要的网络权限。在iOS上,你可能需要在Info.plist
中添加网络权限和后台模式权限。 -
私钥和公钥:在实际应用中,私钥和公钥应该是安全的,并且不应该硬编码在代码中。你可能需要使用安全的存储方式,如Keychain(iOS)或KeyStore(Android)。
-
依赖项:
wireguard_2govpn
插件可能依赖于特定的系统库或二进制文件,确保你的设备或模拟器已经安装了必要的依赖项。 -
错误处理:示例代码中的错误处理非常基础,在实际应用中你应该添加更详细的错误处理和用户反馈机制。
-
平台特定配置:WireGuard在不同平台上的配置可能会有所不同,确保你查阅了相关平台的文档和配置指南。
请根据你的具体需求调整上述代码,并确保在发布应用之前进行充分的测试。