Flutter VPN配置插件wireguard_flutter的使用

Flutter VPN配置插件wireguard_flutter的使用

简介

wireguard_flutter 是一个Flutter插件,用于通过WireGuard隧道设置和控制VPN连接。

使用方法

添加插件

首先,在您的Flutter项目中添加 wireguard_flutter 插件:

flutter pub add wireguard_flutter
初始化

初始化一个带有有效名称的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("status changed $event");
});

或者获取当前状态使用 getStage

final stage = await wireguard.stage();

可用的状态包括:

Code Description
connecting 接口正在连接
connected 接口已连接
disconnecting 接口正在断开连接
disconnected 接口已断开连接
waitingConnection 等待用户交互
authenticating 正在与服务器进行身份验证
reconnect 重新连接到接口
noConnection 尚未建立任何连接
preparing 准备连接
denied 系统拒绝连接,通常是由于权限被拒绝
exiting 退出接口

完整示例Demo

以下是一个完整的Flutter应用示例,展示了如何使用 wireguard_flutter 插件:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:wireguard_flutter/wireguard_flutter.dart';

void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('WireGuard Example App'),
        ),
        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("status changed $event");
      if (mounted) {
        ScaffoldMessenger.of(context).clearSnackBars();
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(
          content: Text('status changed: $event'),
        ));
      }
    });
    name = 'my_wg_vpn';
  }

  Future<void> initialize() async {
    try {
      await wireguard.initialize(interfaceName: name);
      debugPrint("initialize success $name");
    } catch (error, stack) {
      debugPrint("failed to initialize: $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("failed to start $error\n$stack");
    }
  }

  void disconnect() async {
    try {
      await wireguard.stopVpn();
    } catch (e, str) {
      debugPrint('Failed to disconnect $e\n$str');
    }
  }

  void getStatus() async {
    debugPrint("getting stage");
    final stage = await wireguard.stage();
    debugPrint("stage: $stage");

    if (mounted) {
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(
        content: Text('stage: $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(
              'Initialize',
              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(
              'Connect',
              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(
              'Disconnect',
              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(
              'Get Status',
              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_flutter的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter VPN配置插件wireguard_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,关于在Flutter项目中使用wireguard_flutter插件来配置VPN(虚拟私人网络),以下是一个简单的示例代码,展示了如何集成和使用这个插件。请注意,使用VPN插件需要处理敏感的网络配置和权限,确保你遵循所有相关的法律和平台政策。

首先,确保你已经在pubspec.yaml文件中添加了wireguard_flutter依赖:

dependencies:
  flutter:
    sdk: flutter
  wireguard_flutter: ^最新版本号 # 请替换为实际的最新版本号

然后,运行flutter pub get来安装依赖。

接下来,在你的Flutter项目中,你可以按照以下步骤来配置和使用WireGuard。

1. 导入插件

在你的Dart文件中(例如main.dart),导入wireguard_flutter插件:

import 'package:wireguard_flutter/wireguard_flutter.dart';

2. 请求权限

由于配置VPN涉及到敏感操作,你需要在Android和iOS上请求必要的权限。以下是一个简单的权限请求示例(这里只展示了Android的权限请求,iOS的权限请求需要在Info.plist中配置):

import 'package:permission_handler/permission_handler.dart';

void requestPermissions() async {
  // 请求必要的权限
  var status = await Permission.accessFineLocation.status;
  if (!status.isGranted) {
    Map<Permission, PermissionStatus> statuses = await [
      Permission.accessFineLocation,
      Permission.changeNetworkState, // 可能需要这个权限来更改网络连接
    ].request();

    print("Permission statuses: $statuses");
  }
}

别忘了在pubspec.yaml中添加permission_handler依赖:

dependencies:
  permission_handler: ^最新版本号 # 请替换为实际的最新版本号

3. 配置和使用WireGuard

下面是一个基本的WireGuard配置示例,展示了如何加载配置并应用它:

void configureWireGuard() async {
  try {
    // 示例WireGuard配置文件内容(这里应该是一个有效的WireGuard配置文件字符串)
    String config = '''
    [Interface]
    PrivateKey = YOUR_PRIVATE_KEY_HERE
    Address = 10.0.0.2/32

    [Peer]
    PublicKey = PEER_PUBLIC_KEY_HERE
    AllowedIPs = 0.0.0.0/0
    Endpoint = peer.example.com:51820
    PersistentKeepalive = 25
    ''';

    // 加载WireGuard配置
    bool success = await WireGuardFlutter.setConfig(config);
    if (success) {
      print("WireGuard配置成功");
    } else {
      print("WireGuard配置失败");
    }

    // 检查WireGuard状态
    WireGuardStatus status = await WireGuardFlutter.getStatus();
    print("WireGuard状态: $status");

    // 启用或禁用WireGuard接口
    bool enabled = await WireGuardFlutter.enableInterface();
    print("WireGuard接口启用状态: $enabled");

  } catch (e) {
    print("配置WireGuard时出错: $e");
  }
}

4. 在应用启动时调用

最后,在你的应用启动时调用这些函数,例如在main函数中:

void main() {
  runApp(MyApp());
  // 请求权限
  requestPermissions();
  // 配置WireGuard
  configureWireGuard();
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('WireGuard Flutter Example'),
        ),
        body: Center(
          child: Text('Check the console for WireGuard configuration status.'),
        ),
      ),
    );
  }
}

注意事项

  1. 私钥和公钥:在实际使用中,你需要用真实的私钥和公钥替换示例中的占位符。
  2. 权限:确保在Android和iOS上都正确配置了所有必要的权限。
  3. 安全性:处理VPN配置时要非常小心,确保不会泄露敏感信息。
  4. 法律和合规性:使用VPN配置插件时,请确保遵守所有相关的法律和平台政策。

这个示例提供了一个基本的框架,你可以根据自己的需求进一步扩展和修改。

回到顶部