-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
Copy pathvpn_service.ts
134 lines (113 loc) · 4.61 KB
/
vpn_service.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright 2024 The Outline Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import {invokeGoMethod, registerCallback} from './go_plugin';
import {
StartRequestJson,
TunnelStatus,
} from '../src/www/app/outline_server_repository/vpn';
// TODO: Separate this config into LinuxVpnConfig and WindowsVpnConfig. Some fields may share.
interface VpnConfig {
id: string;
interfaceName: string;
connectionName: string;
ipAddress: string;
dnsServers: string[];
routingTableId: number;
routingPriority: number;
protectionMark: number;
}
interface EstablishVpnRequest {
vpn: VpnConfig;
transport: string;
}
export async function establishVpn(request: StartRequestJson) {
const config: EstablishVpnRequest = {
// The following VPN configuration ensures that the new routing can co-exist with any legacy Outline routings (e.g. AppImage).
vpn: {
id: request.id,
// TUN device name, use 'outline-tun1' to avoid conflict with old 'outline-tun0':
// https://github.com/Jigsaw-Code/outline-apps/blob/client/linux/v1.14.0/client/electron/linux_proxy_controller/outline_proxy_controller.h#L203
interfaceName: 'outline-tun1',
// Network Manager connection name, Use "TUN Connection" instead of "VPN Connection"
// because Network Manager has a dedicated "VPN Connection" concept that we did not implement
connectionName: 'Outline TUN Connection',
// TUN IP, use '10.0.85.5' to avoid conflict with old '10.0.85.1':
// https://github.com/Jigsaw-Code/outline-apps/blob/client/linux/v1.14.0/client/electron/linux_proxy_controller/outline_proxy_controller.h#L204
ipAddress: '10.0.85.5',
// DNS server list, being compatible with old code:
// https://github.com/Jigsaw-Code/outline-apps/blob/client/linux/v1.14.0/client/electron/linux_proxy_controller/outline_proxy_controller.h#L207
dnsServers: ['9.9.9.9'],
// Outline magic numbers, 7113 and 0x711E visually resembles "T L I E" in "ouTLInE"
routingTableId: 7113,
routingPriority: 0x711e,
protectionMark: 0x711e,
},
// The actual transport config
transport: request.config.transport,
};
await invokeGoMethod('EstablishVPN', JSON.stringify(config));
}
export async function closeVpn(): Promise<void> {
await invokeGoMethod('CloseVPN', '');
}
export type VpnStateChangeCallback = (status: TunnelStatus, id: string) => void;
/**
* Registers a callback function to be invoked when the VPN state changes.
*
* @param cb - The callback function to be invoked when the VPN state changes.
* The callback will receive the VPN connection ID as well as the new status.
*
* @remarks The caller should subscribe to this event **only once**.
* Use the `id` parameter in the callback to identify the firing VPN connection.
*/
export async function onVpnStateChanged(
cb: VpnStateChangeCallback
): Promise<void> {
if (!cb) {
return;
}
const cbToken = await registerCallback(data => {
const conn = JSON.parse(data) as VPNConnectionState;
console.debug('VPN connection state changed', conn);
switch (conn?.status) {
case VPNConnConnected:
cb(TunnelStatus.CONNECTED, conn.id);
break;
case VPNConnConnecting:
cb(TunnelStatus.RECONNECTING, conn.id);
break;
case VPNConnDisconnecting:
cb(TunnelStatus.DISCONNECTING, conn.id);
break;
case VPNConnDisconnected:
cb(TunnelStatus.DISCONNECTED, conn.id);
break;
}
return '';
});
await invokeGoMethod('SetVPNStateChangeListener', cbToken.toString());
}
//#region type definitions of VPNConnection in Go
// The following constants and types should be aligned with the corresponding definitions
// in `./client/go/outline/vpn/vpn.go`.
type VPNConnStatus = string;
const VPNConnConnecting: VPNConnStatus = 'Connecting';
const VPNConnConnected: VPNConnStatus = 'Connected';
const VPNConnDisconnecting: VPNConnStatus = 'Disconnecting';
const VPNConnDisconnected: VPNConnStatus = 'Disconnected';
interface VPNConnectionState {
readonly id: string;
readonly status: VPNConnStatus;
}
//#endregion type definitions of VPNConnection in Go