diff options
-rw-r--r-- | main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java | 208 |
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"; |