• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# VPN应用开发指南
2
3## 简介
4
5VPN,即虚拟专用网络(Virtual Private Network),是在公用网络上建立专用网络的一种技术。在VPN网络中,任意两个节点间的连接并非依赖传统专用网络所需要的端到端的物理链路,而是构建在公用网络服务商提供的平台(如Internet)之上的逻辑网络。用户数据在这一逻辑链路中进行传输。
6
7OpenHarmony为开发者提供了用于创建VPN的API解决方案。本文将指导您如何开发自己的VPN客户端。
8
9> **说明:**
10>
11> 为了保证应用的运行效率,所有API调用都是异步的,对于异步调用的API均提供了Promise的方式,以下示例均采用Promise方式,更多方式可以查阅[API参考](../reference/apis-network-kit/js-apis-net-vpnExtension.md)。
12
13## VPN应用的显示体验
14
15借助系统提供的VPN Extension接口开发者可以构建支持不同协议的VPN服务。OpenHarmony系统提供了界面 (UI) 使用户可以了解当前VPN应用服务的启动和连接:
16
17- 在VPN应用首次启动连接之前,系统会显示VPN连接授权对话框。该对话框会提示用户是否信任该VPN应用并接受VPN连接请求。
18- 当VPN启动连接成功时,状态栏显示一个VPN (钥匙) 图标以提醒用户VPN处于连接状态。
19
20为了使用户可以方便的查看和配置,您的VPN应用还需要提供以下界面:
21
22- 用于手动启动和停止连接的控件。
23- 当VPN启动连接时,在通知栏显示VPN应用的连接状态或提供网络统计信息 (如连接时长、流量等) 。点击该通知能够将您的VPN应用调入前台。
24
25## 接口说明
26
27完整的JS API说明以及示例代码请参考:[VPN扩展应用API](../reference/apis-network-kit/js-apis-net-vpnExtension.md)。
28
29## 创建VPN Extension Ability
30
31如果想使您的应用支持VPN能力,首先您需要创建一个继承于VpnExtensionAbility的extensionAbilities。
32
33```ts
34// 举例:在应用的module.json5中定义MyVpnExtAbility
35"extensionAbilities": [
36  {
37    "name": "MyVpnExtAbility",
38    "description": "vpnservice",
39    "type": "vpn",
40    "srcEntry": "./ets/serviceextability/MyVpnExtAbility.ts"
41  }
42]
43```
44
45> **注意:**
46>
47> 如果DevEco Studio工具提示不能识别"type": "vpn",需要您手动在SDK的toolchains\modulecheck\module.json文件中,给extensionAbilities对应的type枚举添加"vpn"定义,并清除build缓存。
48
49接下来您需要在创建的VpnExtensionAbility中实现VPN的配置、启动和停止操作:
50
51- 建立一个VPN的网络隧道,以TCP隧道为例(参考本文下方VPN Demo示例工程文件[vpn_client](https://gitee.com/openharmony/applications_app_samples/blob/master/code/BasicFeature/Connectivity/VPN/entry/src/main/cpp/vpn_client.cpp)的TcpConnect()方法);
52- 通过VpnConnection.[protect](../reference/apis-network-kit/js-apis-net-vpnExtension.md#protect)保护前一步建立的TCP隧道;
53- 构建VPN Config参数,参考[VPN Config参数说明](#vpn-config参数说明);
54- 通过VpnConnection.[create](../reference/apis-network-kit/js-apis-net-vpnExtension.md#create)建立VPN网络连接;
55- 处理虚拟网卡的数据,如:读写操作。
56
57
58## 启动VPN Extension Ability
59
60当VPN应用启动VPN连接时,需要调用startVpnExtensionAbility接口,携带需要启动的VpnExtensionAbility信息,其中bundleName需要与您的VPN应用bundleName一致,abilityName为您在前面创建的VpnExtensionAbility名。您可参考如下示例:
61
62```ts
63import { common, Want } from '@kit.AbilityKit';
64import { vpnExtension } from '@kit.NetworkKit';
65
66let want: Want = {
67  deviceId: "",
68  bundleName: "com.example.myvpndemo",
69  abilityName: "MyVpnExtAbility",
70};
71
72@Entry
73@Component
74struct Index {
75  @State message: string = 'Hello World';
76
77  build() {
78    Row() {
79      Column() {
80        Text(this.message)
81          .fontSize(50)
82          .fontWeight(FontWeight.Bold).onClick(() => {
83          console.info("btn click") })
84        Button('Start Extension').onClick(() => {
85          vpnExtension.startVpnExtensionAbility(want);
86        }).width('70%').fontSize(45).margin(16)
87        }.width('100%')
88    }.height('100%')
89  }
90}
91```
92
93如果您的VPN应用未获取用户信任,系统将弹出VPN连接的授权对话框,当获取用户授权后,系统将自动调用并启动您实现的VPN Extension Ability的[onCreate](../reference/apis-network-kit/js-apis-VpnExtensionAbility.md#vpnextensionabilityoncreate)方法将被调用。
94
95目前系统仅支持启动一个VPN连接服务,当VPN已经启动时应用新调用启动接口会收到系统拒绝错误,此时建议您的应用可以提醒用户先断开当前已经激活的VPN应用连接。
96
97
98
99## 停止VPN Extension Ability
100
101当VPN应用需要停止VPN连接时,需要调用stopVpnExtensionAbility接口,携带需要停止的VpnExtensionAbility信息。系统会对调用方做权限校验,stopVpnExtensionAbility的调用方应用必须获取了用户的VPN信任授权,且只允许停止应用自己启动的VpnExtensionAbility,所以接口传入的参数中bundleName需要与您的VPN应用bundleName一致,abilityName为指定停止VPN的VpnExtensionAbility名。
102
103您可参考如下示例:
104
105```ts
106import { common, Want } from '@kit.AbilityKit';
107import { vpnExtension } from '@kit.NetworkKit';
108
109let want: Want = {
110  deviceId: "",
111  bundleName: "com.example.myvpndemo",
112  abilityName: "MyVpnExtAbility",
113};
114
115@Entry
116@Component
117struct Index {
118  @State message: string = 'Hello World';
119
120  build() {
121    Row() {
122      Column() {
123        Text(this.message)
124          .fontSize(50)
125          .fontWeight(FontWeight.Bold).onClick(() => {
126          console.info("btn click") })
127        Button('Start Extension').onClick(() => {
128          vpnExtension.startVpnExtensionAbility(want);
129        }).width('70%').fontSize(45).margin(16)
130        Button('Stop Extension').onClick(() => {
131          console.info("btn end")
132          vpnExtension.stopVpnExtensionAbility(want);
133        }).width('70%').fontSize(45).margin(16)
134
135        }.width('100%')
136    }.height('100%')
137  }
138}
139```
140
141stopVpnExtensionAbility后,您的VPN Extension Ability的[onDestroy](../reference/apis-network-kit/js-apis-VpnExtensionAbility.md#vpnextensionabilityondestroy)方法将被调用,您可在此时destroy vpn连接。
142
143```ts
144import { vpnExtension, VpnExtensionAbility } from '@kit.NetworkKit';
145import { common, Want } from '@kit.AbilityKit';
146import { BusinessError } from '@kit.BasicServicesKit';
147
148let context: vpnExtension.VpnExtensionContext;
149export default class MyVpnExtAbility extends VpnExtensionAbility {
150  onDestroy() {
151    let VpnConnection : vpnExtension.VpnConnection = vpnExtension.createVpnConnection(context);
152    console.info("vpn createVpnConnection: " + JSON.stringify(VpnConnection));
153    VpnConnection.destroy().then(() => {
154      console.info("destroy success.");
155    }).catch((error : BusinessError) => {
156      console.error("destroy fail" + JSON.stringify(error));
157    });
158  }
159}
160```
161
162## 服务生命周期
163
164为了保障设备的网络连接,当系统观察到VPN相关应用出现异常时会主动停止VPN连接:
165
166- 当调用startVpnExtensionAbility接口的应用进程退出时。
167- 当VPN服务进程销毁时。
168
169## VPN Config参数说明
170
171| 名称                | 类型                                                         | 必填 | 说明                                                         |
172| ------------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ |
173| addresses           | Array\<[LinkAddress](../reference/apis-network-kit/js-apis-net-connection.md#linkaddress)\> | 是   | VPN虚拟网卡的IP地址。                                        |
174| routes              | Array\<[RouteInfo](../reference/apis-network-kit/js-apis-net-connection.md#routeinfo)\> | 否   | VPN虚拟网卡的路由信息(目前最多可配置1024条路由)。            |
175| dnsAddresses        | Array\<string\>                                              | 否   | DNS服务器地址信息。配置后VPN白名单的应用访问网络时使用这些DNS服务器,不配置则使用系统分配的DNS服务器地址。 |
176| searchDomains       | Array\<string\>                                              | 否   | DNS的搜索域列表。                                            |
177| mtu                 | number                                                       | 否   | 最大传输单元MTU值(单位:字节)。                               |
178| isIPv4Accepted      | boolean                                                      | 否   | 是否支持IPV4,默认值为true。                                 |
179| isIPv6Accepted      | boolean                                                      | 否   | 是否支持IPV6,默认值为false。                                |
180| isInternal          | boolean                                                      | 否   | 是否支持内置VPN,默认值为false。                             |
181| isBlocking          | boolean                                                      | 否   | 是否阻塞模式,默认值为false。                                |
182| trustedApplications | Array\<string\>                                              | 否   | VPN生效的应用白名单信息,string类型表示的包名。              |
183| blockedApplications | Array\<string\>                                              | 否   | 不生效VPN的应用黑名单信息,string类型表示的包名。            |
184
185**示例:**
186
187```ts
188import { vpnExtension} from '@kit.NetworkKit';
189
190let vpnConfig: vpnExtension.VpnConfig = {
191  // 配置VPN虚拟网卡的IP地址
192  addresses: [{
193    address: {
194      address:'192.x.x.5',
195      family:1
196    },
197    prefixLength:24
198  }],
199  // 配置路由参数
200  routes: [{
201    // VPN虚拟网卡接口名固定为“vpn-tun”
202    interface: 'vpn-tun',
203    destination: {
204      address: {
205        address:'10.x.x.8',
206        family:1,
207        port:8080
208      },
209      prefixLength:24
210    },
211    gateway: {
212      address:'10.x.x.5',
213      family:1,
214      port:8080
215    },
216    hasGateway: false,
217    isDefaultRoute: false,
218  }],
219  // 配置最大传输单元值
220  mtu: 1400,
221  // 配置VPN使用的DNS服务器,
222  dnsAddresses: ['223.x.x.5', '223.x.x.6'],
223  // VPN生效白名单的应用
224  trustedApplications: ['com.test.browser'],
225  // 不生效VPN黑名单的应用
226  blockedApplications: ['com.test.games'],
227}
228let context: vpnExtension.VpnExtensionContext;
229
230function vpnCreate(){
231  let VpnConnection: vpnExtension.VpnConnection = vpnExtension.createVpnConnection(context);
232  VpnConnection.create(vpnConfig).then((data) => {
233    console.info("vpn create " + JSON.stringify(data));
234  })
235}
236```
237
238
239
240## VPN Demo示例
241
242OpenHarmony开源项目包含一个名为[VPN](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Connectivity/VPN)的示例应用。此应用展示了如何设置和连接 VPN 服务。
243
244
245
246