Move OrbotVPNService to a Manager and consolidate services

This allows for the VPN service to be set in the foreground with the TorService
and reduce the chance to be killed due to lack of memory
This commit is contained in:
Nathan Freitas 2016-03-09 14:43:01 -05:00
parent 2973eaccd8
commit 9097b79a7e
5 changed files with 75 additions and 45 deletions

View File

@ -6,12 +6,15 @@
android:installLocation="auto" android:installLocation="auto"
> >
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="23"/> <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="23"/>
<!--
<permission android:name="org.torproject.android.MANAGE_TOR" <permission android:name="org.torproject.android.MANAGE_TOR"
android:label="@string/permission_manage_tor_label" android:label="@string/permission_manage_tor_label"
android:description="@string/permission_manage_tor_description" android:description="@string/permission_manage_tor_description"
android:protectionLevel="signature"/> android:protectionLevel="signature"/>
<uses-permission android:name="org.torproject.android.MANAGE_TOR"/> <uses-permission android:name="org.torproject.android.MANAGE_TOR"/>
-->
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
@ -88,7 +91,7 @@
<service <service
android:name=".service.TorService" android:name=".service.TorService"
android:enabled="true" android:enabled="true"
android:permission="org.torproject.android.MANAGE_TOR" android:permission="android.permission.BIND_VPN_SERVICE"
android:stopWithTask="false" > android:stopWithTask="false" >
</service> </service>
@ -118,13 +121,13 @@
</intent-filter> </intent-filter>
</receiver> </receiver>
<!--
<service android:name="org.torproject.android.vpn.OrbotVpnService" <service android:name="org.torproject.android.vpn.OrbotVpnService"
android:permission="android.permission.BIND_VPN_SERVICE"> android:permission="android.permission.BIND_VPN_SERVICE">
<intent-filter> <intent-filter>
<action android:name="android.net.VpnService"/> <action android:name="android.net.VpnService"/>
</intent-filter> </intent-filter>
</service> </service>
-->
</application> </application>
</manifest> </manifest>

2
external/Makefile vendored
View File

@ -83,6 +83,8 @@ ifeq ($(APP_ABI),armeabi)
CFLAGS += $(TARGET_thumb_release_CFLAGS) CFLAGS += $(TARGET_thumb_release_CFLAGS)
endif endif
.PHONY = clean showsetup \ .PHONY = clean showsetup \
assets assets-clean \ assets assets-clean \
openssl-static openssl-static-clean \ openssl-static openssl-static-clean \

View File

@ -2,7 +2,7 @@
<resources> <resources>
<string name="pdnsd_conf" formatted="false"> <string name="pdnsd_conf" formatted="false">
global { global {
perm_cache=1024; perm_cache=0;
cache_dir="/data/data/org.torproject.android/app_bin"; cache_dir="/data/data/org.torproject.android/app_bin";
server_port = 8091; server_port = 8091;
server_ip = 0.0.0.0; server_ip = 0.0.0.0;
@ -12,7 +12,7 @@ global {
timeout=10; timeout=10;
daemon=on; daemon=on;
pid_file="/data/data/org.torproject.android/app_bin/pdnsd.pid"; pid_file="/data/data/org.torproject.android/app_bin/pdnsd.pid";
} }
server { server {

View File

@ -23,6 +23,7 @@ import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor; import android.content.SharedPreferences.Editor;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.net.VpnService;
import android.os.Build; import android.os.Build;
import android.os.IBinder; import android.os.IBinder;
import android.os.RemoteException; import android.os.RemoteException;
@ -46,7 +47,7 @@ import org.torproject.android.Prefs;
import org.torproject.android.R; import org.torproject.android.R;
import org.torproject.android.settings.AppManager; import org.torproject.android.settings.AppManager;
import org.torproject.android.settings.TorifiedApp; import org.torproject.android.settings.TorifiedApp;
import org.torproject.android.vpn.OrbotVpnService; import org.torproject.android.vpn.OrbotVpnManager;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
@ -82,7 +83,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
public class TorService extends Service implements TorServiceConstants, OrbotConstants, EventHandler public class TorService extends VpnService implements TorServiceConstants, OrbotConstants, EventHandler
{ {
private String mCurrentStatus = STATUS_OFF; private String mCurrentStatus = STATUS_OFF;
@ -121,7 +122,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
private long lastWritten = -1; private long lastWritten = -1;
private NotificationManager mNotificationManager = null; private NotificationManager mNotificationManager = null;
private Builder mNotifyBuilder; private Notification.Builder mNotifyBuilder;
private Notification mNotification; private Notification mNotification;
private boolean mNotificationShowing = false; private boolean mNotificationShowing = false;
@ -130,6 +131,8 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
private ExecutorService mExecutor = Executors.newFixedThreadPool(1); private ExecutorService mExecutor = Executors.newFixedThreadPool(1);
private NumberFormat mNumberFormat = null; private NumberFormat mNumberFormat = null;
private OrbotVpnManager mVpnManager;
public void debug(String msg) public void debug(String msg)
{ {
@ -364,6 +367,15 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
unregisterReceiver(mNetworkStateReceiver); unregisterReceiver(mNetworkStateReceiver);
super.onDestroy(); super.onDestroy();
} }
@Override
public void onRevoke ()
{
if (mVpnManager != null)
mVpnManager.onRevoke();
super.onRevoke();
}
private void stopTor() { private void stopTor() {
Log.i("TorService", "stopTor"); Log.i("TorService", "stopTor");
@ -744,7 +756,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
if (Prefs.bridgesEnabled()) if (Prefs.bridgesEnabled())
if (Prefs.useVpn() && !mIsLollipop) if (Prefs.useVpn() && !mIsLollipop)
{ {
customEnv.add("TOR_PT_PROXY=socks5://" + OrbotVpnService.sSocksProxyLocalhost + ":" + OrbotVpnService.sSocksProxyServerPort); customEnv.add("TOR_PT_PROXY=socks5://" + OrbotVpnManager.sSocksProxyLocalhost + ":" + OrbotVpnManager.sSocksProxyServerPort);
} }
String baseDirectory = OrbotApp.fileTor.getParent(); String baseDirectory = OrbotApp.fileTor.getParent();
@ -1190,12 +1202,14 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
updateConfiguration("DNSPort",TOR_VPN_DNS_LISTEN_ADDRESS + ":" + TorServiceConstants.TOR_DNS_PORT_DEFAULT,false); updateConfiguration("DNSPort",TOR_VPN_DNS_LISTEN_ADDRESS + ":" + TorServiceConstants.TOR_DNS_PORT_DEFAULT,false);
Intent intent = new Intent(TorService.this, OrbotVpnService.class); if (mVpnManager == null)
intent.setAction("start"); mVpnManager = new OrbotVpnManager (this);
Intent intent = new Intent();
intent.setAction("start");
intent.putExtra("torSocks", mPortSOCKS); intent.putExtra("torSocks", mPortSOCKS);
startService(intent); mVpnManager.handleIntent(new Builder(),intent);
} }
@ -1205,9 +1219,14 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
Prefs.putUseVpn(false); Prefs.putUseVpn(false);
processTransparentProxying(); processTransparentProxying();
Intent intent = new Intent(TorService.this, OrbotVpnService.class); if (mVpnManager != null)
intent.setAction("stop"); {
startService(intent); Intent intent = new Intent();
intent.setAction("stop");
mVpnManager.handleIntent(new Builder(), intent);
mVpnManager = null;
}
} }
@Override @Override
@ -1851,7 +1870,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
if (!mIsLollipop) if (!mIsLollipop)
{ {
String proxyType = "socks5"; String proxyType = "socks5";
extraLines.append(proxyType + "Proxy" + ' ' + OrbotVpnService.sSocksProxyLocalhost + ':' + OrbotVpnService.sSocksProxyServerPort).append('\n'); extraLines.append(proxyType + "Proxy" + ' ' + OrbotVpnManager.sSocksProxyLocalhost + ':' + OrbotVpnManager.sSocksProxyServerPort).append('\n');
}; };
} }

View File

@ -31,6 +31,7 @@ import org.sufficientlysecure.rootcommands.Shell;
import org.sufficientlysecure.rootcommands.command.SimpleCommand; import org.sufficientlysecure.rootcommands.command.SimpleCommand;
import org.torproject.android.OrbotApp; import org.torproject.android.OrbotApp;
import org.torproject.android.R; import org.torproject.android.R;
import org.torproject.android.service.TorService;
import org.torproject.android.service.TorServiceConstants; import org.torproject.android.service.TorServiceConstants;
import org.torproject.android.service.TorServiceUtils; import org.torproject.android.service.TorServiceUtils;
import org.torproject.android.settings.AppManager; import org.torproject.android.settings.AppManager;
@ -38,11 +39,13 @@ import org.torproject.android.settings.TorifiedApp;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.Service;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.NameNotFoundException;
import android.net.VpnService; import android.net.VpnService;
import android.net.VpnService.Builder;
import android.os.Build; import android.os.Build;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
@ -55,12 +58,11 @@ import com.runjva.sourceforge.jsocks.server.ServerAuthenticatorNone;
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public class OrbotVpnService extends VpnService implements Handler.Callback { public class OrbotVpnManager implements Handler.Callback {
private static final String TAG = "OrbotVpnService"; private static final String TAG = "OrbotVpnService";
private PendingIntent mConfigureIntent; private PendingIntent mConfigureIntent;
private Handler mHandler;
private Thread mThreadVPN; private Thread mThreadVPN;
private String mSessionName = "OrbotVPN"; private String mSessionName = "OrbotVPN";
@ -83,13 +85,20 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
private boolean isRestart = false; private boolean isRestart = false;
private TorService mService;
static{ static{
System.loadLibrary("tun2socks"); System.loadLibrary("tun2socks");
} }
@Override public OrbotVpnManager (TorService service)
public int onStartCommand(Intent intent, int flags, int startId) { {
mService = service;
}
//public int onStartCommand(Intent intent, int flags, int startId) {
public int handleIntent(Builder builder, Intent intent) {
if (intent != null) if (intent != null)
{ {
@ -105,18 +114,13 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
mTorSocks = intent.getIntExtra("torSocks", TorServiceConstants.SOCKS_PROXY_PORT_DEFAULT); mTorSocks = intent.getIntExtra("torSocks", TorServiceConstants.SOCKS_PROXY_PORT_DEFAULT);
// The handler is only used to show messages.
if (mHandler == null) {
mHandler = new Handler(this);
}
if (!mIsLollipop) if (!mIsLollipop)
{ {
startSocksBypass(); startSocksBypass();
} }
setupTun2Socks(); setupTun2Socks(builder);
} }
} }
else if (action.equals("stop")) else if (action.equals("stop"))
@ -124,8 +128,8 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
Log.d(TAG,"stop OrbotVPNService service!"); Log.d(TAG,"stop OrbotVPNService service!");
stopVPN(); stopVPN();
if (mHandler != null) //if (mHandler != null)
mHandler.postDelayed(new Runnable () { public void run () { stopSelf(); }}, 1000); //mHandler.postDelayed(new Runnable () { public void run () { stopSelf(); }}, 1000);
} }
else if (action.equals("refresh")) else if (action.equals("refresh"))
{ {
@ -135,12 +139,12 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
startSocksBypass(); startSocksBypass();
if (!isRestart) if (!isRestart)
setupTun2Socks(); setupTun2Socks(builder);
} }
} }
return START_STICKY; return Service.START_STICKY;
} }
private void startSocksBypass() private void startSocksBypass()
@ -177,7 +181,7 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
try try
{ {
mSocksProxyServer = new ProxyServer(new ServerAuthenticatorNone(null, null)); mSocksProxyServer = new ProxyServer(new ServerAuthenticatorNone(null, null));
ProxyServer.setVpnService(OrbotVpnService.this); ProxyServer.setVpnService(mService);
mSocksProxyServer.start(sSocksProxyServerPort, 5, InetAddress.getLocalHost()); mSocksProxyServer.start(sSocksProxyServerPort, 5, InetAddress.getLocalHost());
} }
@ -201,6 +205,7 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
} }
/**
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
@ -218,7 +223,7 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
@Override @Override
public void onDestroy() { public void onDestroy() {
stopVPN(); stopVPN();
} }*/
private void stopVPN () private void stopVPN ()
{ {
@ -260,13 +265,13 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
@Override @Override
public boolean handleMessage(Message message) { public boolean handleMessage(Message message) {
if (message != null) { if (message != null) {
Toast.makeText(this, message.what, Toast.LENGTH_SHORT).show(); Toast.makeText(mService, message.what, Toast.LENGTH_SHORT).show();
} }
return true; return true;
} }
private synchronized void setupTun2Socks() { private synchronized void setupTun2Socks(final Builder builder) {
if (mInterface != null) //stop tun2socks now to give it time to clean up if (mInterface != null) //stop tun2socks now to give it time to clean up
@ -289,7 +294,7 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
Thread.sleep(3000); Thread.sleep(3000);
} }
//start PDNSD daemon pointing to OpenDNS //start PDNSD daemon pointing to actual DNS
startDNS(DEFAULT_ACTUAL_DNS_HOST,DEFAULT_ACTUAL_DNS_PORT); startDNS(DEFAULT_ACTUAL_DNS_HOST,DEFAULT_ACTUAL_DNS_PORT);
final String vpnName = "OrbotVPN"; final String vpnName = "OrbotVPN";
@ -305,10 +310,8 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
+ String.valueOf(mTorSocks); + String.valueOf(mTorSocks);
final String localDNS = virtualGateway + ':' + "8091";//String.valueOf(TorServiceConstants.TOR_DNS_PORT_DEFAULT); final String localDNS = virtualGateway + ':' + "8091";//String.valueOf(TorServiceConstants.TOR_DNS_PORT_DEFAULT);
final boolean localDnsTransparentProxy = true; final boolean localDnsTransparentProxy = true;
Builder builder = new Builder();
builder.setMtu(VPN_MTU); builder.setMtu(VPN_MTU);
builder.addAddress(virtualGateway,32); builder.addAddress(virtualGateway,32);
@ -355,6 +358,7 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
}; };
mThreadVPN.start(); mThreadVPN.start();
} }
@ -362,13 +366,13 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
private void doLollipopAppRouting (Builder builder) throws NameNotFoundException private void doLollipopAppRouting (Builder builder) throws NameNotFoundException
{ {
ArrayList<TorifiedApp> apps = AppManager.getApps(this, TorServiceUtils.getSharedPrefs(getApplicationContext())); ArrayList<TorifiedApp> apps = AppManager.getApps(mService, TorServiceUtils.getSharedPrefs(mService.getApplicationContext()));
boolean perAppEnabled = false; boolean perAppEnabled = false;
for (TorifiedApp app : apps) for (TorifiedApp app : apps)
{ {
if (app.isTorified() && (!app.getPackageName().equals(getPackageName()))) if (app.isTorified() && (!app.getPackageName().equals(mService.getPackageName())))
{ {
builder.addAllowedApplication(app.getPackageName()); builder.addAllowedApplication(app.getPackageName());
perAppEnabled = true; perAppEnabled = true;
@ -377,30 +381,32 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
} }
if (!perAppEnabled) if (!perAppEnabled)
builder.addDisallowedApplication(getPackageName()); builder.addDisallowedApplication(mService.getPackageName());
} }
@Override
public void onRevoke() { public void onRevoke() {
Log.w(TAG,"VPNService REVOKED!"); Log.w(TAG,"VPNService REVOKED!");
if (!isRestart) if (!isRestart)
{ {
SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); SharedPreferences prefs = TorServiceUtils.getSharedPrefs(mService.getApplicationContext());
prefs.edit().putBoolean("pref_vpn", false).commit(); prefs.edit().putBoolean("pref_vpn", false).commit();
stopVPN(); stopVPN();
} }
isRestart = false; isRestart = false;
super.onRevoke(); //super.onRevoke();
} }
private void startDNS (String dns, int port) throws IOException, TimeoutException private void startDNS (String dns, int port) throws IOException, TimeoutException
{ {
makePdnsdConf(this, dns, port,OrbotApp.filePdnsd.getParentFile() ); makePdnsdConf(mService, dns, port,OrbotApp.filePdnsd.getParentFile() );
ArrayList<String> customEnv = new ArrayList<String>(); ArrayList<String> customEnv = new ArrayList<String>();
String baseDirectory = OrbotApp.filePdnsd.getParent(); String baseDirectory = OrbotApp.filePdnsd.getParent();