Skip to content

Commit a8e9d37

Browse files
author
alberto lalama
authored
Bypass VPN by calling addDisallowedApplication API (#9)
1 parent b18b091 commit a8e9d37

File tree

4 files changed

+22
-172
lines changed

4 files changed

+22
-172
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ To handle DNS resoution, we have implemented a local DNS resolver that intercept
88

99
### Target Devices
1010

11-
This plugin targets Android devices running Marshmellow (API 23), or higher. This requirement stems from calling `bindProcessToNetwork`, a [connectivity API](https://developer.android.com/reference/android/net/ConnectivityManager.html#bindProcessToNetwork(android.net.Network)) introduced in version 23, which allows the client application traffic to bypass the VPN.
11+
This plugin targets Android devices running Lollipop (API 21), or higher. This requirement stems from calling `addDisallowedApplication`, a [VPNService.Builder API](https://developer.android.com/reference/android/net/VpnService.Builder.html#addDisallowedApplication(java.lang.String)) introduced in version 21, which allows the specified application's traffic to bypass the VPN.
1212

1313
### Javascript API
1414

src/android/org/uproxy/tun2socks/NetworkManager.java

-151
This file was deleted.

src/android/org/uproxy/tun2socks/Tun2Socks.java

+3-9
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ public class Tun2Socks extends CordovaPlugin {
3131

3232
private String m_socksServerAddress;
3333
private CallbackContext m_onDisconnectCallback = null;
34-
private NetworkManager m_networkManager = null;
3534

3635
@Override
3736
public boolean execute(String action, JSONArray args, CallbackContext callbackContext)
@@ -68,15 +67,14 @@ public boolean execute(String action, JSONArray args, CallbackContext callbackCo
6867
}
6968

7069
// Initializes the plugin.
71-
// Requires API 23 (Marshmallow) to use the NetworkManager.
72-
@TargetApi(Build.VERSION_CODES.M)
70+
// Requires API 21 (Lollipop) for the application traffic to bypass the VPN.
71+
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
7372
@Override
7473
protected void pluginInitialize() {
7574
if (!hasVpnService()) {
7675
Log.i(LOG_TAG, "Device does not support plugin.");
7776
return;
7877
}
79-
m_networkManager = new NetworkManager(getBaseContext());
8078

8179
LocalBroadcastManager.getInstance(getBaseContext())
8280
.registerReceiver(
@@ -86,10 +84,6 @@ protected void pluginInitialize() {
8684

8785
@Override
8886
public void onDestroy() {
89-
// Stop network manager
90-
if (m_networkManager != null) {
91-
m_networkManager.destroy();
92-
}
9387
// Stop tunnel service in case the user has quit the app without
9488
// disconnecting the VPN.
9589
stopTunnelService();
@@ -110,7 +104,7 @@ protected void prepareAndStartTunnelService(CallbackContext callbackContext) {
110104

111105
// Returns whether the device supports the tunnel VPN service.
112106
private boolean hasVpnService() {
113-
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
107+
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
114108
}
115109

116110
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)

src/android/org/uproxy/tun2socks/Tunnel.java

+18-11
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import android.annotation.TargetApi;
2323
import android.content.Context;
24+
import android.content.pm.PackageManager.NameNotFoundException;
2425
import android.net.VpnService;
2526
import android.os.Build;
2627
import android.os.ParcelFileDescriptor;
@@ -131,7 +132,7 @@ public synchronized void stop() {
131132
// synchronized functions as stop() is synchronized and a deadlock is possible as callbacks
132133
// can be called while stop holds the lock.
133134
//
134-
// Calling allowBypass on VPNService.Builder requires API 21 (Lollipop).
135+
// Calling addDisallowedApplication on VPNService.Builder requires API 21 (Lollipop).
135136
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
136137
private boolean startVpn() throws Exception {
137138
mPrivateAddress = selectPrivateAddress();
@@ -143,16 +144,22 @@ private boolean startVpn() throws Exception {
143144
// Workaround for https://code.google.com/p/android/issues/detail?id=61096
144145
Locale.setDefault(new Locale("en"));
145146

146-
ParcelFileDescriptor tunFd =
147-
((VpnService.Builder) mHostService.newVpnServiceBuilder())
148-
.setSession(mHostService.getAppName())
149-
.setMtu(VPN_INTERFACE_MTU)
150-
.addAddress(mPrivateAddress.mIpAddress, mPrivateAddress.mPrefixLength)
151-
.addRoute("0.0.0.0", 0)
152-
.addRoute(mPrivateAddress.mSubnet, mPrivateAddress.mPrefixLength)
153-
.addDnsServer(mPrivateAddress.mRouter)
154-
.allowBypass()
155-
.establish();
147+
ParcelFileDescriptor tunFd = null;
148+
try {
149+
tunFd =
150+
((VpnService.Builder) mHostService.newVpnServiceBuilder())
151+
.setSession(mHostService.getAppName())
152+
.setMtu(VPN_INTERFACE_MTU)
153+
.addAddress(mPrivateAddress.mIpAddress, mPrivateAddress.mPrefixLength)
154+
.addRoute("0.0.0.0", 0)
155+
.addDnsServer(mPrivateAddress.mRouter)
156+
.addDisallowedApplication(mHostService.getContext().getPackageName())
157+
.establish();
158+
} catch (NameNotFoundException e) {
159+
mHostService.onDiagnosticMessage(
160+
"failed exclude app from VPN: " + e.getMessage());
161+
}
162+
156163
if (tunFd == null) {
157164
// As per http://developer.android.com/reference/android/net/VpnService.Builder.html#establish%28%29,
158165
// this application is no longer prepared or was revoked.

0 commit comments

Comments
 (0)