2015-10-24 18:01:55 +00:00
|
|
|
package eu.faircode.netguard;
|
|
|
|
|
|
|
|
import android.app.PendingIntent;
|
|
|
|
import android.content.BroadcastReceiver;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.IntentFilter;
|
2015-10-25 09:29:49 +00:00
|
|
|
import android.content.SharedPreferences;
|
2015-10-25 15:16:20 +00:00
|
|
|
import android.content.pm.PackageManager;
|
2015-10-24 18:01:55 +00:00
|
|
|
import android.net.ConnectivityManager;
|
|
|
|
import android.net.VpnService;
|
|
|
|
import android.os.ParcelFileDescriptor;
|
2015-10-24 19:50:29 +00:00
|
|
|
import android.preference.PreferenceManager;
|
2015-10-24 18:01:55 +00:00
|
|
|
import android.util.Log;
|
2015-10-25 18:02:33 +00:00
|
|
|
import android.widget.Toast;
|
2015-10-24 18:01:55 +00:00
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
2015-10-25 15:16:20 +00:00
|
|
|
public class BlackHoleService extends VpnService {
|
|
|
|
private static final String TAG = "NetGuard.Service";
|
2015-10-24 18:01:55 +00:00
|
|
|
|
2015-10-25 15:16:20 +00:00
|
|
|
private ParcelFileDescriptor vpn = null;
|
2015-10-26 16:23:41 +00:00
|
|
|
private static final String EXTRA_COMMAND = "Command";
|
2015-10-24 18:01:55 +00:00
|
|
|
|
2015-10-26 16:23:41 +00:00
|
|
|
private enum Command {start, reload, stop}
|
2015-10-24 18:01:55 +00:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
2015-10-25 15:28:41 +00:00
|
|
|
// Get enabled
|
2015-10-25 09:29:49 +00:00
|
|
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
|
|
|
boolean enabled = prefs.getBoolean("enabled", false);
|
|
|
|
|
2015-10-25 15:28:41 +00:00
|
|
|
// Get command
|
2015-10-25 09:29:49 +00:00
|
|
|
Command cmd = (intent == null ? Command.start : (Command) intent.getSerializableExtra(EXTRA_COMMAND));
|
2015-10-25 15:16:20 +00:00
|
|
|
Log.i(TAG, "Start intent=" + intent + " command=" + cmd + " enabled=" + enabled + " vpn=" + (vpn != null));
|
2015-10-25 09:29:49 +00:00
|
|
|
|
2015-10-25 15:28:41 +00:00
|
|
|
// Process command
|
2015-10-26 13:32:14 +00:00
|
|
|
switch (cmd) {
|
|
|
|
case start:
|
|
|
|
if (enabled && vpn == null)
|
|
|
|
vpn = vpnStart();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case reload:
|
|
|
|
// Seamless handover
|
|
|
|
ParcelFileDescriptor prev = vpn;
|
|
|
|
if (enabled)
|
|
|
|
vpn = vpnStart();
|
|
|
|
if (prev != null)
|
|
|
|
vpnStop(prev);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case stop:
|
|
|
|
if (vpn != null) {
|
|
|
|
vpnStop(vpn);
|
|
|
|
vpn = null;
|
|
|
|
}
|
2015-10-25 09:29:49 +00:00
|
|
|
stopSelf();
|
2015-10-26 13:32:14 +00:00
|
|
|
break;
|
2015-10-24 18:01:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return START_STICKY;
|
|
|
|
}
|
|
|
|
|
2015-10-26 13:32:14 +00:00
|
|
|
private ParcelFileDescriptor vpnStart() {
|
2015-10-25 15:16:20 +00:00
|
|
|
Log.i(TAG, "Starting");
|
|
|
|
|
2015-10-25 15:28:41 +00:00
|
|
|
// Check if Wi-Fi
|
2015-10-25 16:12:25 +00:00
|
|
|
boolean wifi = Util.isWifiActive(this);
|
2015-10-25 15:16:20 +00:00
|
|
|
Log.i(TAG, "wifi=" + wifi);
|
|
|
|
|
|
|
|
// Build VPN service
|
|
|
|
final Builder builder = new Builder();
|
2015-10-25 15:28:41 +00:00
|
|
|
builder.setSession(getString(R.string.app_name));
|
2015-10-25 15:16:20 +00:00
|
|
|
builder.addAddress("10.1.10.1", 32);
|
2015-10-26 13:08:13 +00:00
|
|
|
builder.addAddress("fd00:1:fd00:1:fd00:1:fd00:1", 64);
|
2015-10-25 15:16:20 +00:00
|
|
|
builder.addRoute("0.0.0.0", 0);
|
2015-10-26 13:08:13 +00:00
|
|
|
builder.addRoute("0:0:0:0:0:0:0:0", 0);
|
2015-10-25 15:16:20 +00:00
|
|
|
|
|
|
|
// Add list of allowed applications
|
|
|
|
for (Rule rule : Rule.getRules(this))
|
|
|
|
if (!(wifi ? rule.wifi_blocked : rule.other_blocked)) {
|
|
|
|
Log.i(TAG, "Allowing " + rule.info.packageName);
|
|
|
|
try {
|
|
|
|
builder.addDisallowedApplication(rule.info.packageName);
|
2015-10-25 18:02:33 +00:00
|
|
|
} catch (PackageManager.NameNotFoundException ex) {
|
|
|
|
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
|
2015-10-25 15:16:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-25 15:28:41 +00:00
|
|
|
// Build configure intent
|
2015-10-25 15:16:20 +00:00
|
|
|
Intent configure = new Intent(this, ActivityMain.class);
|
|
|
|
PendingIntent pi = PendingIntent.getActivity(this, 0, configure, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
|
|
builder.setConfigureIntent(pi);
|
|
|
|
|
|
|
|
// Start VPN service
|
2015-10-25 18:02:33 +00:00
|
|
|
try {
|
2015-10-26 13:32:14 +00:00
|
|
|
return builder.establish();
|
2015-10-26 13:13:23 +00:00
|
|
|
|
2015-10-25 18:02:33 +00:00
|
|
|
} 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);
|
2015-10-26 13:32:14 +00:00
|
|
|
|
|
|
|
return null;
|
2015-10-25 18:02:33 +00:00
|
|
|
}
|
2015-10-25 15:16:20 +00:00
|
|
|
}
|
|
|
|
|
2015-10-26 13:32:14 +00:00
|
|
|
private void vpnStop(ParcelFileDescriptor pfd) {
|
2015-10-25 15:16:20 +00:00
|
|
|
Log.i(TAG, "Stopping");
|
|
|
|
try {
|
2015-10-26 13:32:14 +00:00
|
|
|
pfd.close();
|
2015-10-25 18:02:33 +00:00
|
|
|
} catch (IOException ex) {
|
|
|
|
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
|
2015-10-25 15:16:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-24 18:01:55 +00:00
|
|
|
private BroadcastReceiver connectivityChangedReceiver = new BroadcastReceiver() {
|
|
|
|
@Override
|
|
|
|
public void onReceive(Context context, Intent intent) {
|
2015-10-25 09:29:49 +00:00
|
|
|
Log.i(TAG, "Received " + intent);
|
|
|
|
Util.logExtras(TAG, intent);
|
|
|
|
if (intent.hasExtra(ConnectivityManager.EXTRA_NETWORK_TYPE) &&
|
2015-10-25 22:31:00 +00:00
|
|
|
intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_DUMMY) == ConnectivityManager.TYPE_WIFI)
|
|
|
|
reload(null, BlackHoleService.this);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
private BroadcastReceiver packageAddedReceiver = new BroadcastReceiver() {
|
|
|
|
@Override
|
|
|
|
public void onReceive(Context context, Intent intent) {
|
|
|
|
Log.i(TAG, "Received " + intent);
|
2015-10-26 12:19:52 +00:00
|
|
|
Util.logExtras(TAG, intent);
|
2015-10-25 22:31:00 +00:00
|
|
|
reload(null, BlackHoleService.this);
|
2015-10-24 18:01:55 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onCreate() {
|
|
|
|
super.onCreate();
|
2015-10-24 19:50:29 +00:00
|
|
|
Log.i(TAG, "Create");
|
2015-10-25 15:28:41 +00:00
|
|
|
|
2015-10-26 16:32:03 +00:00
|
|
|
// Listen for connectivity updates
|
2015-10-25 22:31:00 +00:00
|
|
|
IntentFilter ifConnectivity = new IntentFilter();
|
|
|
|
ifConnectivity.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
|
|
|
registerReceiver(connectivityChangedReceiver, ifConnectivity);
|
|
|
|
|
|
|
|
// Listen for added applications
|
|
|
|
IntentFilter ifPackage = new IntentFilter();
|
|
|
|
ifPackage.addAction(Intent.ACTION_PACKAGE_ADDED);
|
|
|
|
ifPackage.addDataScheme("package");
|
|
|
|
registerReceiver(packageAddedReceiver, ifPackage);
|
2015-10-24 18:01:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onDestroy() {
|
|
|
|
Log.i(TAG, "Destroy");
|
2015-10-25 15:28:41 +00:00
|
|
|
|
2015-10-26 13:32:14 +00:00
|
|
|
if (vpn != null) {
|
|
|
|
vpnStop(vpn);
|
|
|
|
vpn = null;
|
|
|
|
}
|
2015-10-25 15:28:41 +00:00
|
|
|
|
2015-10-24 18:01:55 +00:00
|
|
|
unregisterReceiver(connectivityChangedReceiver);
|
2015-10-25 22:31:00 +00:00
|
|
|
unregisterReceiver(packageAddedReceiver);
|
2015-10-25 15:28:41 +00:00
|
|
|
|
2015-10-24 18:01:55 +00:00
|
|
|
super.onDestroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onRevoke() {
|
|
|
|
Log.i(TAG, "Revoke");
|
2015-10-25 15:28:41 +00:00
|
|
|
|
2015-10-26 13:32:14 +00:00
|
|
|
if (vpn != null) {
|
|
|
|
vpnStop(vpn);
|
|
|
|
vpn = null;
|
|
|
|
}
|
2015-10-25 15:28:41 +00:00
|
|
|
|
|
|
|
// Disable firewall
|
2015-10-25 09:29:49 +00:00
|
|
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
|
|
|
prefs.edit().putBoolean("enabled", false).apply();
|
2015-10-25 15:28:41 +00:00
|
|
|
|
2015-10-24 18:01:55 +00:00
|
|
|
super.onRevoke();
|
|
|
|
}
|
2015-10-25 22:04:10 +00:00
|
|
|
|
2015-10-26 16:23:41 +00:00
|
|
|
public static void start(Context context) {
|
|
|
|
Intent intent = new Intent(context, BlackHoleService.class);
|
|
|
|
intent.putExtra(EXTRA_COMMAND, Command.start);
|
|
|
|
context.startService(intent);
|
|
|
|
}
|
|
|
|
|
2015-10-26 16:32:03 +00:00
|
|
|
public static void reload(String network, Context context) {
|
|
|
|
if (network == null || ("wifi".equals(network) ? Util.isWifiActive(context) : !Util.isWifiActive(context))) {
|
2015-10-25 22:04:10 +00:00
|
|
|
Intent intent = new Intent(context, BlackHoleService.class);
|
|
|
|
intent.putExtra(EXTRA_COMMAND, Command.reload);
|
|
|
|
context.startService(intent);
|
|
|
|
}
|
|
|
|
}
|
2015-10-26 16:23:41 +00:00
|
|
|
|
|
|
|
public static void stop(Context context) {
|
|
|
|
Intent intent = new Intent(context, BlackHoleService.class);
|
|
|
|
intent.putExtra(EXTRA_COMMAND, Command.stop);
|
|
|
|
context.startService(intent);
|
|
|
|
}
|
2015-10-24 18:01:55 +00:00
|
|
|
}
|