private ParcelFileDescriptor startVPN() { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); // Check state boolean wifi = Util.isWifiActive(this); boolean metered = Util.isMeteredNetwork(this); boolean useMetered = prefs.getBoolean("use_metered", false); Set<String> ssidHomes = prefs.getStringSet("wifi_homes", new HashSet<String>()); String ssidNetwork = Util.getWifiSSID(this); String generation = Util.getNetworkGeneration(this); boolean unmetered_2g = prefs.getBoolean("unmetered_2g", false); boolean unmetered_3g = prefs.getBoolean("unmetered_3g", false); boolean unmetered_4g = prefs.getBoolean("unmetered_4g", false); boolean roaming = Util.isRoaming(SinkholeService.this); boolean national = prefs.getBoolean("national_roaming", false); boolean telephony = Util.hasTelephony(this); // Update connected state last_connected = Util.isConnected(SinkholeService.this); // Update metered state if (wifi && (!useMetered || !telephony)) metered = false; if (wifi && ssidHomes.size() > 0 && !ssidHomes.contains(ssidNetwork)) metered = true; if (unmetered_2g && "2G".equals(generation)) metered = false; if (unmetered_3g && "3G".equals(generation)) metered = false; if (unmetered_4g && "4G".equals(generation)) metered = false; if (!last_connected) metered = true; last_metered = metered; // Update roaming state if (roaming && national) roaming = Util.isInternational(this); Log.i( TAG, "Starting connected=" + last_connected + " wifi=" + wifi + " metered=" + metered + " telephony=" + telephony + " generation=" + generation + " roaming=" + roaming + " interactive=" + last_interactive); // Build VPN service final Builder builder = new Builder(); builder.setSession(getString(R.string.app_name) + " session"); // TODO: make tunnel parameters configurable builder.addAddress("10.1.10.1", 32); builder.addAddress("fd00:1:fd00:1:fd00:1:fd00:1", 64); builder.addRoute("0.0.0.0", 0); builder.addRoute("0:0:0:0:0:0:0:0", 0); // Add list of allowed applications int nAllowed = 0; int nBlocked = 0; for (Rule rule : Rule.getRules(true, TAG, this)) { boolean blocked = (metered ? rule.other_blocked : rule.wifi_blocked); boolean screen = (metered ? rule.screen_other : rule.screen_wifi); if ((!blocked || (screen && last_interactive)) && (!metered || !(rule.roaming && roaming))) { nAllowed++; if (debug) Log.i(TAG, "Allowing " + rule.info.packageName); try { builder.addDisallowedApplication(rule.info.packageName); } catch (PackageManager.NameNotFoundException ex) { Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex)); Util.sendCrashReport(ex, this); } } else nBlocked++; } Log.i(TAG, "Allowed=" + nAllowed + " blocked=" + nBlocked); // Update notification Notification notification = getForegroundNotification(nAllowed, nBlocked); NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); nm.notify(NOTIFY_FOREGROUND, notification); // Build configure intent Intent configure = new Intent(this, ActivityMain.class); PendingIntent pi = PendingIntent.getActivity(this, 0, configure, PendingIntent.FLAG_UPDATE_CURRENT); builder.setConfigureIntent(pi); if (debug) builder.setBlocking(true); // Start VPN service return builder.establish(); }
private ParcelFileDescriptor startVPN() { Log.i(TAG, "Starting"); // Check state boolean wifi = Util.isWifiActive(this); boolean metered = Util.isMetered(this); boolean interactive = Util.isInteractive(this); Log.i( TAG, "wifi=" + wifi + " metered=" + metered + " roaming=" + last_roaming + " interactive=" + interactive); // Build VPN service final Builder builder = new Builder(); builder.setSession(getString(R.string.app_name)); // TODO: make tunnel parameters configurable builder.addAddress("10.1.10.1", 32); builder.addAddress("fd00:1:fd00:1:fd00:1:fd00:1", 64); builder.addRoute("0.0.0.0", 0); builder.addRoute("0:0:0:0:0:0:0:0", 0); // Add list of allowed applications for (Rule rule : Rule.getRules(true, TAG, this)) { boolean blocked = (metered ? rule.other_blocked : rule.wifi_blocked); if ((!blocked || (rule.unused && interactive)) && (!metered || !(rule.roaming && last_roaming))) { if (debug) Log.i(TAG, "Allowing " + rule.info.packageName); try { builder.addDisallowedApplication(rule.info.packageName); } catch (PackageManager.NameNotFoundException ex) { Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex)); } } } // Build configure intent Intent configure = new Intent(this, ActivityMain.class); PendingIntent pi = PendingIntent.getActivity(this, 0, configure, PendingIntent.FLAG_UPDATE_CURRENT); builder.setConfigureIntent(pi); if (debug) builder.setBlocking(true); // Start VPN service try { return builder.establish(); } catch (Throwable ex) { Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex)); // Disable firewall SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); prefs.edit().putBoolean("enabled", false).apply(); // Feedback Util.toast(ex.toString(), Toast.LENGTH_LONG, this); Widget.updateWidgets(this); return null; } }
public ParcelFileDescriptor openTun() { // Debug.startMethodTracing(getExternalFilesDir(null).toString() + "/opentun.trace", 40* 1024 * // 1024); Builder builder = new Builder(); VpnStatus.logInfo(R.string.last_openvpn_tun_config); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mProfile.mAllowLocalLAN) { allowAllAFFamilies(builder); } if (mLocalIP == null && mLocalIPv6 == null) { VpnStatus.logError(getString(R.string.opentun_no_ipaddr)); return null; } if (mLocalIP != null) { addLocalNetworksToRoutes(); try { builder.addAddress(mLocalIP.mIp, mLocalIP.len); } catch (IllegalArgumentException iae) { VpnStatus.logError(R.string.dns_add_error, mLocalIP, iae.getLocalizedMessage()); return null; } } if (mLocalIPv6 != null) { String[] ipv6parts = mLocalIPv6.split("/"); try { builder.addAddress(ipv6parts[0], Integer.parseInt(ipv6parts[1])); } catch (IllegalArgumentException iae) { VpnStatus.logError(R.string.ip_add_error, mLocalIPv6, iae.getLocalizedMessage()); return null; } } for (String dns : mDnslist) { try { builder.addDnsServer(dns); } catch (IllegalArgumentException iae) { VpnStatus.logError(R.string.dns_add_error, dns, iae.getLocalizedMessage()); } } String release = Build.VERSION.RELEASE; if ((Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT && !release.startsWith("4.4.3") && !release.startsWith("4.4.4") && !release.startsWith("4.4.5") && !release.startsWith("4.4.6")) && mMtu < 1280) { VpnStatus.logInfo( String.format( Locale.US, "Forcing MTU to 1280 instead of %d to workaround Android Bug #70916", mMtu)); builder.setMtu(1280); } else { builder.setMtu(mMtu); } Collection<ipAddress> positiveIPv4Routes = mRoutes.getPositiveIPList(); Collection<ipAddress> positiveIPv6Routes = mRoutesv6.getPositiveIPList(); ipAddress multicastRange = new ipAddress(new CIDRIP("224.0.0.0", 3), true); for (NetworkSpace.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 (NetworkSpace.ipAddress route6 : positiveIPv6Routes) { try { builder.addRoute(route6.getIPv6Address(), route6.networkMask); } catch (IllegalArgumentException ia) { VpnStatus.logError( getString(R.string.route_rejected) + route6 + " " + ia.getLocalizedMessage()); } } if ("samsung".equals(Build.BRAND) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && 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); boolean dnsIncluded = false; for (ipAddress net : positiveIPv4Routes) { if (net.containsNet(dnsServer)) { dnsIncluded = true; } } if (!dnsIncluded) { String samsungwarning = String.format( "Warning Samsung Android 5.0+ devices ignore DNS servers outside the VPN range. To enable DNS add a custom route to your DNS Server (%s) or change to a DNS inside your VPN range", mDnslist.get(0)); VpnStatus.logWarning(samsungwarning); } } catch (Exception e) { VpnStatus.logError("Error parsing DNS Server IP: " + mDnslist.get(0)); } } if (mDomain != null) builder.addSearchDomain(mDomain); VpnStatus.logInfo(R.string.local_ip_info, mLocalIP.mIp, mLocalIP.len, mLocalIPv6, 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))); VpnStatus.logDebug( R.string.routes_debug, TextUtils.join(", ", positiveIPv4Routes), TextUtils.join(", ", positiveIPv6Routes)); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { setAllowedVpnPackages(builder); } 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); builder.setSession(session); // No DNS Server, log a warning if (mDnslist.size() == 0) VpnStatus.logInfo(R.string.warn_no_dns); mLastTunCfg = getTunConfigString(); // Reset information mDnslist.clear(); mRoutes.clear(); mRoutesv6.clear(); mLocalIP = null; mLocalIPv6 = null; mDomain = null; builder.setConfigureIntent(getLogPendingIntent()); try { // Debug.stopMethodTracing(); ParcelFileDescriptor tun = builder.establish(); if (tun == null) throw new NullPointerException( "Android establish() method returned null (Really broken network configuration?)"); return tun; } catch (Exception e) { VpnStatus.logError(R.string.tun_open_error); VpnStatus.logError(getString(R.string.error) + e.getLocalizedMessage()); if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR1) { VpnStatus.logError(R.string.tun_error_helpful); } return null; } }