• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# VPN Extension Ability Development
2
3## Introduction
4
5A virtual private network (VPN) is a dedicated network established on a public network. Unlike a traditional private network, a VPN does not require an end-to-end physical link between any two nodes. It is built over a network platform (for example, Internet) provided by a public network service provider. User data is transmitted over the logical link.
6
7OpenHarmony provides the VPN Extension solution for enhanced VPN management. Currently, the VPN capabilities provided to third-party applications are primarily used for creating virtual NICs and configuring VPN routing information. The connection tunnel process and internal connection protocols need to be implemented by the applications themselves. The following guides you through on how to develop your own VPN client.
8
9> **NOTE**
10>
11> To maximize the application running efficiency, all APIs are called asynchronously in callback or promise mode. The following code examples use the promise mode. For details about the APIs, see [API Reference](../reference/apis-network-kit/js-apis-net-vpnExtension.md).
12
13For details about the complete JavaScript APIs and sample code, see [API Reference](../reference/apis-network-kit/js-apis-net-vpnExtension.md).
14
15## VPN Extension Ability UI
16
17With the VPN Extension APIs provided by OpenHarmony, you can build VPN services that support different protocols. OpenHarmony provides a UI for users to learn about VPN startup and connection.
18
19- When the VPN application sets up a connection for the first time, the VPN connection authorization dialog box is displayed. The dialog box prompts users whether to trust the VPN application and accept the VPN connection request.
20- If the VPN connection is successful, a VPN icon (a key) is displayed in the status bar to remind the user that the VPN is connected.
21
22To facilitate the query and configuration, your VPN application needs to provide the following UIs:
23
24- UI for manually starting and stopping the VPN connection.
25- UI for displaying the connection status of the VPN application in the notification bar or providing network statistics (such as the connection duration and traffic) of the VPN connection. Touching the notification in notification bar should bring your VPN application to the foreground.
26
27
28## How to Develop
29
30### Creating a VPN Extension Ability
31
32To enable your application to support the VPN functionality, you need to create an **ExtensionAbilities** instance inherited from **VpnExtensionAbility**.
33
34```ts
35// Assume that the VNP application is named MyVpnExtAbility. Define it in module.json5.
36"extensionAbilities": [
37  {
38    "name": "MyVpnExtAbility",
39    "description": "vpnservice",
40    "type": "vpn",
41    "srcEntry": "./ets/serviceextability/MyVpnExtAbility.ts"
42  }
43]
44```
45
46> **NOTE**
47>
48> If the DevEco Studio tool displays a message indicating unrecognizable **"type": "vpn"**, you need to manually add **vpn** to the **type** enums corresponding to **extensionAbilities** in the **toolchains\modulecheck\module.json** file of the SDK and clear the build cache.
49
50Next, you need to configure, start, and stop the VPN in the created **VpnExtensionAbility**.
51
52- Establish a VPN tunnel. The following uses the UDP tunnel as an example. For details, see the **UdpConnect()** API in the [napi_init](https://gitee.com/openharmony/applications_app_samples/blob/master/code/DocsSample/NetWork_Kit/NetWorkKit_NetManager/VPNControl_Case/entry/src/main/cpp/napi_init.cpp) demo project.
53- Use [VpnConnection.protect](../reference/apis-network-kit/js-apis-net-vpnExtension.md#protect) to enable protection for the UDP tunnel.
54- Construct VPN Config parameters. For details, see [VPN Config Parameters](#description-of-vpn-config-parameters).
55- Use [VpnConnection.create](../reference/apis-network-kit/js-apis-net-vpnExtension.md#create) to establish a VPN connection.
56- Process data of the virtual network interface card (vNIC), such as reading or writing data.
57
58### Starting the VPN Extension Ability
59
60To start a connection from the VPN application, you need to call **startVpnExtensionAbility** with the **VpnExtensionAbility** information specified. Make sure that **bundleName** is the same as that of the VPN application, and **abilityName** is the name of the **VpnExtensionAbility** you created. The sample code is as follows:
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
93If your VPN app is not trusted by the user, the system displays a dialog box asking the user to authorize the VPN connection. After obtaining the authorization, the system automatically calls [onCreate](../reference/apis-network-kit/js-apis-VpnExtensionAbility.md#vpnextensionabilityoncreate) of the **VpnExtensionAbility**.
94
95Currently, only one active VPN connection is supported. If the application calls **startVpnExtensionAbility** when a VPN connection is active, it will receive a system rejection error. In this case, you are advised to remind the user to disconnect the active VPN connection first.
96
97
98
99### Stopping the VPN Extension Ability
100
101To stop a VPN connection, the VPN application needs to call **stopVpnExtensionAbility** with the target **VpnExtensionAbility** specified. The system verifies the permission of the caller. The caller of **stopVpnExtensionAbility** must have obtained the VPN connection authorization of the user and can only stop the **VpnExtensionAbility** it started. Therefore, make sure that the value of **bundleName** passed by the API is the same as that of the VPN application, and the value of **abilityName** is the same as that of the target **VpnExtensionAbility**.
102
103The sample code is as follows:
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
141After the **VPNExtensionAbility** is stopped, call [onDestroy](../reference/apis-network-kit/js-apis-VpnExtensionAbility.md#vpnextensionabilityondestroy) to destroy the VPN connection and release related resources.
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## Service Lifecycle Management
163
164To ensure network connectivity, the system automatically stops the VPN connection when detecting that the VPN application is abnormal:
165
166- The application process that calls **startVpnExtensionAbility** exits.
167- The VPN service process is destroyed.
168
169## Description of VPN Config parameters
170
171| Name               | Type                                                        | Mandatory| Description                                                        |
172| ------------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ |
173| addresses           | Array\<[LinkAddress](../reference/apis-network-kit/js-apis-net-connection.md#linkaddress)\> | Yes  | IP addresses of virtual network interface cards (vNICs).                                       |
174| routes              | Array\<[RouteInfo](../reference/apis-network-kit/js-apis-net-connection.md#routeinfo)\> | No  | Routes of vNICs. Currently, a maximum of 1024 routes can be configured.           |
175| dnsAddresses        | Array\<string\>                                              | No  | IP addresses of DNS servers. Trusted VPN applications can access the network through these IP addresses. If this parameter is not configured, IP address allocated by the system will be used.|
176| searchDomains       | Array\<string\>                                              | No  | List of DNS search domains.                                           |
177| mtu                 | number                                                       | No  | Maximum transmission unit (MTU), in bytes.                              |
178| isIPv4Accepted      | boolean                                                      | No  | Whether IPv4 is supported. The default value is **true**. The value **true** indicates that IPV4 is supported, and the value **false** indicates the opposite.                                |
179| isIPv6Accepted      | boolean                                                      | No  | Whether IPv6 is supported. The default value is **false**. The value **true** indicates that IPV6 is supported, and the value **false** indicates the opposite.                               |
180| isInternal          | boolean                                                      | No  | Whether the built-in VPN is supported. The default value is **false**. The value **true** indicates that the built-in VPN is supported, and the value **false** indicates the opposite.                            |
181| isBlocking          | boolean                                                      | No  | Whether the blocking mode is used. The default value is **false**. The value **true** indicates that the blocking mode is used, and the value **false** indicates the opposite.                               |
182| trustedApplications | Array\<string\>                                              | No  | Trusted VPN applications, which are represented by bundle names of the string type             |
183| blockedApplications | Array\<string\>                                              | No  | Blocked VPN applications, which are represented by bundle names of the string type           |
184
185**Example**
186
187```ts
188import { vpnExtension} from '@kit.NetworkKit';
189
190let vpnConfig: vpnExtension.VpnConfig = {
191  // Configure the IP address of the vNIC.
192  addresses: [{
193    address: {
194      address:'192.x.x.5',
195      family:1
196    },
197    prefixLength:24
198  }],
199  // Configure route information.
200  routes: [{
201    // Set the name of the vNIC, which has a fixed value of 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  // Configure the MTU.
220  mtu: 1400,
221  // Configure IP addresses of DNS serves.
222  dnsAddresses: ['223.x.x.5', '223.x.x.6'],
223  // Configure trusted VPN applications.
224  trustedApplications: ['com.test.browser'],
225  // Configure blocked VPN applications.
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
242The OpenHarmony project provides a sample application named [VPN](https://gitee.com/openharmony/applications_app_samples/tree/master/code/DocsSample/NetWork_Kit/NetWorkKit_NetManager/VPNControl_Case), which showcases how to implement the VPN service.
243