summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java208
1 files changed, 107 insertions, 101 deletions
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 edc36e9a..5b59a907 100644
--- a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
+++ b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
@@ -87,17 +87,27 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
private static final int PRIORITY_DEFAULT = 0;
private static final int PRIORITY_MAX = 2;
private static boolean mNotificationAlwaysVisible = false;
- private final Vector<String> mDnslist = new Vector<>();
- private final NetworkSpace mRoutes = new NetworkSpace();
- private final NetworkSpace mRoutesv6 = new NetworkSpace();
+
+ static class TunConfig {
+ private final Vector<String> mDnslist = new Vector<>();
+ private final NetworkSpace mRoutes = new NetworkSpace();
+ private final NetworkSpace mRoutesv6 = new NetworkSpace();
+ private String mDomain = null;
+ private CIDRIP mLocalIP = null;
+ private int mMtu;
+ private String mLocalIPv6 = null;
+
+ private ProxyInfo mProxyInfo;
+ };
+
+ private TunConfig tunConfig = new TunConfig();
+
private final Object mProcessLock = new Object();
private String lastChannel;
private Thread mProcessThread = null;
private VpnProfile mProfile;
- private String mDomain = null;
- private CIDRIP mLocalIP = null;
- private int mMtu;
- private String mLocalIPv6 = null;
+
+
private DeviceStateReceiver mDeviceStateReceiver;
private boolean mDisplayBytecount = false;
private boolean mStarting = false;
@@ -138,12 +148,11 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
};
- private String mLastTunCfg;
+ private TunConfig mLastTunCfg;
private String mRemoteGW;
private Handler guiHandler;
private Toast mlastToast;
private Runnable mOpenVPNThread;
- private ProxyInfo mProxyInfo;
private HandlerThread mCommandHandlerThread;
private Handler mCommandHandler;
@@ -747,27 +756,35 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
VpnStatus.flushLog();
}
- private String getTunConfigString() {
+ private static String getTunConfigString(TunConfig tc) {
// The format of the string is not important, only that
// two identical configurations produce the same result
String cfg = "TUNCFG UNQIUE STRING ips:";
- if (mLocalIP != null)
- cfg += mLocalIP.toString();
- if (mLocalIPv6 != null)
- cfg += mLocalIPv6;
+ if (tc.mLocalIP != null)
+ cfg += tc.mLocalIP.toString();
+ if (tc.mLocalIPv6 != null)
+ cfg += tc.mLocalIPv6;
- cfg += "routes: " + TextUtils.join("|", mRoutes.getNetworks(true)) + TextUtils.join("|", mRoutesv6.getNetworks(true));
- cfg += "excl. routes:" + TextUtils.join("|", mRoutes.getNetworks(false)) + TextUtils.join("|", mRoutesv6.getNetworks(false));
- cfg += "dns: " + TextUtils.join("|", mDnslist);
- cfg += "domain: " + mDomain;
- cfg += "mtu: " + mMtu;
- cfg += "proxyInfo: " + mProxyInfo;
+ cfg += "routes: " + TextUtils.join("|", tc.mRoutes.getNetworks(true)) + TextUtils.join("|", tc.mRoutesv6.getNetworks(true));
+ cfg += "excl. routes:" + TextUtils.join("|", tc.mRoutes.getNetworks(false)) + TextUtils.join("|", tc.mRoutesv6.getNetworks(false));
+ cfg += "dns: " + TextUtils.join("|", tc.mDnslist);
+ cfg += "domain: " + tc.mDomain;
+ cfg += "mtu: " + tc.mMtu;
+ cfg += "proxyInfo: " + tc.mProxyInfo;
return cfg;
}
public ParcelFileDescriptor openTun() {
+ ParcelFileDescriptor pfd = openTun(tunConfig);
+
+ // Reset information
+ mLastTunCfg = tunConfig;
+ tunConfig = new TunConfig();
+ return pfd;
+ }
+ private ParcelFileDescriptor openTun(TunConfig tc) {
//Debug.startMethodTracing(getExternalFilesDir(null).toString() + "/opentun.trace", 40* 1024 * 1024);
@@ -786,36 +803,36 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
allowAllAFFamilies(builder);
}
- if (mLocalIP == null && mLocalIPv6 == null) {
+ if (tc.mLocalIP == null && tc.mLocalIPv6 == null) {
VpnStatus.logError(getString(R.string.opentun_no_ipaddr));
return null;
}
- if (mLocalIP != null) {
+ if (tc.mLocalIP != null) {
// OpenVPN3 manages excluded local networks by callback
if (!VpnProfile.doUseOpenVPN3(this))
- addLocalNetworksToRoutes();
+ addLocalNetworksToRoutes(tc);
try {
- builder.addAddress(mLocalIP.mIp, mLocalIP.len);
+ builder.addAddress(tc.mLocalIP.mIp, tc.mLocalIP.len);
} catch (IllegalArgumentException iae) {
- VpnStatus.logError(R.string.dns_add_error, mLocalIP, iae.getLocalizedMessage());
+ VpnStatus.logError(R.string.dns_add_error, tc.mLocalIP, iae.getLocalizedMessage());
return null;
}
}
- if (mLocalIPv6 != null) {
- String[] ipv6parts = mLocalIPv6.split("/");
+ if (tc.mLocalIPv6 != null) {
+ String[] ipv6parts = tc.mLocalIPv6.split("/");
try {
builder.addAddress(ipv6parts[0], Integer.parseInt(ipv6parts[1]));
} catch (IllegalArgumentException iae) {
- VpnStatus.logError(R.string.ip_add_error, mLocalIPv6, iae.getLocalizedMessage());
+ VpnStatus.logError(R.string.ip_add_error, tc.mLocalIPv6, iae.getLocalizedMessage());
return null;
}
}
- for (String dns : mDnslist) {
+ for (String dns : tc.mDnslist) {
try {
builder.addDnsServer(dns);
} catch (IllegalArgumentException iae) {
@@ -824,15 +841,15 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
String release = Build.VERSION.RELEASE;
- builder.setMtu(mMtu);
+ builder.setMtu(tc.mMtu);
- Collection<IpAddress> positiveIPv4Routes = mRoutes.getPositiveIPList();
- Collection<IpAddress> positiveIPv6Routes = mRoutesv6.getPositiveIPList();
+ Collection<IpAddress> positiveIPv4Routes = tc.mRoutes.getPositiveIPList();
+ Collection<IpAddress> positiveIPv6Routes = tc.mRoutesv6.getPositiveIPList();
- if ("samsung".equals(Build.BRAND) && mDnslist.size() >= 1) {
+ if ("samsung".equals(Build.BRAND) && tc.mDnslist.size() >= 1) {
// Check if the first DNS Server is in the VPN range
try {
- IpAddress dnsServer = new IpAddress(new CIDRIP(mDnslist.get(0), 32), true);
+ IpAddress dnsServer = new IpAddress(new CIDRIP(tc.mDnslist.get(0), 32), true);
boolean dnsIncluded = false;
for (IpAddress net : positiveIPv4Routes) {
if (net.containsNet(dnsServer)) {
@@ -840,28 +857,28 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
}
if (!dnsIncluded) {
- String samsungwarning = String.format("Warning Samsung Android 5.0+ devices ignore DNS servers outside the VPN range. To enable DNS resolution a route to your DNS Server (%s) has been added.", mDnslist.get(0));
+ String samsungwarning = String.format("Warning Samsung Android 5.0+ devices ignore DNS servers outside the VPN range. To enable DNS resolution a route to your DNS Server (%s) has been added.", tc.mDnslist.get(0));
VpnStatus.logWarning(samsungwarning);
positiveIPv4Routes.add(dnsServer);
}
} catch (Exception e) {
// If it looks like IPv6 ignore error
- if (!mDnslist.get(0).contains(":"))
- VpnStatus.logError("Error parsing DNS Server IP: " + mDnslist.get(0));
+ if (!tc.mDnslist.get(0).contains(":"))
+ VpnStatus.logError("Error parsing DNS Server IP: " + tc.mDnslist.get(0));
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
- installRoutesExcluded(builder, mRoutes);
- installRoutesExcluded(builder, mRoutesv6);
+ installRoutesExcluded(builder, tc.mRoutes);
+ installRoutesExcluded(builder, tc.mRoutesv6);
} else {
installRoutesPostiveOnly(builder, positiveIPv4Routes, positiveIPv6Routes);
}
- if (mDomain != null)
- builder.addSearchDomain(mDomain);
+ if (tc.mDomain != null)
+ builder.addSearchDomain(tc.mDomain);
String ipv4info;
String ipv6info;
@@ -874,27 +891,27 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
int ipv4len;
- if (mLocalIP != null) {
- ipv4len = mLocalIP.len;
- ipv4info = mLocalIP.mIp;
+ if (tc.mLocalIP != null) {
+ ipv4len = tc.mLocalIP.len;
+ ipv4info = tc.mLocalIP.mIp;
} else {
ipv4len = -1;
}
- if (mLocalIPv6 != null) {
- ipv6info = mLocalIPv6;
+ if (tc.mLocalIPv6 != null) {
+ ipv6info = tc.mLocalIPv6;
}
- if ((!mRoutes.getNetworks(false).isEmpty() || !mRoutesv6.getNetworks(false).isEmpty()) && isLockdownEnabledCompat()) {
+ if ((!tc.mRoutes.getNetworks(false).isEmpty() || !tc.mRoutesv6.getNetworks(false).isEmpty()) && isLockdownEnabledCompat()) {
VpnStatus.logInfo("VPN lockdown enabled (do not allow apps to bypass VPN) enabled. Route exclusion will not allow apps to bypass VPN (e.g. bypass VPN for local networks)");
}
- VpnStatus.logInfo(R.string.local_ip_info, ipv4info, ipv4len, ipv6info, mMtu);
- VpnStatus.logInfo(R.string.dns_server_info, TextUtils.join(", ", mDnslist), mDomain);
- VpnStatus.logInfo(R.string.routes_info_incl, TextUtils.join(", ", mRoutes.getNetworks(true)), TextUtils.join(", ", mRoutesv6.getNetworks(true)));
- VpnStatus.logInfo(R.string.routes_info_excl, TextUtils.join(", ", mRoutes.getNetworks(false)), TextUtils.join(", ", mRoutesv6.getNetworks(false)));
- if (mProxyInfo != null) {
- VpnStatus.logInfo(R.string.proxy_info, mProxyInfo.getHost(), mProxyInfo.getPort());
+ VpnStatus.logInfo(R.string.local_ip_info, ipv4info, ipv4len, ipv6info, tc.mMtu);
+ VpnStatus.logInfo(R.string.dns_server_info, TextUtils.join(", ", tc.mDnslist), tc.mDomain);
+ VpnStatus.logInfo(R.string.routes_info_incl, TextUtils.join(", ", tc.mRoutes.getNetworks(true)), TextUtils.join(", ", tc.mRoutesv6.getNetworks(true)));
+ VpnStatus.logInfo(R.string.routes_info_excl, TextUtils.join(", ", tc.mRoutes.getNetworks(false)), TextUtils.join(", ", tc.mRoutesv6.getNetworks(false)));
+ if (tc.mProxyInfo != null) {
+ VpnStatus.logInfo(R.string.proxy_info, tc.mProxyInfo.getHost(), tc.mProxyInfo.getPort());
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
/* On Tiramisu we install the routes exactly like promised */
@@ -915,31 +932,20 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
String session = mProfile.mName;
- if (mLocalIP != null && mLocalIPv6 != null)
- session = getString(R.string.session_ipv6string, session, mLocalIP, mLocalIPv6);
- else if (mLocalIP != null)
- session = getString(R.string.session_ipv4string, session, mLocalIP);
+ if (tc.mLocalIP != null && tc.mLocalIPv6 != null)
+ session = getString(R.string.session_ipv6string, session, tc.mLocalIP, tc.mLocalIPv6);
+ else if (tc.mLocalIP != null)
+ session = getString(R.string.session_ipv4string, session, tc.mLocalIP);
else
- session = getString(R.string.session_ipv4string, session, mLocalIPv6);
+ session = getString(R.string.session_ipv4string, session, tc.mLocalIPv6);
builder.setSession(session);
// No DNS Server, log a warning
- if (mDnslist.size() == 0)
+ if (tc.mDnslist.size() == 0)
VpnStatus.logInfo(R.string.warn_no_dns);
- setHttpProxy(builder);
-
- mLastTunCfg = getTunConfigString();
-
- // Reset information
- mDnslist.clear();
- mRoutes.clear();
- mRoutesv6.clear();
- mLocalIP = null;
- mLocalIPv6 = null;
- mDomain = null;
- mProxyInfo = null;
+ setHttpProxy(builder, tc);
builder.setConfigureIntent(getGraphPendingIntent());
@@ -1000,10 +1006,10 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
}
- private void setHttpProxy(Builder builder) {
- if (mProxyInfo != null && Build.VERSION.SDK_INT >= 29) {
- builder.setHttpProxy(mProxyInfo);
- } else if (mProxyInfo != null) {
+ private void setHttpProxy(Builder builder, TunConfig tc) {
+ if (tc.mProxyInfo != null && Build.VERSION.SDK_INT >= 29) {
+ builder.setHttpProxy(tc.mProxyInfo);
+ } else if (tc.mProxyInfo != null) {
VpnStatus.logWarning("HTTP Proxy needs Android 10 or later.");
}
}
@@ -1023,16 +1029,16 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
builder.allowFamily(OsConstants.AF_INET6);
}
- private void addLocalNetworksToRoutes() {
+ private void addLocalNetworksToRoutes(TunConfig tc) {
for (String net : NetworkUtils.getLocalNetworks(this, false)) {
String[] netparts = net.split("/");
String ipAddr = netparts[0];
int netMask = Integer.parseInt(netparts[1]);
- if (ipAddr.equals(mLocalIP.mIp))
+ if (ipAddr.equals(tc.mLocalIP.mIp))
continue;
if(mProfile.mAllowLocalLAN)
- mRoutes.addIP(new CIDRIP(ipAddr, netMask), false);
+ tc.mRoutes.addIP(new CIDRIP(ipAddr, netMask), false);
}
if (mProfile.mAllowLocalLAN) {
@@ -1103,12 +1109,12 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
public void addDNS(String dns) {
- mDnslist.add(dns);
+ tunConfig.mDnslist.add(dns);
}
public void setDomain(String domain) {
- if (mDomain == null) {
- mDomain = domain;
+ if (tunConfig.mDomain == null) {
+ tunConfig.mDomain = domain;
}
}
@@ -1116,12 +1122,12 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
* Route that is always included, used by the v3 core
*/
public void addRoute(CIDRIP route, boolean include) {
- mRoutes.addIP(route, include);
+ tunConfig.mRoutes.addIP(route, include);
}
public boolean addHttpProxy(String proxy, int port) {
try {
- mProxyInfo = ProxyInfo.buildDirectProxy(proxy, port);
+ tunConfig.mProxyInfo = ProxyInfo.buildDirectProxy(proxy, port);
} catch (Exception e) {
VpnStatus.logError("Could not set proxy" + e.getLocalizedMessage());
return false;
@@ -1135,11 +1141,11 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
IpAddress gatewayIP = new IpAddress(new CIDRIP(gateway, 32), false);
- if (mLocalIP == null) {
+ if (tunConfig.mLocalIP == null) {
VpnStatus.logError("Local IP address unset and received. Neither pushed server config nor local config specifies an IP addresses. Opening tun device is most likely going to fail.");
return;
}
- IpAddress localNet = new IpAddress(mLocalIP, true);
+ IpAddress localNet = new IpAddress(tunConfig.mLocalIP, true);
if (localNet.containsNet(gatewayIP))
include = true;
@@ -1155,7 +1161,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
if (route.normalise())
VpnStatus.logWarning(R.string.route_not_netip, dest, route.len, route.mIp);
- mRoutes.addIP(route, include);
+ tunConfig.mRoutes.addIP(route, include);
}
public void addRoutev6(String network, String device) {
@@ -1170,7 +1176,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
try {
Inet6Address ip = (Inet6Address) InetAddress.getAllByName(v6parts[0])[0];
int mask = Integer.parseInt(v6parts[1]);
- mRoutesv6.addIPv6(ip, mask, included);
+ tunConfig.mRoutesv6.addIPv6(ip, mask, included);
} catch (UnknownHostException e) {
VpnStatus.logException(e);
@@ -1185,21 +1191,21 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
public void setMtu(int mtu) {
- mMtu = mtu;
+ tunConfig.mMtu = mtu;
}
public void setLocalIP(CIDRIP cdrip) {
- mLocalIP = cdrip;
+ tunConfig.mLocalIP = cdrip;
}
public void setLocalIP(String local, String netmask, int mtu, String mode) {
- mLocalIP = new CIDRIP(local, netmask);
- mMtu = mtu;
+ tunConfig.mLocalIP = new CIDRIP(local, netmask);
+ tunConfig.mMtu = mtu;
mRemoteGW = null;
long netMaskAsInt = CIDRIP.getInt(netmask);
- if (mLocalIP.len == 32 && !netmask.equals("255.255.255.255")) {
+ if (tunConfig.mLocalIP.len == 32 && !netmask.equals("255.255.255.255")) {
// get the netmask as IP
int masklen;
@@ -1213,22 +1219,22 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
// Netmask is Ip address +/-1, assume net30/p2p with small net
- if ((netMaskAsInt & mask) == (mLocalIP.getInt() & mask)) {
- mLocalIP.len = masklen;
+ if ((netMaskAsInt & mask) == (tunConfig.mLocalIP.getInt() & mask)) {
+ tunConfig.mLocalIP.len = masklen;
} else {
- mLocalIP.len = 32;
+ tunConfig.mLocalIP.len = 32;
if (!"p2p".equals(mode))
VpnStatus.logWarning(R.string.ip_not_cidr, local, netmask, mode);
}
}
- if (("p2p".equals(mode) && mLocalIP.len < 32) || ("net30".equals(mode) && mLocalIP.len < 30)) {
+ if (("p2p".equals(mode) && tunConfig.mLocalIP.len < 32) || ("net30".equals(mode) && tunConfig.mLocalIP.len < 30)) {
VpnStatus.logWarning(R.string.ip_looks_like_subnet, local, netmask, mode);
}
/* Workaround for Lollipop and higher, it does not route traffic to the VPNs own network mask */
- if (mLocalIP.len <= 31) {
- CIDRIP interfaceRoute = new CIDRIP(mLocalIP.mIp, mLocalIP.len);
+ if (tunConfig.mLocalIP.len <= 31) {
+ CIDRIP interfaceRoute = new CIDRIP(tunConfig.mLocalIP.mIp, tunConfig.mLocalIP.len);
interfaceRoute.normalise();
addRoute(interfaceRoute, true);
}
@@ -1239,7 +1245,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
public void setLocalIPv6(String ipv6addr) {
- mLocalIPv6 = ipv6addr;
+ tunConfig.mLocalIPv6 = ipv6addr;
}
@Override
@@ -1317,8 +1323,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
public String getTunReopenStatus() {
- String currentConfiguration = getTunConfigString();
- if (currentConfiguration.equals(mLastTunCfg)) {
+ String currentConfiguration = getTunConfigString(mLastTunCfg);
+ if (currentConfiguration.equals(getTunConfigString(mLastTunCfg))) {
return "NOACTION";
} else {
return "OPEN_BEFORE_CLOSE";