react-native-wireguard-vpn-patched 1.0.22-patch.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +238 -0
- package/android/build.gradle +60 -0
- package/android/src/main/java/com/wireguardvpn/WireGuardVpnModule.kt +353 -0
- package/android/src/main/java/com/wireguardvpn/WireGuardVpnPackage.kt +16 -0
- package/app.plugin.js +4 -0
- package/ios/WireGuardVpn.h +5 -0
- package/ios/WireGuardVpn.m +294 -0
- package/lib/index.d.ts +53 -0
- package/lib/index.js +46 -0
- package/lib/index.js.map +1 -0
- package/package.json +56 -0
- package/plugin/withWireGuardVpn.js +105 -0
- package/react-native-wireguard-vpn-patched.podspec +21 -0
- package/src/index.d.ts +41 -0
- package/src/index.ts +99 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
#import "WireGuardVpn.h"
|
|
2
|
+
#import <NetworkExtension/NetworkExtension.h>
|
|
3
|
+
|
|
4
|
+
@implementation WireGuardVpn {
|
|
5
|
+
id _neStatusObserver;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
RCT_EXPORT_MODULE(WireGuardVpnModule)
|
|
9
|
+
|
|
10
|
+
- (NSArray<NSString *> *)supportedEvents
|
|
11
|
+
{
|
|
12
|
+
return @[@"vpnStateChanged"];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// RN will call these when JS starts/stops listening to events.
|
|
16
|
+
- (void)startObserving
|
|
17
|
+
{
|
|
18
|
+
if (_neStatusObserver != nil) return;
|
|
19
|
+
|
|
20
|
+
__weak typeof(self) weakSelf = self;
|
|
21
|
+
_neStatusObserver = [[NSNotificationCenter defaultCenter]
|
|
22
|
+
addObserverForName:NEVPNStatusDidChangeNotification
|
|
23
|
+
object:nil
|
|
24
|
+
queue:[NSOperationQueue mainQueue]
|
|
25
|
+
usingBlock:^(NSNotification * _Nonnull note) {
|
|
26
|
+
[weakSelf emitVpnStateChanged];
|
|
27
|
+
}];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
- (void)stopObserving
|
|
31
|
+
{
|
|
32
|
+
if (_neStatusObserver == nil) return;
|
|
33
|
+
[[NSNotificationCenter defaultCenter] removeObserver:_neStatusObserver];
|
|
34
|
+
_neStatusObserver = nil;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
- (void)emitVpnStateChanged
|
|
38
|
+
{
|
|
39
|
+
if (![self hasListeners]) return;
|
|
40
|
+
|
|
41
|
+
NSString *providerBundleIdentifier = @"com.wireguardvpn.tunnel";
|
|
42
|
+
[NETunnelProviderManager loadAllFromPreferencesWithCompletionHandler:^(NSArray<NETunnelProviderManager *> * _Nullable managers, NSError * _Nullable error) {
|
|
43
|
+
if (error || managers == nil) return;
|
|
44
|
+
|
|
45
|
+
NETunnelProviderManager *manager = nil;
|
|
46
|
+
for (NETunnelProviderManager *m in managers) {
|
|
47
|
+
if (![m.protocolConfiguration isKindOfClass:[NETunnelProviderProtocol class]]) continue;
|
|
48
|
+
NETunnelProviderProtocol *p = (NETunnelProviderProtocol *)m.protocolConfiguration;
|
|
49
|
+
if ([p.providerBundleIdentifier isEqualToString:providerBundleIdentifier]) {
|
|
50
|
+
manager = m;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!manager) return;
|
|
56
|
+
|
|
57
|
+
NEVPNStatus status = manager.connection.status;
|
|
58
|
+
NSString *tunnelState = [self stringFromVPNStatus:status];
|
|
59
|
+
|
|
60
|
+
NSString *simpleStatus = nil;
|
|
61
|
+
if (status == NEVPNStatusConnected) simpleStatus = @"CONNECTED";
|
|
62
|
+
else if (status == NEVPNStatusDisconnected) simpleStatus = @"DISCONNECTED";
|
|
63
|
+
else if (status == NEVPNStatusConnecting) simpleStatus = @"CONNECTING";
|
|
64
|
+
else if (status == NEVPNStatusDisconnecting) simpleStatus = @"DISCONNECTING";
|
|
65
|
+
else if (status == NEVPNStatusInvalid) simpleStatus = @"ERROR";
|
|
66
|
+
else simpleStatus = @"UNKNOWN";
|
|
67
|
+
|
|
68
|
+
NSDictionary *body = @{
|
|
69
|
+
@"isConnected": @((status == NEVPNStatusConnected) ? YES : NO),
|
|
70
|
+
@"tunnelState": tunnelState ?: @"UNKNOWN",
|
|
71
|
+
@"status": simpleStatus ?: @"UNKNOWN"
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
[self sendEventWithName:@"vpnStateChanged" body:body];
|
|
75
|
+
}];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
RCT_EXPORT_METHOD(initialize:(RCTPromiseResolveBlock)resolve
|
|
79
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
80
|
+
{
|
|
81
|
+
[NETunnelProviderManager loadAllFromPreferencesWithCompletionHandler:^(NSArray<NETunnelProviderManager *> * _Nullable managers, NSError * _Nullable error) {
|
|
82
|
+
if (error) {
|
|
83
|
+
reject(@"INIT_ERROR", error.localizedDescription, error);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
NETunnelProviderManager *manager = managers.firstObject ?: [[NETunnelProviderManager alloc] init];
|
|
88
|
+
manager.localizedDescription = @"WireGuard VPN";
|
|
89
|
+
manager.protocolConfiguration = [[NETunnelProviderProtocol alloc] init];
|
|
90
|
+
|
|
91
|
+
[manager saveToPreferencesWithCompletionHandler:^(NSError * _Nullable error) {
|
|
92
|
+
if (error) {
|
|
93
|
+
reject(@"INIT_ERROR", error.localizedDescription, error);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
resolve(nil);
|
|
97
|
+
}];
|
|
98
|
+
}];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
RCT_EXPORT_METHOD(connect:(NSDictionary *)config
|
|
102
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
103
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
104
|
+
{
|
|
105
|
+
// Validate required config early for clearer errors.
|
|
106
|
+
NSString *serverAddress = config[@"serverAddress"];
|
|
107
|
+
id serverPort = config[@"serverPort"];
|
|
108
|
+
NSString *privateKey = config[@"privateKey"];
|
|
109
|
+
NSString *publicKey = config[@"publicKey"];
|
|
110
|
+
id allowedIPs = config[@"allowedIPs"];
|
|
111
|
+
|
|
112
|
+
BOOL hasRequired =
|
|
113
|
+
(serverAddress && ![serverAddress isKindOfClass:[NSNull class]]) &&
|
|
114
|
+
(privateKey && ![privateKey isKindOfClass:[NSNull class]]) &&
|
|
115
|
+
(publicKey && ![publicKey isKindOfClass:[NSNull class]]) &&
|
|
116
|
+
serverPort &&
|
|
117
|
+
(allowedIPs && [allowedIPs isKindOfClass:[NSArray class]] && [(NSArray *)allowedIPs count] > 0);
|
|
118
|
+
|
|
119
|
+
if (!hasRequired) {
|
|
120
|
+
reject(@"CONNECT_ERROR",
|
|
121
|
+
@"Missing required config: serverAddress, serverPort, privateKey, publicKey, allowedIPs (non-empty array)",
|
|
122
|
+
nil);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
[NETunnelProviderManager loadAllFromPreferencesWithCompletionHandler:^(NSArray<NETunnelProviderManager *> * _Nullable managers, NSError * _Nullable error) {
|
|
127
|
+
if (error) {
|
|
128
|
+
reject(@"CONNECT_ERROR", error.localizedDescription, error);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
NSString *providerBundleIdentifier = @"com.wireguardvpn.tunnel";
|
|
133
|
+
|
|
134
|
+
// Pick the correct NETunnelProviderManager (do not assume firstObject).
|
|
135
|
+
NETunnelProviderManager *manager = nil;
|
|
136
|
+
for (NETunnelProviderManager *m in managers) {
|
|
137
|
+
if (![m.protocolConfiguration isKindOfClass:[NETunnelProviderProtocol class]]) {
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
NETunnelProviderProtocol *p = (NETunnelProviderProtocol *)m.protocolConfiguration;
|
|
141
|
+
if ([p.providerBundleIdentifier isEqualToString:providerBundleIdentifier]) {
|
|
142
|
+
manager = m;
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (!manager) {
|
|
147
|
+
manager = [[NETunnelProviderManager alloc] init];
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
manager.enabled = YES;
|
|
151
|
+
|
|
152
|
+
NETunnelProviderProtocol *protocol = nil;
|
|
153
|
+
if ([manager.protocolConfiguration isKindOfClass:[NETunnelProviderProtocol class]]) {
|
|
154
|
+
protocol = (NETunnelProviderProtocol *)manager.protocolConfiguration;
|
|
155
|
+
} else {
|
|
156
|
+
protocol = [[NETunnelProviderProtocol alloc] init];
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
protocol.serverAddress = config[@"serverAddress"];
|
|
160
|
+
protocol.providerBundleIdentifier = providerBundleIdentifier;
|
|
161
|
+
|
|
162
|
+
NSMutableDictionary *tunnelConfig = [NSMutableDictionary dictionary];
|
|
163
|
+
tunnelConfig[@"privateKey"] = config[@"privateKey"];
|
|
164
|
+
tunnelConfig[@"publicKey"] = config[@"publicKey"];
|
|
165
|
+
tunnelConfig[@"serverPort"] = config[@"serverPort"];
|
|
166
|
+
tunnelConfig[@"allowedIPs"] = config[@"allowedIPs"];
|
|
167
|
+
tunnelConfig[@"dns"] = config[@"dns"];
|
|
168
|
+
tunnelConfig[@"mtu"] = config[@"mtu"];
|
|
169
|
+
|
|
170
|
+
protocol.providerConfiguration = tunnelConfig;
|
|
171
|
+
|
|
172
|
+
manager.protocolConfiguration = protocol;
|
|
173
|
+
|
|
174
|
+
[manager saveToPreferencesWithCompletionHandler:^(NSError * _Nullable error) {
|
|
175
|
+
if (error) {
|
|
176
|
+
reject(@"CONNECT_ERROR", error.localizedDescription, error);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
NSError *startError;
|
|
181
|
+
[manager.connection startVPNTunnelAndReturnError:&startError];
|
|
182
|
+
|
|
183
|
+
if (startError) {
|
|
184
|
+
reject(@"CONNECT_ERROR", startError.localizedDescription, startError);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
resolve(nil);
|
|
189
|
+
}];
|
|
190
|
+
}];
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
RCT_EXPORT_METHOD(disconnect:(RCTPromiseResolveBlock)resolve
|
|
194
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
195
|
+
{
|
|
196
|
+
[NETunnelProviderManager loadAllFromPreferencesWithCompletionHandler:^(NSArray<NETunnelProviderManager *> * _Nullable managers, NSError * _Nullable error) {
|
|
197
|
+
if (error) {
|
|
198
|
+
reject(@"DISCONNECT_ERROR", error.localizedDescription, error);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
NSString *providerBundleIdentifier = @"com.wireguardvpn.tunnel";
|
|
203
|
+
NETunnelProviderManager *manager = nil;
|
|
204
|
+
for (NETunnelProviderManager *m in managers) {
|
|
205
|
+
if (![m.protocolConfiguration isKindOfClass:[NETunnelProviderProtocol class]]) continue;
|
|
206
|
+
NETunnelProviderProtocol *p = (NETunnelProviderProtocol *)m.protocolConfiguration;
|
|
207
|
+
if ([p.providerBundleIdentifier isEqualToString:providerBundleIdentifier]) {
|
|
208
|
+
manager = m;
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (!manager) {
|
|
214
|
+
resolve(nil);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
[manager.connection stopVPNTunnel];
|
|
219
|
+
resolve(nil);
|
|
220
|
+
}];
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
RCT_EXPORT_METHOD(getStatus:(RCTPromiseResolveBlock)resolve
|
|
224
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
225
|
+
{
|
|
226
|
+
[NETunnelProviderManager loadAllFromPreferencesWithCompletionHandler:^(NSArray<NETunnelProviderManager *> * _Nullable managers, NSError * _Nullable error) {
|
|
227
|
+
if (error) {
|
|
228
|
+
reject(@"STATUS_ERROR", error.localizedDescription, error);
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
NSString *providerBundleIdentifier = @"com.wireguardvpn.tunnel";
|
|
233
|
+
NETunnelProviderManager *manager = nil;
|
|
234
|
+
for (NETunnelProviderManager *m in managers) {
|
|
235
|
+
if (![m.protocolConfiguration isKindOfClass:[NETunnelProviderProtocol class]]) continue;
|
|
236
|
+
NETunnelProviderProtocol *p = (NETunnelProviderProtocol *)m.protocolConfiguration;
|
|
237
|
+
if ([p.providerBundleIdentifier isEqualToString:providerBundleIdentifier]) {
|
|
238
|
+
manager = m;
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (!manager) {
|
|
244
|
+
resolve(@{
|
|
245
|
+
@"isConnected": @NO,
|
|
246
|
+
@"tunnelState": @"INACTIVE",
|
|
247
|
+
@"status": @"DISCONNECTED",
|
|
248
|
+
});
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
NEVPNStatus status = manager.connection.status;
|
|
253
|
+
NSString *tunnelState = [self stringFromVPNStatus:status];
|
|
254
|
+
NSString *simpleStatus = nil;
|
|
255
|
+
if (status == NEVPNStatusConnected) simpleStatus = @"CONNECTED";
|
|
256
|
+
else if (status == NEVPNStatusDisconnected) simpleStatus = @"DISCONNECTED";
|
|
257
|
+
else if (status == NEVPNStatusConnecting) simpleStatus = @"CONNECTING";
|
|
258
|
+
else if (status == NEVPNStatusDisconnecting) simpleStatus = @"DISCONNECTING";
|
|
259
|
+
else if (status == NEVPNStatusInvalid) simpleStatus = @"ERROR";
|
|
260
|
+
else simpleStatus = @"UNKNOWN";
|
|
261
|
+
|
|
262
|
+
resolve(@{
|
|
263
|
+
@"isConnected": @(status == NEVPNStatusConnected),
|
|
264
|
+
@"tunnelState": tunnelState,
|
|
265
|
+
@"status": simpleStatus
|
|
266
|
+
});
|
|
267
|
+
}];
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
RCT_EXPORT_METHOD(isSupported:(RCTPromiseResolveBlock)resolve
|
|
271
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
272
|
+
{
|
|
273
|
+
resolve(@YES);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
- (NSString *)stringFromVPNStatus:(NEVPNStatus)status
|
|
277
|
+
{
|
|
278
|
+
switch (status) {
|
|
279
|
+
case NEVPNStatusConnected:
|
|
280
|
+
return @"ACTIVE";
|
|
281
|
+
case NEVPNStatusConnecting:
|
|
282
|
+
return @"CONNECTING";
|
|
283
|
+
case NEVPNStatusDisconnecting:
|
|
284
|
+
return @"DISCONNECTING";
|
|
285
|
+
case NEVPNStatusDisconnected:
|
|
286
|
+
return @"INACTIVE";
|
|
287
|
+
case NEVPNStatusInvalid:
|
|
288
|
+
return @"ERROR";
|
|
289
|
+
default:
|
|
290
|
+
return @"UNKNOWN";
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
@end
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export interface WireGuardConfig {
|
|
2
|
+
privateKey: string;
|
|
3
|
+
publicKey: string;
|
|
4
|
+
serverAddress: string;
|
|
5
|
+
serverPort: number;
|
|
6
|
+
/** Interface address(es), e.g. "10.64.0.1/32". If omitted, defaults to 10.64.0.1/32. Do not use 0.0.0.0/0 or ::/0 here (use allowedIPs for routing). */
|
|
7
|
+
address?: string | string[];
|
|
8
|
+
allowedIPs: string[];
|
|
9
|
+
dns?: string[];
|
|
10
|
+
mtu?: number;
|
|
11
|
+
presharedKey?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Split tunneling — Android only.
|
|
14
|
+
* Package names of apps whose traffic should bypass the VPN tunnel.
|
|
15
|
+
* Example: ["com.google.android.apps.maps", "com.example.bankingapp"]
|
|
16
|
+
*/
|
|
17
|
+
excludedApps?: string[];
|
|
18
|
+
}
|
|
19
|
+
export interface WireGuardStatus {
|
|
20
|
+
isConnected: boolean;
|
|
21
|
+
tunnelState: 'ACTIVE' | 'INACTIVE' | 'CONNECTING' | 'DISCONNECTING' | 'ERROR' | 'UNKNOWN';
|
|
22
|
+
/**
|
|
23
|
+
* Connection status as a simpler string for app UI logic.
|
|
24
|
+
* - CONNECTED when tunnel is up
|
|
25
|
+
* - DISCONNECTED when tunnel is down
|
|
26
|
+
* - CONNECTING/DISCONNECTING/ERROR/UNKNOWN for intermediate states
|
|
27
|
+
*/
|
|
28
|
+
status: 'CONNECTED' | 'DISCONNECTED' | 'CONNECTING' | 'DISCONNECTING' | 'ERROR' | 'UNKNOWN';
|
|
29
|
+
error?: string;
|
|
30
|
+
}
|
|
31
|
+
declare const _default: {
|
|
32
|
+
/**
|
|
33
|
+
* Initialize the VPN service
|
|
34
|
+
*/
|
|
35
|
+
initialize(): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Connect to VPN using provided configuration
|
|
38
|
+
*/
|
|
39
|
+
connect(config: WireGuardConfig): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Disconnect from VPN
|
|
42
|
+
*/
|
|
43
|
+
disconnect(): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Get current VPN status
|
|
46
|
+
*/
|
|
47
|
+
getStatus(): Promise<WireGuardStatus>;
|
|
48
|
+
/**
|
|
49
|
+
* Check if VPN is supported on the device
|
|
50
|
+
*/
|
|
51
|
+
isSupported(): Promise<boolean>;
|
|
52
|
+
};
|
|
53
|
+
export default _default;
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const react_native_1 = require("react-native");
|
|
4
|
+
const LINKING_ERROR = `The package 'react-native-wireguard-vpn-patched' doesn't seem to be linked. Make sure: \n\n` +
|
|
5
|
+
react_native_1.Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
|
|
6
|
+
'- You rebuilt the app after installing the package\n' +
|
|
7
|
+
'- You are not using Expo Go\n';
|
|
8
|
+
const WireGuardVpnModule = react_native_1.NativeModules.WireGuardVpnModule
|
|
9
|
+
? react_native_1.NativeModules.WireGuardVpnModule
|
|
10
|
+
: new Proxy({}, {
|
|
11
|
+
get() {
|
|
12
|
+
throw new Error(LINKING_ERROR);
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
exports.default = {
|
|
16
|
+
/**
|
|
17
|
+
* Initialize the VPN service
|
|
18
|
+
*/
|
|
19
|
+
initialize() {
|
|
20
|
+
return WireGuardVpnModule.initialize();
|
|
21
|
+
},
|
|
22
|
+
/**
|
|
23
|
+
* Connect to VPN using provided configuration
|
|
24
|
+
*/
|
|
25
|
+
connect(config) {
|
|
26
|
+
return WireGuardVpnModule.connect(config);
|
|
27
|
+
},
|
|
28
|
+
/**
|
|
29
|
+
* Disconnect from VPN
|
|
30
|
+
*/
|
|
31
|
+
disconnect() {
|
|
32
|
+
return WireGuardVpnModule.disconnect();
|
|
33
|
+
},
|
|
34
|
+
/**
|
|
35
|
+
* Get current VPN status
|
|
36
|
+
*/
|
|
37
|
+
getStatus() {
|
|
38
|
+
return WireGuardVpnModule.getStatus();
|
|
39
|
+
},
|
|
40
|
+
/**
|
|
41
|
+
* Check if VPN is supported on the device
|
|
42
|
+
*/
|
|
43
|
+
isSupported() {
|
|
44
|
+
return WireGuardVpnModule.isSupported();
|
|
45
|
+
},
|
|
46
|
+
};
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAAA,+CAAuD;AAEvD,MAAM,aAAa,GACjB,qFAAqF;IACrF,uBAAQ,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,gCAAgC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IACvE,sDAAsD;IACtD,+BAA+B,CAAC;AAElC,MAAM,kBAAkB,GAAG,4BAAa,CAAC,kBAAkB;IACzD,CAAC,CAAC,4BAAa,CAAC,kBAAkB;IAClC,CAAC,CAAC,IAAI,KAAK,CACP,EAAE,EACF;QACE,GAAG;YACD,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;QACjC,CAAC;KACF,CACF,CAAC;AAwCN,kBAAe;IACb;;OAEG;IACH,UAAU;QACR,OAAO,kBAAkB,CAAC,UAAU,EAAE,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,MAAuB;QAC7B,OAAO,kBAAkB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,UAAU;QACR,OAAO,kBAAkB,CAAC,UAAU,EAAE,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,SAAS;QACP,OAAO,kBAAkB,CAAC,SAAS,EAAE,CAAC;IACxC,CAAC;IAED;;OAEG;IACH,WAAW;QACT,OAAO,kBAAkB,CAAC,WAAW,EAAE,CAAC;IAC1C,CAAC;CACF,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-native-wireguard-vpn-patched",
|
|
3
|
+
"version": "1.0.22-patch.2",
|
|
4
|
+
"description": "Production-ready React Native WireGuard VPN module with Android VPN permission handling and split tunneling support. Forked from react-native-wireguard-vpn v1.0.22.",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"types": "lib/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"src",
|
|
9
|
+
"lib",
|
|
10
|
+
"android/build.gradle",
|
|
11
|
+
"android/src",
|
|
12
|
+
"ios",
|
|
13
|
+
"plugin",
|
|
14
|
+
"app.plugin.js",
|
|
15
|
+
"react-native-wireguard-vpn-patched.podspec"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"prepare": "npm run build"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"react-native",
|
|
23
|
+
"wireguard",
|
|
24
|
+
"vpn",
|
|
25
|
+
"android",
|
|
26
|
+
"ios",
|
|
27
|
+
"split-tunneling",
|
|
28
|
+
"kill-switch",
|
|
29
|
+
"tunnel",
|
|
30
|
+
"wireguard-vpn"
|
|
31
|
+
],
|
|
32
|
+
"author": {
|
|
33
|
+
"name": "Abdul Ahad",
|
|
34
|
+
"email": "ahad06074@gmail.com",
|
|
35
|
+
"url": "https://github.com/AbdulAHAD968"
|
|
36
|
+
},
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "git+https://github.com/AbdulAHAD968/react-native-wireguard-vpn-patched.git"
|
|
41
|
+
},
|
|
42
|
+
"bugs": {
|
|
43
|
+
"url": "https://github.com/AbdulAHAD968/react-native-wireguard-vpn-patched/issues"
|
|
44
|
+
},
|
|
45
|
+
"homepage": "https://github.com/AbdulAHAD968/react-native-wireguard-vpn-patched#readme",
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"react": ">=18.2.0",
|
|
48
|
+
"react-native": ">=0.72.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/react": "^18.0.0",
|
|
52
|
+
"react": "18.2.0",
|
|
53
|
+
"react-native": "0.72.17",
|
|
54
|
+
"typescript": "^5.0.0"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// Expo config plugin that updates iOS Info.plist + entitlements for Network Extension.
|
|
2
|
+
// This does NOT create the Packet Tunnel extension target; that still must be created in Xcode.
|
|
3
|
+
|
|
4
|
+
const getConfigPlugins = () => {
|
|
5
|
+
// Prefer expo's re-export first, but support older setups.
|
|
6
|
+
try {
|
|
7
|
+
return require('expo/config-plugins');
|
|
8
|
+
} catch (e) {
|
|
9
|
+
return require('@expo/config-plugins');
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const configPlugins = getConfigPlugins();
|
|
14
|
+
const { withInfoPlist, withEntitlementsPlist, withAndroidManifest } = configPlugins;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @type {(config: import('@expo/config-plugins').ConfigPluginProps) => any}
|
|
18
|
+
*/
|
|
19
|
+
function withWireGuardVpn(config) {
|
|
20
|
+
// 1) iOS Info.plist
|
|
21
|
+
config = withInfoPlist(config, (cfg) => {
|
|
22
|
+
cfg.modResults.NSLocalNetworkUsageDescription =
|
|
23
|
+
cfg.modResults.NSLocalNetworkUsageDescription ||
|
|
24
|
+
'This app requires access to network features for VPN functionality';
|
|
25
|
+
|
|
26
|
+
const existingModes = cfg.modResults.UIBackgroundModes;
|
|
27
|
+
const modes = Array.isArray(existingModes) ? existingModes.slice() : [];
|
|
28
|
+
|
|
29
|
+
if (!modes.includes('network-authentication')) modes.push('network-authentication');
|
|
30
|
+
if (!modes.includes('network')) modes.push('network');
|
|
31
|
+
|
|
32
|
+
cfg.modResults.UIBackgroundModes = modes;
|
|
33
|
+
return cfg;
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// 2) iOS entitlements (.entitlements plist)
|
|
37
|
+
config = withEntitlementsPlist(config, (cfg) => {
|
|
38
|
+
const entitlements = cfg.modResults || {};
|
|
39
|
+
const key = 'com.apple.developer.networking.networkextension';
|
|
40
|
+
|
|
41
|
+
const current = entitlements[key];
|
|
42
|
+
const values = Array.isArray(current)
|
|
43
|
+
? current.slice()
|
|
44
|
+
: current
|
|
45
|
+
? [current]
|
|
46
|
+
: [];
|
|
47
|
+
|
|
48
|
+
// This entitlement is required for NEPacketTunnelProvider.
|
|
49
|
+
// If your app/provisioning already contains it, this won't duplicate values.
|
|
50
|
+
if (!values.includes('packet-tunnel-provider')) values.push('packet-tunnel-provider');
|
|
51
|
+
|
|
52
|
+
entitlements[key] = values;
|
|
53
|
+
cfg.modResults = entitlements;
|
|
54
|
+
return cfg;
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// 3) Android: ensure required VPN permissions exist in the app manifest.
|
|
58
|
+
// RN autolinking usually merges the library manifest automatically, but for Expo/prebuild
|
|
59
|
+
// we add them defensively to prevent "missing permission" issues.
|
|
60
|
+
config = withAndroidManifest(config, (cfg) => {
|
|
61
|
+
const manifest = cfg.modResults.manifest;
|
|
62
|
+
if (!manifest) return cfg;
|
|
63
|
+
|
|
64
|
+
const perms = Array.isArray(manifest['uses-permission'])
|
|
65
|
+
? manifest['uses-permission']
|
|
66
|
+
: [];
|
|
67
|
+
|
|
68
|
+
const ensurePermission = (name) => {
|
|
69
|
+
const exists = perms.some(
|
|
70
|
+
(p) => p && p.$ && p.$['android:name'] && p.$['android:name'] === name
|
|
71
|
+
);
|
|
72
|
+
if (!exists) {
|
|
73
|
+
perms.push({ $: { 'android:name': name } });
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
ensurePermission('android.permission.INTERNET');
|
|
78
|
+
ensurePermission('android.permission.FOREGROUND_SERVICE');
|
|
79
|
+
ensurePermission('android.permission.BIND_VPN_SERVICE');
|
|
80
|
+
|
|
81
|
+
manifest['uses-permission'] = perms;
|
|
82
|
+
|
|
83
|
+
// networkSecurityConfig reference: only set if it doesn't exist yet.
|
|
84
|
+
try {
|
|
85
|
+
const application = Array.isArray(manifest.application)
|
|
86
|
+
? manifest.application[0]
|
|
87
|
+
: manifest.application;
|
|
88
|
+
if (application && application.$) {
|
|
89
|
+
const existing = application.$['android:networkSecurityConfig'];
|
|
90
|
+
if (!existing) {
|
|
91
|
+
application.$['android:networkSecurityConfig'] = '@xml/network_security_config';
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
} catch (e) {
|
|
95
|
+
// ignore; manifest structure can vary across Expo/RN versions
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return cfg;
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
return config;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
module.exports = withWireGuardVpn;
|
|
105
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = "react-native-wireguard-vpn-patched"
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.description = package['description']
|
|
10
|
+
s.homepage = package['homepage']
|
|
11
|
+
s.license = package['license']
|
|
12
|
+
s.authors = package['author']
|
|
13
|
+
s.platforms = { :ios => "12.0" }
|
|
14
|
+
git_url = package['repository']['url'].to_s.gsub(/^git\+/, '').gsub(/\.git$/, '')
|
|
15
|
+
s.source = { :git => git_url, :tag => "v#{s.version}" }
|
|
16
|
+
s.source_files = "ios/**/*.{h,m,mm}"
|
|
17
|
+
s.requires_arc = true
|
|
18
|
+
s.dependency "React-Core"
|
|
19
|
+
s.frameworks = "NetworkExtension"
|
|
20
|
+
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
|
|
21
|
+
end
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
declare module 'react-native-wireguard-vpn' {
|
|
2
|
+
export interface WireGuardConfig {
|
|
3
|
+
privateKey: string;
|
|
4
|
+
publicKey: string;
|
|
5
|
+
serverAddress: string;
|
|
6
|
+
serverPort: number;
|
|
7
|
+
/** Interface address(es), e.g. "10.64.0.1/32". Optional; defaults to 10.64.0.1/32. Do not use 0.0.0.0/0 or ::/0 here. */
|
|
8
|
+
address?: string | string[];
|
|
9
|
+
allowedIPs: string[];
|
|
10
|
+
dns?: string[];
|
|
11
|
+
mtu?: number;
|
|
12
|
+
presharedKey?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface WireGuardStatus {
|
|
16
|
+
isConnected: boolean;
|
|
17
|
+
tunnelState:
|
|
18
|
+
| 'ACTIVE'
|
|
19
|
+
| 'INACTIVE'
|
|
20
|
+
| 'CONNECTING'
|
|
21
|
+
| 'DISCONNECTING'
|
|
22
|
+
| 'ERROR'
|
|
23
|
+
| 'UNKNOWN';
|
|
24
|
+
status:
|
|
25
|
+
| 'CONNECTED'
|
|
26
|
+
| 'DISCONNECTED'
|
|
27
|
+
| 'CONNECTING'
|
|
28
|
+
| 'DISCONNECTING'
|
|
29
|
+
| 'ERROR'
|
|
30
|
+
| 'UNKNOWN';
|
|
31
|
+
error?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const WireGuardVpnModule: {
|
|
35
|
+
initialize(): Promise<void>;
|
|
36
|
+
connect(config: WireGuardConfig): Promise<void>;
|
|
37
|
+
disconnect(): Promise<void>;
|
|
38
|
+
getStatus(): Promise<WireGuardStatus>;
|
|
39
|
+
isSupported(): Promise<boolean>;
|
|
40
|
+
};
|
|
41
|
+
}
|