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();
  }
Exemple #2
0
  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;
    }
  }