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在不同平台上的配置可能会有所不同,确保你查阅了相关平台的文档和配置指南。 
请根据你的具体需求调整上述代码,并确保在发布应用之前进行充分的测试。
 
        
       
             
             
            

