summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2022-08-02 01:25:40 +0200
committerArne Schwabe <arne@rfc2549.org>2022-08-02 01:25:40 +0200
commit2ea430e30bb5078d52c783018eeb364e6e108138 (patch)
treebcb48a6db5c393c4135ef2a37c514cc840d75334
parent1b6616661683cea71bcab21c3bb75b3520c5b501 (diff)
Use route exclusion API available in API 33
-rw-r--r--main/build.gradle.kts5
-rw-r--r--main/src/main/cpp/CMakeLists.txt2
m---------main/src/main/cpp/openvpn30
-rw-r--r--main/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java30
-rw-r--r--main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java83
-rw-r--r--main/src/ui/java/de/blinkt/openvpn/core/OpenVPNThreadv3.java1
6 files changed, 91 insertions, 30 deletions
diff --git a/main/build.gradle.kts b/main/build.gradle.kts
index 8ca1f1a9..ac2eeae0 100644
--- a/main/build.gradle.kts
+++ b/main/build.gradle.kts
@@ -13,13 +13,13 @@ plugins {
}
android {
- compileSdk = 32
+ compileSdk = 33
ndkVersion = "24.0.8215888"
defaultConfig {
minSdk = 21
- targetSdk = 32
+ targetSdk = 33
versionCode = 193
versionName = "0.7.38"
externalNativeBuild {
@@ -140,6 +140,7 @@ fun registerGenTask(variantName: String, variantDirName: String): File {
}
commandLine(listOf(swigcmd, "-outdir", genDir, "-outcurrentdir", "-c++", "-java", "-package", "net.openvpn.ovpn3",
"-Isrc/main/cpp/openvpn3/client", "-Isrc/main/cpp/openvpn3/",
+ "-DOPENVPN_PLATFORM_ANDROID",
"-o", "${genDir}/ovpncli_wrap.cxx", "-oh", "${genDir}/ovpncli_wrap.h",
"src/main/cpp/openvpn3/client/ovpncli.i"))
inputs.files( "src/main/cpp/openvpn3/client/ovpncli.i")
diff --git a/main/src/main/cpp/CMakeLists.txt b/main/src/main/cpp/CMakeLists.txt
index 0921e807..c0222151 100644
--- a/main/src/main/cpp/CMakeLists.txt
+++ b/main/src/main/cpp/CMakeLists.txt
@@ -45,6 +45,7 @@ if (NOT ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} MATCHES "build/intermediates/cmake/.*s
-c++
-java -package net.openvpn.ovpn3
-outcurrentdir
+ -DOPENVPN_PLATFORM_ANDROID
-I${CMAKE_SOURCE_DIR}/openvpn3/client
-I${CMAKE_SOURCE_DIR}/openvpn3
${CMAKE_SOURCE_DIR}/openvpn3/client/ovpncli.i)
@@ -92,7 +93,6 @@ if (NOT ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} MATCHES "build/intermediates/cmake/.*s
-DASIO_STANDALONE
-DUSE_ASIO
-DGIT_VERSION_STRING=\"${OPENVPN3_GIT}\"
- -DNO_ROUTE_EXCLUDE_EMULATION
-DOPENVPN_SHOW_SESSION_TOKEN
-DOPENSSL_API_COMPAT=0x10200000L
-DOPENVPN_ALLOW_INSECURE_CERTPROFILE
diff --git a/main/src/main/cpp/openvpn3 b/main/src/main/cpp/openvpn3
-Subproject 9f02ce1670f75d8f3b9eb903394368fee53cd05
+Subproject a6296185ec5d6f604ed2c66a3e1c81ff99e387f
diff --git a/main/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java b/main/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java
index 5876ead5..9c8cf363 100644
--- a/main/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java
+++ b/main/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java
@@ -5,11 +5,17 @@
package de.blinkt.openvpn.core;
-import android.os.Build;
+import android.net.IpPrefix;
+
import androidx.annotation.NonNull;
+import java.lang.reflect.Array;
import java.math.BigInteger;
+import java.net.Inet4Address;
import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Locale;
import java.util.PriorityQueue;
@@ -203,6 +209,28 @@ public class NetworkSpace {
return a && b;
}
+
+ public IpPrefix getPrefix() throws UnknownHostException {
+ if (isV4){
+ /* add 0x01 00 00 00 00, so that all representations are 5 byte otherwise
+ /* numbers that are above 0x7fffffff get a leading 0x00 byte to not be negative
+ and small number 1-3 bytes*/
+ byte[] ipBytes = netAddress.add(BigInteger.valueOf(0x0100000000L)).toByteArray();
+ ipBytes = Arrays.copyOfRange(ipBytes, 1, 5);
+
+ InetAddress inet4addr = Inet4Address.getByAddress(ipBytes);
+ return new IpPrefix(inet4addr, networkMask);
+ }
+ else
+ {
+ /* same dance for IPv6 */
+ byte[] ipBytes = netAddress.add(BigInteger.ONE.shiftLeft(128)).toByteArray();
+ ipBytes = Arrays.copyOfRange(ipBytes, 1, 17);
+
+ InetAddress inet6addr = Inet6Address.getByAddress(ipBytes);
+ return new IpPrefix(inet6addr, networkMask);
+ }
+ }
}
diff --git a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
index 8d8ea145..d3de35f9 100644
--- a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
+++ b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
@@ -5,9 +5,11 @@
package de.blinkt.openvpn.core;
+import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_CONNECTED;
+import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT;
+import static de.blinkt.openvpn.core.NetworkSpace.IpAddress;
+
import android.Manifest.permission;
-import android.annotation.TargetApi;
-import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -21,6 +23,7 @@ import android.content.pm.ShortcutManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.net.ConnectivityManager;
+import android.net.IpPrefix;
import android.net.ProxyInfo;
import android.net.Uri;
import android.net.VpnService;
@@ -62,10 +65,6 @@ import de.blinkt.openvpn.api.ExternalAppDatabase;
import de.blinkt.openvpn.core.VpnStatus.ByteCountListener;
import de.blinkt.openvpn.core.VpnStatus.StateListener;
-import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_CONNECTED;
-import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT;
-import static de.blinkt.openvpn.core.NetworkSpace.IpAddress;
-
public class OpenVPNService extends VpnService implements StateListener, Callback, ByteCountListener, IOpenVPNServiceInternal {
public static final String START_SERVICE = "de.blinkt.openvpn.START_SERVICE";
public static final String START_SERVICE_STICKY = "de.blinkt.openvpn.START_SERVICE_STICKY";
@@ -813,26 +812,12 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
}
- IpAddress multicastRange = new IpAddress(new CIDRIP("224.0.0.0", 3), true);
-
- for (IpAddress route : positiveIPv4Routes) {
- try {
- if (multicastRange.containsNet(route))
- VpnStatus.logDebug(R.string.ignore_multicast_route, route.toString());
- else
- builder.addRoute(route.getIPv4Address(), route.networkMask);
- } catch (IllegalArgumentException ia) {
- VpnStatus.logError(getString(R.string.route_rejected) + route + " " + ia.getLocalizedMessage());
- }
- }
-
- for (IpAddress route6 : positiveIPv6Routes) {
- try {
- builder.addRoute(route6.getIPv6Address(), route6.networkMask);
- } catch (IllegalArgumentException ia) {
- VpnStatus.logError(getString(R.string.route_rejected) + route6 + " " + ia.getLocalizedMessage());
- }
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ installRoutesExcluded(builder, mRoutes);
+ installRoutesExcluded(builder, mRoutesv6);
+ } else {
+ installRoutesPostiveOnly(builder, positiveIPv4Routes, positiveIPv6Routes);
}
@@ -872,7 +857,10 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
if (mProxyInfo != null) {
VpnStatus.logInfo(R.string.proxy_info, mProxyInfo.getHost(), mProxyInfo.getPort());
}
- VpnStatus.logDebug(R.string.routes_debug, TextUtils.join(", ", positiveIPv4Routes), TextUtils.join(", ", positiveIPv6Routes));
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
+ /* On Tiramisu we install the routes exactly like promised */
+ VpnStatus.logDebug(R.string.routes_debug, TextUtils.join(", ", positiveIPv4Routes), TextUtils.join(", ", positiveIPv6Routes));
+ }
setAllowedVpnPackages(builder);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
// VPN always uses the default network
@@ -928,6 +916,49 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
+ private void installRoutesExcluded(Builder builder, NetworkSpace routes)
+ {
+ for(IpAddress ipIncl: routes.getNetworks(true))
+ {
+ try {
+ builder.addRoute(ipIncl.getPrefix());
+ } catch (UnknownHostException|IllegalArgumentException ia) {
+ VpnStatus.logError(getString(R.string.route_rejected) + ipIncl + " " + ia.getLocalizedMessage());
+ }
+ }
+ for(IpAddress ipExcl: routes.getNetworks(false))
+ {
+ try {
+ builder.excludeRoute(ipExcl.getPrefix());
+ } catch (UnknownHostException|IllegalArgumentException ia) {
+ VpnStatus.logError(getString(R.string.route_rejected) + ipExcl + " " + ia.getLocalizedMessage());
+ }
+ }
+ }
+
+ private void installRoutesPostiveOnly(Builder builder, Collection<IpAddress> positiveIPv4Routes, Collection<IpAddress> positiveIPv6Routes) {
+ IpAddress multicastRange = new IpAddress(new CIDRIP("224.0.0.0", 3), true);
+
+ for (IpAddress route : positiveIPv4Routes) {
+ try {
+ if (multicastRange.containsNet(route))
+ VpnStatus.logDebug(R.string.ignore_multicast_route, route.toString());
+ else
+ builder.addRoute(route.getIPv4Address(), route.networkMask);
+ } catch (IllegalArgumentException ia) {
+ VpnStatus.logError(getString(R.string.route_rejected) + route + " " + ia.getLocalizedMessage());
+ }
+ }
+
+ for (IpAddress route6 : positiveIPv6Routes) {
+ try {
+ builder.addRoute(route6.getIPv6Address(), route6.networkMask);
+ } catch (IllegalArgumentException ia) {
+ VpnStatus.logError(getString(R.string.route_rejected) + route6 + " " + ia.getLocalizedMessage());
+ }
+ }
+ }
+
private void setHttpProxy(Builder builder) {
if (mProxyInfo != null && Build.VERSION.SDK_INT >= 29) {
builder.setHttpProxy(mProxyInfo);
diff --git a/main/src/ui/java/de/blinkt/openvpn/core/OpenVPNThreadv3.java b/main/src/ui/java/de/blinkt/openvpn/core/OpenVPNThreadv3.java
index 0cbd7ce5..75093e14 100644
--- a/main/src/ui/java/de/blinkt/openvpn/core/OpenVPNThreadv3.java
+++ b/main/src/ui/java/de/blinkt/openvpn/core/OpenVPNThreadv3.java
@@ -195,6 +195,7 @@ public class OpenVPNThreadv3 extends ClientAPI_OpenVPNClient implements Runnable
boolean retryOnAuthFailed = mVp.mAuthRetry == AUTH_RETRY_NOINTERACT;
config.setRetryOnAuthFailed(retryOnAuthFailed);
config.setEnableLegacyAlgorithms(mVp.mUseLegacyProvider);
+ config.setEnableRouteEmulation(false);
if (mVp.mCompatMode > 0 && mVp.mCompatMode < 20500)
config.setEnableNonPreferredDCAlgorithms(true);
if (!TextUtils.isEmpty(mVp.mTlSCertProfile))