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. The following guides you through on how to develop your own VPN client. 8 9> **NOTE** 10> 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). 11 12## VPN Extension Ability UI 13 14With 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. 15 16- 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. 17- 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. 18 19To facilitate the query and configuration, your VPN application needs to provide the following UIs: 20 21- UI for manually starting and stopping the VPN connection. 22- 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. 23 24## Available APIs 25 26For details about the complete JavaScript APIs and sample code, see [API Reference](../reference/apis-network-kit/js-apis-net-vpnExtension.md). 27 28## Creating a VPN Extension Ability 29 30To enable your application to support the VPN functionality, you need to create an **ExtensionAbilities** instance inherited from **VpnExtensionAbility**. 31 32```ts 33// Assume that the VNP application is named MyVpnExtAbility. Define it in module.json5. 34"extensionAbilities": [ 35 { 36 "name": "MyVpnExtAbility", 37 "description": "vpnservice", 38 "type": "vpn", 39 "srcEntry": "./ets/serviceextability/MyVpnExtAbility.ts" 40 } 41] 42``` 43 44Next, you need to configure, start, and stop the VPN in the created **VpnExtensionAbility**. 45 46- Establish a VPN tunnel. The following uses the UDP tunnel as an example. 47- Use [VpnConnection.protect](../reference/apis-network-kit/js-apis-net-vpnExtension.md#protect) to enable protection for the UDP tunnel. 48- Construct VPN Config parameters. For details, see [VPN Config Parameters](#description-of-vpn-config-parameters). 49- Use [VpnConnection.create](../reference/apis-network-kit/js-apis-net-vpnExtension.md#create) to establish a VPN connection. 50- Process data of the virtual network interface card (vNIC), such as reading or writing data. 51 52 53## Starting the VPN Extension Ability 54 55To 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: 56 57```ts 58import { common, Want } from '@kit.AbilityKit'; 59import { vpnExtension } from '@kit.NetworkKit'; 60 61let context = getContext(this) as common.VpnExtensionContext; 62let want: Want = { 63 deviceId: "", 64 bundleName: "com.example.myvpndemo", 65 abilityName: "MyVpnExtAbility", 66}; 67 68@Entry 69@Component 70struct Index { 71 @State message: string = 'Hello World'; 72 73 build() { 74 Row() { 75 Column() { 76 Text(this.message) 77 .fontSize(50) 78 .fontWeight(FontWeight.Bold).onClick(() => { 79 console.info("btn click") }) 80 Button('Start Extension').onClick(() => { 81 vpnExtension.startVpnExtensionAbility(want); 82 }).width('70%').fontSize(45).margin(16) 83 }.width('100%') 84 }.height('100%') 85 } 86} 87``` 88 89If 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**. 90 91Currently, 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. 92 93 94 95## Stopping the VPN Extension Ability 96 97To 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**. 98 99The sample code is as follows: 100 101```ts 102import { common, Want } from '@kit.AbilityKit'; 103import { vpnExtension } from '@kit.NetworkKit'; 104 105let context = getContext(this) as common.VpnExtensionContext; 106let want: Want = { 107 deviceId: "", 108 bundleName: "com.example.myvpndemo", 109 abilityName: "MyVpnExtAbility", 110}; 111 112@Entry 113@Component 114struct Index { 115 @State message: string = 'Hello World'; 116 117 build() { 118 Row() { 119 Column() { 120 Text(this.message) 121 .fontSize(50) 122 .fontWeight(FontWeight.Bold).onClick(() => { 123 console.info("btn click") }) 124 Button('Start Extension').onClick(() => { 125 vpnExtension.startVpnExtensionAbility(want); 126 }).width('70%').fontSize(45).margin(16) 127 Button('Stop Extension').onClick(() => { 128 console.info("btn end") 129 vpnExtension.stopVpnExtensionAbility(want); 130 }).width('70%').fontSize(45).margin(16) 131 132 }.width('100%') 133 }.height('100%') 134 } 135} 136``` 137 138After the **VPNExtensionAbility** is stopped, call [onDestroy](../reference/apis-network-kit/js-apis-VpnExtensionAbility.md#vpnextensionabilityondestroy) to destroy the VPN connection and release related resources. 139 140```ts 141import { vpnExtension, VpnExtensionAbility } from '@kit.NetworkKit'; 142import { common, Want } from '@kit.AbilityKit'; 143import { BusinessError } from '@kit.BasicServicesKit'; 144 145let context: vpnExtension.VpnExtensionContext; 146export default class MyVpnExtAbility extends VpnExtensionAbility { 147 onDestroy() { 148 let VpnConnection : vpnExtension.VpnConnection = vpnExtension.createVpnConnection(context); 149 console.info("vpn createVpnConnection: " + JSON.stringify(VpnConnection)); 150 VpnConnection.destroy().then(() => { 151 console.info("destroy success."); 152 }).catch((error : BusinessError) => { 153 console.error("destroy fail" + JSON.stringify(error)); 154 }); 155 } 156} 157``` 158 159## Service Lifecycle Management 160 161To ensure network connectivity, the system automatically stops the VPN connection when detecting that the VPN application is abnormal: 162 163- The application process that calls **startVpnExtensionAbility** exits. 164- The VPN service process is destroyed. 165 166## Description of VPN Config parameters 167 168| Name | Type | Mandatory| Description | 169| ------------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ | 170| addresses | Array\<[LinkAddress](../reference/apis-network-kit/js-apis-net-connection.md#linkaddress)\> | Yes | IP addresses of virtual network interface cards (vNICs). | 171| 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. | 172| 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.| 173| searchDomains | Array\<string\> | No | List of DNS search domains. | 174| mtu | number | No | Maximum transmission unit (MTU), in bytes. | 175| isIPv4Accepted | boolean | No | Whether IPv4 is supported. The default value is **true**. | 176| isIPv6Accepted | boolean | No | Whether IPv6 is supported. The default value is **false**. | 177| isInternal | boolean | No | Whether the built-in VPN is supported. The default value is **false**. | 178| isBlocking | boolean | No | Whether the blocking mode is used. The default value is **false**. | 179| trustedApplications | Array\<string\> | No | Trusted VPN applications, which are represented by bundle names of the string type | 180| blockedApplications | Array\<string\> | No | Blocked VPN applications, which are represented by bundle names of the string type | 181 182**Example** 183 184```ts 185import { vpnExtension} from '@kit.NetworkKit'; 186 187let vpnConfig: vpnExtension.VpnConfig = { 188 // Configure the IP address of the vNIC. 189 addresses: [{ 190 address: { 191 address:'192.x.x.5', 192 family:1 193 }, 194 prefixLength:24 195 }], 196 // Configure route information. 197 routes: [{ 198 // Set the name of the vNIC, which has a fixed value of vpn-tun. 199 interface: 'vpn-tun', 200 destination: { 201 address: { 202 address:'10.x.x.8', 203 family:1, 204 port:8080 205 }, 206 prefixLength:24 207 }, 208 gateway: { 209 address:'10.x.x.5', 210 family:1, 211 port:8080 212 }, 213 hasGateway: false, 214 isDefaultRoute: false, 215 }], 216 // Configure the MTU. 217 mtu: 1400, 218 // Configure IP addresses of DNS serves. 219 dnsAddresses: ['223.x.x.5', '223.x.x.6'], 220 // Configure trusted VPN applications. 221 trustedApplications: ['com.test.browser'], 222 // Configure blocked VPN applications. 223 blockedApplications: ['com.test.games'], 224} 225let context: vpnExtension.VpnExtensionContext; 226 227function vpnCreate(){ 228 let VpnConnection: vpnExtension.VpnConnection = vpnExtension.createVpnConnection(context); 229 VpnConnection.create(vpnConfig).then((data) => { 230 console.info("vpn create " + JSON.stringify(data)); 231 }) 232} 233``` 234 235 236 237## VPN Demo 238 239The OpenHarmony project provides a sample application named [VPN](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Connectivity/VPN), which showcases how to implement the VPN service. 240