@ohos.net.vpnExtension (VPN增强管理)

三方VPN管理模块,支持三方VPN的启动和停止功能。三方VPN是指由第三方提供的VPN服务,它们通常提供更多的功能和更广泛的网络连接选项,包括更多的安全和隐私功能,以及更全面的定制选项。当前提供三方VPN能力主要用于创建虚拟网卡及配置VPN路由信息,连接隧道过程及内部连接的协议需要应用内部自行实现。

说明:

本模块首批接口从 API version 11 开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。
以下模块不支持在VpnExtensionAbility中引用,可能会导致程序异常退出。

导入模块

import { vpnExtension } from '@kit.NetworkKit';

LinkAddress

type LinkAddress = connection.LinkAddress

获取网络链接信息。

系统能力:SystemCapability.Communication.NetManager.Core

类型 说明
connection.LinkAddress 网络链路信息。

RouteInfo

type RouteInfo = connection.RouteInfo

获取网络路由信息。

系统能力:SystemCapability.Communication.NetManager.Core

类型 说明
connection.RouteInfo 网络路由信息。

VpnExtensionContext

type VpnExtensionContext = _VpnExtensionContext

VPN扩展的上下文。它允许访问serviceExtension特定资源。

系统能力:SystemCapability.Ability.AbilityRuntime.Core

类型 说明
_VpnExtensionContext VPN扩展的上下文。

vpnExtension.startVpnExtensionAbility

startVpnExtensionAbility(want: Want): Promise<void>

启动新的三方VPN功能。使用Promise异步回调。

系统能力:SystemCapability.Ability.AbilityRuntime.Core

模型约束:此接口仅可在Stage模型下使用。

参数:

参数名 类型 必填 说明
want Want 指示要启动的信息。
说明: 从API version 22开始,支持在VPN首次启动时传递want中的parameters字段。

返回值:

类型 说明
Promise<void> Promise对象,无返回结果。

错误码:

以下错误码的详细介绍请参见元能力子系统错误码通用错误码

错误码ID 错误信息
401 If the input parameter is not valid parameter.
16000001 The specified ability does not exist.
16000002 Incorrect ability type.
16000006 Cross-user operations are not allowed.
16000008 The crowdtesting application expires.
16000011 The context does not exist.
16000050 Internal error.
16200001 The caller has been released.

示例: Stage 模型示例:

import { Want } from '@kit.AbilityKit';
import { vpnExtension } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';

let want: Want = {
  deviceId: "",
  bundleName: "com.example.myvpndemo",
  abilityName: "MyVpnExtAbility",
};

@Entry
@Component
struct Index {
  @State message: string = 'Hello World'

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(40)
          .fontWeight(FontWeight.Bold).onClick(() => {
          console.info("btn click")
        })
        Button('Start Extension').onClick(() => {
          vpnExtension.startVpnExtensionAbility(want).then(() => {
            console.info('startVpnExtensionAbility success');
          }).catch((err: BusinessError) => {
            console.error('startVpnExtensionAbility error: ' + JSON.stringify(err));
          })
        }).width('70%').fontSize(30).margin(16)
      }.width('100%')
    }.height('100%')
  }
}

vpnExtension.stopVpnExtensionAbility

stopVpnExtensionAbility(want: Want): Promise<void>

停止同一应用程序中的服务。使用Promise异步回调。

系统能力:SystemCapability.Ability.AbilityRuntime.Core

模型约束:此接口仅可在Stage模型下使用。

参数:

参数名 类型 必填 说明
want Want 指示要启动的信息。

返回值:

类型 说明
Promise<void> Promise对象,无返回结果。

错误码:

以下错误码的详细介绍请参见元能力子系统错误码通用错误码

错误码 ID 错误信息
401 If the input parameter is not valid parameter.
16000001 The specified ability does not exist.
16000002 Incorrect ability type.
16000006 Cross-user operations are not allowed.
16000011 The context does not exist.
16000050 Internal error.
16200001 The caller has been released.

示例: Stage 模型示例:

import { Want } from '@kit.AbilityKit';
import { vpnExtension } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';

let want: Want = {
  deviceId: "",
  bundleName: "com.example.myvpndemo",
  abilityName: "MyVpnExtAbility",
};

@Entry
@Component
struct Index {
  @State message: string = 'Hello World'

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold).onClick(() => {
          console.info("btn click")
        })
        Button('Start Extension').onClick(() => {
          vpnExtension.startVpnExtensionAbility(want).then(() => {
            console.info('startVpnExtensionAbility success');
          }).catch((err: BusinessError) => {
            console.error('startVpnExtensionAbility error: ' + JSON.stringify(err));
          })
        }).width('70%').fontSize(30).margin(16)
        Button('Stop Extension').onClick(() => {
          console.info("btn end")
          vpnExtension.stopVpnExtensionAbility(want).then(() => {
            console.info('stopVpnExtensionAbility success');
          }).catch((err: BusinessError) => {
            console.error('stopVpnExtensionAbility error: ' + JSON.stringify(err));
          })
        }).width('70%').fontSize(30).margin(16)

      }.width('100%')
    }.height('100%')
  }
}

vpnExtension.createVpnObserver

createVpnObserver(): VpnObserver

创建一个VPN观察者对象。用于监听VPN相关事件。

起始版本: 26.0.0

系统能力:SystemCapability.Communication.NetManager.Vpn

模型约束:此接口仅可在Stage模型下使用。

返回值:

类型 说明
VpnObserver 返回一个VPN观察者对象。

示例:

import { vpnExtension } from '@kit.NetworkKit';

let vpnObserver: vpnExtension.VpnObserver = vpnExtension.createVpnObserver();

VpnObserver

VPN观察者对象。用于监听VPN相关事件。在调用VpnObserver的方法前,需要先通过vpnExtension.createVpnObserver创建VPN连接对象。

onAuthorizationResult

onAuthorizationResult(callback: Callback<boolean>): void

注册用户授权结果监听器。授权结果在调用startVpnExtensionAbility弹出授权弹窗,用户点击弹窗后通知,仅接收当前VPN的结果。在不需要监听授权结果时可以调用offAuthorizationResult接口取消注册。

注意

多次调用该接口时,仅最后一次传入的callback生效。

起始版本: 26.0.0

系统能力:SystemCapability.Communication.NetManager.Vpn

模型约束:此接口仅可在Stage模型下使用。

参数:

参数名 类型 必填 说明
callback Callback<boolean> 回调函数,用于返回用户授权结果。true表示用户同意授权,false表示用户拒绝授权。

示例:

import { vpnExtension } from '@kit.NetworkKit';

let vpnObserver: vpnExtension.VpnObserver = vpnExtension.createVpnObserver();
vpnObserver.onAuthorizationResult((result: boolean) => {
  if (result) {
    console.info('VPN authorization succeeded');
  } else {
    console.error('VPN authorization failed');
  }
});

offAuthorizationResult

offAuthorizationResult(callback?: Callback<boolean>): void

取消注册用户授权结果监听器。

注意

多次调用onAuthorizationResult注册监听时,若需取消授权结果监听,需要传最后一次调用时传入的callback,或者不传入参数。

起始版本: 26.0.0

系统能力:SystemCapability.Communication.NetManager.Vpn

模型约束:此接口仅可在Stage模型下使用。

参数:

参数名 类型 必填 说明
callback Callback<boolean> 监听器回调函数,用于返回用户授权结果。
传入该参数:取消注册指定的监听器。不传参数:取消注册所有已注册的监听器。

示例:

import { vpnExtension } from '@kit.NetworkKit';

let vpnObserver: vpnExtension.VpnObserver = vpnExtension.createVpnObserver();

let callback = (result: boolean) => {
  console.info('Authorization result: ' + result);
};
// 注册监听器
vpnObserver.onAuthorizationResult(callback);

// 取消注册指定监听器
vpnObserver.offAuthorizationResult(callback);

// 取消注册已注册的监听器
vpnObserver.offAuthorizationResult();

vpnExtension.createVpnConnection

createVpnConnection(context: VpnExtensionContext): VpnConnection

创建一个三方VPN连接对象。

说明:

调用createVpnConnection接口前,需要先调用startVpnExtensionAbility接口启用VPN功能。

系统能力:SystemCapability.Communication.NetManager.Vpn

模型约束:此接口仅可在Stage模型下使用。

参数:

参数名 类型 必填 说明
context VpnExtensionContext 指定 context。

返回值:

类型 说明
VpnConnection 返回一个VPN连接对象。

错误码:

以下错误码的详细介绍请参见通用错误码

错误码ID 错误信息
401 Parameter error.

示例: Stage 模型示例:

import { vpnExtension, VpnExtensionAbility } from '@kit.NetworkKit';
import { common, Want } from '@kit.AbilityKit';

let context: vpnExtension.VpnExtensionContext;
export default class MyVpnExtAbility extends VpnExtensionAbility {
  onCreate(want: Want) {
    let vpnConnection : vpnExtension.VpnConnection = vpnExtension.createVpnConnection(context);
    console.info("VPN createVpnConnection: " + JSON.stringify(vpnConnection));
  }
}

VpnConnection

VPN连接对象。在调用VpnConnection的方法前,需要先通过vpnExt.createVpnConnection创建VPN连接对象。

create

create(config: VpnConfig): Promise<number>

使用config创建一个VPN网络。使用Promise异步回调。

说明:

建议在不需要VPN网络的时候配对调用destroy()destroy(vpnId: string)接口销毁启动的VPN网络,并执行资源清理等操作。

系统能力:SystemCapability.Communication.NetManager.Vpn

参数:

参数名 类型 必填 说明
config VpnConfig 指定VPN网络的配置信息。

返回值:

类型 说明
Promise<number> 以 Promise 形式返回获取结果,返回指定虚拟网卡的文件描述符 fd。

错误码:

以下错误码的详细介绍请参见VPN错误码通用错误码

错误码ID 错误信息
401 Parameter error.
2200001 Invalid parameter value.
2200002 Operation failed. Cannot connect to service.
2200003 System internal error.
2203001 VPN creation denied, please check the user type.
2203002 VPN exist already, please execute destroy first.

示例:

import { vpnExtension, VpnExtensionAbility } from '@kit.NetworkKit';
import { common, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';

let context: vpnExtension.VpnExtensionContext;
export default class MyVpnExtAbility extends VpnExtensionAbility {
  private tunIp: string = '10.0.0.5';
  private blockedAppName: string = 'com.example.myvpndemo';
  onCreate(want: Want) {
    let vpnConnection : vpnExtension.VpnConnection = vpnExtension.createVpnConnection(context);
    console.info("vpn createVpnConnection: " + JSON.stringify(vpnConnection));
    this.SetupVpn();
    
    // 不需要VPN网络时,调用destroy()接口销毁启动的VPN网络,并执行资源清理等操作。
    vpnConnection.destroy().then(() => {
      console.info("destroy success.");
    }).catch((error : BusinessError) => {
      console.error(`destroy fail. Code:${error.code}, message:${error.message}`);
    });
  }
  SetupVpn() {
        class Address {
            address: string;
            family: number;

            constructor(address: string, family: number) {
                this.address = address;
                this.family = family;
            }
        }

        class AddressWithPrefix {
            address: Address;
            prefixLength: number;

            constructor(address: Address, prefixLength: number) {
                this.address = address;
                this.prefixLength = prefixLength;
            }
        }

        class Config {
            addresses: AddressWithPrefix[];
            mtu: number;
            dnsAddresses: string[];
            trustedApplications: string[];
            blockedApplications: string[];

            constructor(
                tunIp: string,
                blockedAppName: string
            ) {
                this.addresses = [
                    new AddressWithPrefix(new Address(tunIp, 1), 24)
                ];
                this.mtu = 1400;
                this.dnsAddresses = ["114.114.114.114"];
                this.trustedApplications = [];
                this.blockedApplications = [blockedAppName];
            }
        }

        let config = new Config(this.tunIp, this.blockedAppName);

        try {
            let vpnConnection : vpnExtension.VpnConnection = vpnExtension.createVpnConnection(context);
            vpnConnection.create(config).then((data) => {
                hilog.error(0x0000, 'developTag', 'tunfd: %{public}s', JSON.stringify(data) ?? '');
            })
        } catch (error) {
            hilog.error(0x0000, 'developTag', 'VPN setUp fail: %{public}s', JSON.stringify(error) ?? '');
        }
    }
}

protect

protect(socketFd: number): Promise<void>

保护套接字不受VPN连接影响,通过该套接字发送的数据将直接基于物理网络收发,因此其流量不会通过VPN转发。使用Promise方式作为异步方法。

系统能力:SystemCapability.Communication.NetManager.Vpn

参数:

参数名 类型 必填 说明
socketFd number 指定保护的 socketfd,该文件描述符通过getSocketFd获取。

返回值:

类型 说明
Promise<void> Promise对象,无返回结果。

错误码:

以下错误码的详细介绍请参见VPN错误码通用错误码

错误码ID 错误信息
401 Parameter error.
2200001 Invalid parameter value.
2200002 Operation failed. Cannot connect to service.
2200003 System internal error.
2203004 Invalid socket file descriptor.

示例:

import { vpnExtension, VpnExtensionAbility } from '@kit.NetworkKit';
import { common, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';

let g_tunnelFd = -1;
let context: vpnExtension.VpnExtensionContext;
export default class MyVpnExtAbility extends VpnExtensionAbility {
  private vpnServerIp: string = '192.168.31.13';
  onCreate(want: Want) {
    let vpnConnection : vpnExtension.VpnConnection = vpnExtension.createVpnConnection(context);
    console.info("VPN createVpnConnection: " + JSON.stringify(vpnConnection));
    this.CreateTunnel();
    this.Protect();
  }
  CreateTunnel() {
      g_tunnelFd = 8888;
  }
  Protect() {
        hilog.info(0x0000, 'developTag', '%{public}s', 'VPN Protect');
        let vpnConnection : vpnExtension.VpnConnection = vpnExtension.createVpnConnection(context);
        vpnConnection.protect(g_tunnelFd).then(() => {
            hilog.info(0x0000, 'developTag', '%{public}s', 'VPN Protect Success');
        }).catch((err : Error) => {
            hilog.error(0x0000, 'developTag', 'VPN Protect Failed %{public}s', JSON.stringify(err) ?? '');
        })
  }
}

destroy

destroy(): Promise<void>

销毁启动的VPN网络。使用Promise异步回调。

系统能力:SystemCapability.Communication.NetManager.Vpn

返回值:

类型 说明
Promise<void> Promise对象,无返回结果。

错误码:

以下错误码的详细介绍请参见VPN错误码通用错误码

错误码ID 错误信息
401 Parameter error.
2200002 Operation failed. Cannot connect to service.
2200003 System internal error.

示例:

import { vpnExtension, VpnExtensionAbility } from '@kit.NetworkKit';
import { common, Want } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';

let context: vpnExtension.VpnExtensionContext;
export default class MyVpnExtAbility extends VpnExtensionAbility {
  onCreate(want: Want) {
    let vpnConnection : vpnExtension.VpnConnection = vpnExtension.createVpnConnection(context);
    console.info("VPN createVpnConnection: " + JSON.stringify(vpnConnection));
    vpnConnection.destroy().then(() => {
      console.info("destroy success.");
    }).catch((error : BusinessError) => {
      console.error("destroy fail" + JSON.stringify(error));
    });
  }
}

destroy20+

destroy(vpnId: string): Promise<void>

根据vpnId销毁指定的VPN网络。使用Promise异步回调。

系统能力:SystemCapability.Communication.NetManager.Vpn

参数:

参数名 类型 必填 说明
vpnId string vpn唯一标识。

返回值:

类型 说明
Promise<void> Promise对象,无返回结果。

错误码:

以下错误码的详细介绍请参见VPN错误码

错误码ID 错误信息
19900001 Invalid parameter value.
19900002 System internal error.

示例:

import { vpnExtension, VpnExtensionAbility } from '@kit.NetworkKit';
import { BusinessError } from "@kit.BasicServicesKit";

export default class MyVpnExtAbility extends VpnExtensionAbility {
  onCreate() {
    let vpnConnection = vpnExtension.createVpnConnection(this.context);

    // 可通过generateVpnId()获取vpnId
    let vpnId = 'testVpnId';
    vpnConnection.destroy(vpnId).then(() => {
      console.info("destroy success");
    }).catch((error: BusinessError) => {
      console.error(`destroy fail, Code is ${error.code}, message is ${error.message}`);
    });
  }
}

generateVpnId20+

generateVpnId(): Promise<string>

生成VPN唯一标识。使用Promise异步回调。

如需使用系统多VPN能力,需调用该接口生成vpnId,配置到VpnConfig中。

注意

当前系统多VPN能力仅支持IPv4。

系统能力:SystemCapability.Communication.NetManager.Vpn

返回值:

类型 说明
Promise<string> 以Promise形式返回获取结果,返回vpnId。

错误码:

以下错误码的详细介绍请参见VPN错误码

错误码ID 错误信息
19900001 Invalid parameter value.
19900002 System internal error.

示例:

import { vpnExtension, VpnExtensionAbility } from '@kit.NetworkKit';
import { BusinessError } from "@kit.BasicServicesKit";

export default class MyVpnExtAbility extends VpnExtensionAbility {
  onCreate() {
    let vpnConnection = vpnExtension.createVpnConnection(this.context);
    vpnConnection.generateVpnId().then((data) => {
      if (data) {
        console.info("generateVpnId success, vpnId = " + JSON.stringify(data));
      }
    }).catch((error: BusinessError) => {
      console.error(`generateVpnId fail, Code is ${error.code}, message is ${error.message}`);
    });
  }
}

protectProcessNet22+

protectProcessNet(): Promise<void>

保护应用进程不受VPN连接影响,被保护的进程直接基于物理网络收发数据,流量不通过VPN转发。使用Promise异步回调。

系统能力:SystemCapability.Communication.NetManager.Vpn

返回值:

类型 说明
Promise<void> Promise对象,无返回结果。

示例:

import { vpnExtension, VpnExtensionAbility } from '@kit.NetworkKit';
import { hilog } from '@kit.PerformanceAnalysisKit';

let g_tunnelFd = -1;
export default class MyVpnExtAbility  extends VpnExtensionAbility {
  onCreate() {
    let vpnConnection = vpnExtension.createVpnConnection(this.context);
    console.info("VPN createVpnConnection: " + JSON.stringify(vpnConnection));
    this.ProtectNetByProcess();
  }
  CreateTunnel() {
    g_tunnelFd = 8888;
  }
  ProtectNetByProcess() {
    hilog.info(0x0000, 'developTag', '%{public}s', 'vpn ProtectNetByProcess');
    let vpnConnection = vpnExtension.createVpnConnection(this.context);
    vpnConnection.protectProcessNet().then(() => {
      hilog.info(0x0000, 'developTag', '%{public}s', 'vpn ProtectNetByProcess Success');
      this.CreateTunnel();
    }).catch((err: Error) => {
      hilog.error(0x0000, 'developTag', 'vpn ProtectNetByProcess Failed %{public}s', JSON.stringify(err) ?? '');
    })
  }
}

VpnConfig

三方VPN配置参数。

系统能力:SystemCapability.Communication.NetManager.Vpn

名称 类型 只读 可选 说明
addresses Array<LinkAddress> VPN虚拟网卡的IP地址。API version 23之前,最多支持64个IP地址;从API version 23开始,最多支持2000个IP地址。
vpnId20+ string VPN唯一标识。
routes Array<RouteInfo> VPN虚拟网卡的路由信息(API version 23前最多可配置1024条路由;从API version 23开始最多可配置10000条路由)。
dnsAddresses Array<string> DNS服务器地址信息。当配置DNS服务器地址后,VPN启动状态下被代理的应用上网时,使用配置的DNS服务器做DNS查询。
searchDomains Array<string> DNS的搜索域列表。
mtu number 最大传输单元MTU值(单位:字节)。取值范围:[576,1500]。
isIPv4Accepted boolean 是否支持IPv4。true表示支持,false表示不支持, 默认值为true。
注意:若支持IPv4功能,需要在addresses中配置IPv4类型的IP地址。
isIPv6Accepted boolean 是否支持IPv6。true表示支持,false表示不支持, 默认值为false。
注意:若支持IPv6功能,需要在addresses中配置IPv6类型的IP地址。
isInternal boolean 是否支持内置VPN。true表示支持,false表示不支持, 默认值为false。
isBlocking boolean 是否阻塞模式。true表示阻塞模式,false表示非阻塞模式, 默认值为false。
trustedApplications Array<string> 受信任的应用信息列表,string类型表示的包名。当配置该列表后,仅该列表中的应用数据才能根据routes被VPN代理。API version 23前最多可配置64个受信任的应用包名;从API version 23开始最多可配置256个受信任的应用包名。
注意:trustedApplications和blockedApplications列表不能同时配置。
blockedApplications Array<string> 被阻止的应用信息列表,string类型表示的包名。当配置该列表后,该列表中的应用数据不会被VPN代理,其他应用可以根据routes配置被VPN代理。API version 23前最多可配置64个被阻止的应用包名;从API version 23开始最多可配置256个被阻止的应用包名。
注意:trustedApplications和blockedApplications列表不能同时配置。

示例:

import { vpnExtension} from '@kit.NetworkKit';

let vpnConfig: vpnExtension.VpnConfig = {
  addresses: [],
  vpnId: '123',
  routes: [{
    interface: "eth0",
    destination: {
      address: {
        address:'',
        family:1,
        port:8080
      },
      prefixLength:1
    },
    gateway: {
      address:'',
      family:1,
      port:8080
    },
    hasGateway: true,
    isDefaultRoute: true,
  }],
  mtu: 1400,
  dnsAddresses: ["223.5.5.5", "223.6.6.6"],
  trustedApplications: [],
  blockedApplications: [],
}
let context: vpnExtension.VpnExtensionContext;

function vpnCreate(){
  let vpnConnection: vpnExtension.VpnConnection = vpnExtension.createVpnConnection(context);
  vpnConnection.create(vpnConfig).then((data) => {
    console.info("VPN create " + JSON.stringify(data));
  })
}