commit 9ff0b00cb26b0f4c09e9420ad4d992fa7de26c82 Author: n8fr8 nathan@guardianproject.info Date: Tue Jul 9 14:28:11 2019 -0400
fix VPN code to support dynamic DNS port for Tor --- .../org/torproject/android/service/TorService.java | 55 +++---- .../android/service/TorServiceConstants.java | 3 + .../android/service/vpn/OrbotVpnManager.java | 180 +++++++++++---------- .../android/service/vpn/TorVpnService.java | 42 +++++ .../torproject/android/service/vpn/VpnUtils.java | 26 ++- orbotservice/src/main/res/values/pdnsd.xml | 4 +- 6 files changed, 180 insertions(+), 130 deletions(-)
diff --git a/orbotservice/src/main/java/org/torproject/android/service/TorService.java b/orbotservice/src/main/java/org/torproject/android/service/TorService.java index be1e18e2..c83c252e 100644 --- a/orbotservice/src/main/java/org/torproject/android/service/TorService.java +++ b/orbotservice/src/main/java/org/torproject/android/service/TorService.java @@ -811,11 +811,8 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon reply.setPackage(packageName); sendBroadcast(reply); } - else - { - LocalBroadcastManager.getInstance(this).sendBroadcast(reply);
- } + LocalBroadcastManager.getInstance(this).sendBroadcast(reply);
}
@@ -1105,21 +1102,22 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
String confDns = conn.getInfo("net/listeners/dns"); st = new StringTokenizer(confDns," "); - - confDns = st.nextToken().split(":")[1]; - confDns = confDns.substring(0,confDns.length()-1); - mPortDns = Integer.parseInt(confDns); - getSharedPrefs(getApplicationContext()).edit().putInt(VpnPrefs.PREFS_DNS_PORT, mPortDns).apply(); - + if (st.hasMoreTokens()) { + confDns = st.nextToken().split(":")[1]; + confDns = confDns.substring(0, confDns.length() - 1); + mPortDns = Integer.parseInt(confDns); + getSharedPrefs(getApplicationContext()).edit().putInt(VpnPrefs.PREFS_DNS_PORT, mPortDns).apply(); + }
String confTrans = conn.getInfo("net/listeners/trans"); st = new StringTokenizer(confTrans," "); + if (st.hasMoreTokens()) { + confTrans = st.nextToken().split(":")[1]; + confTrans = confTrans.substring(0, confTrans.length() - 1); + mPortTrans = Integer.parseInt(confTrans); + }
- confTrans = st.nextToken().split(":")[1]; - confTrans = confDns.substring(0,confTrans.length()-1); - mPortTrans = Integer.parseInt(confTrans); - - sendCallbackPorts(mPortSOCKS, mPortHTTP); + sendCallbackPorts(mPortSOCKS, mPortHTTP, mPortDns, mPortTrans);
return Integer.parseInt(torProcId);
@@ -1434,13 +1432,15 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
}
- private void sendCallbackPorts (int socksPort, int httpPort) + private void sendCallbackPorts (int socksPort, int httpPort, int dnsPort, int transPort) {
Intent intent = new Intent(LOCAL_ACTION_PORTS); // You can also include some extra data. - intent.putExtra("socks",socksPort); - intent.putExtra("http",httpPort); + intent.putExtra(EXTRA_SOCKS_PROXY_PORT,socksPort); + intent.putExtra(EXTRA_HTTP_PROXY_PORT,httpPort); + intent.putExtra(EXTRA_DNS_PORT,dnsPort); + intent.putExtra(EXTRA_TRANS_PORT,transPort);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
@@ -1970,21 +1970,10 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
private void startVPNService () { - if (mPortSOCKS != -1) { - Intent intentVpn = new Intent(this, TorVpnService.class); - intentVpn.setAction("start"); - intentVpn.putExtra("torSocks", mPortSOCKS); - startService(intentVpn); - } - else - { - mHandler.postDelayed(new Runnable() { - public void run () - { - startVPNService(); - } - },5000); - } + Intent intentVpn = new Intent(this, TorVpnService.class); + intentVpn.setAction("start"); + startService(intentVpn); + }
diff --git a/orbotservice/src/main/java/org/torproject/android/service/TorServiceConstants.java b/orbotservice/src/main/java/org/torproject/android/service/TorServiceConstants.java index 8fd9eeca..b805cd6a 100644 --- a/orbotservice/src/main/java/org/torproject/android/service/TorServiceConstants.java +++ b/orbotservice/src/main/java/org/torproject/android/service/TorServiceConstants.java @@ -65,6 +65,9 @@ public interface TorServiceConstants { String EXTRA_HTTP_PROXY_HOST = "org.torproject.android.intent.extra.HTTP_PROXY_HOST"; String EXTRA_HTTP_PROXY_PORT = "org.torproject.android.intent.extra.HTTP_PROXY_PORT";
+ String EXTRA_DNS_PORT = "org.torproject.android.intent.extra.DNS_PORT"; + String EXTRA_TRANS_PORT = "org.torproject.android.intent.extra.TRANS_PORT"; + String LOCAL_ACTION_LOG = "log"; String LOCAL_ACTION_BANDWIDTH = "bandwidth"; String LOCAL_EXTRA_LOG = "log"; diff --git a/orbotservice/src/main/java/org/torproject/android/service/vpn/OrbotVpnManager.java b/orbotservice/src/main/java/org/torproject/android/service/vpn/OrbotVpnManager.java index 7233159f..cf9b8b71 100644 --- a/orbotservice/src/main/java/org/torproject/android/service/vpn/OrbotVpnManager.java +++ b/orbotservice/src/main/java/org/torproject/android/service/vpn/OrbotVpnManager.java @@ -19,8 +19,10 @@ package org.torproject.android.service.vpn; import android.annotation.TargetApi; import android.app.PendingIntent; import android.app.Service; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.PackageManager.NameNotFoundException; import android.net.VpnService; @@ -29,6 +31,7 @@ import android.os.Build; import android.os.Handler; import android.os.Message; import android.os.ParcelFileDescriptor; +import android.support.v4.content.LocalBroadcastManager; import android.util.Log; import android.widget.Toast;
@@ -36,12 +39,15 @@ import com.runjva.sourceforge.jsocks.protocol.ProxyServer; import com.runjva.sourceforge.jsocks.server.ServerAuthenticatorNone;
import org.torproject.android.service.R; +import org.torproject.android.service.TorService; +import org.torproject.android.service.TorServiceConstants; import org.torproject.android.service.util.CustomNativeLoader;
import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; @@ -63,30 +69,25 @@ public class OrbotVpnManager implements Handler.Callback { private ParcelFileDescriptor mInterface;
private int mTorSocks = -1; + private int mTorDns = -1;
- public static int sSocksProxyServerPort = -1; + public static int sSocksProxyServerPort = -1; public static String sSocksProxyLocalhost = null; private ProxyServer mSocksProxyServer;
private final static int VPN_MTU = 1500;
private final static boolean mIsLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; - - //this is the actual DNS server we talk to over UDP or TCP (now using Tor's DNS port) - //private final static String DEFAULT_ACTUAL_DNS_HOST = "127.0.0.1"; - //private final static int DEFAULT_ACTUAL_DNS_PORT = TorServiceConstants.TOR_DNS_PORT_DEFAULT; -
- - File filePdnsd = null; + private File filePdnsd = null;
private final static String PDNSD_BIN = "pdnsd"; - private final static int PDNSD_PORT = 8091;
private boolean isRestart = false;
private VpnService mService;
+ private Builder mLastBuilder;
public OrbotVpnManager (VpnService service) throws IOException, TimeoutException { mService = service; @@ -96,6 +97,7 @@ public class OrbotVpnManager implements Handler.Callback {
Tun2Socks.init();
+ }
//public int onStartCommand(Intent intent, int flags, int startId) { @@ -107,40 +109,45 @@ public class OrbotVpnManager implements Handler.Callback { if (action.equals("start")) { - // Stop the previous session by interrupting the thread. - if (mThreadVPN == null || (!mThreadVPN.isAlive())) - { - Log.d(TAG,"starting OrbotVPNService service!"); - - mTorSocks = intent.getIntExtra("torSocks", -1); - - if (!mIsLollipop) - { - startSocksBypass(); - } - - setupTun2Socks(builder); - } + if (mThreadVPN != null && mThreadVPN.isAlive()) + stopVPN(); + + mLastBuilder = builder; + + if (mTorSocks != -1) + { + if (!mIsLollipop) + { + startSocksBypass(); + } + + setupTun2Socks(builder); + } + + } else if (action.equals("stop")) { Log.d(TAG,"stop OrbotVPNService service!"); - stopVPN(); - //if (mHandler != null) - //mHandler.postDelayed(new Runnable () { public void run () { stopSelf(); }}, 1000); - } - else if (action.equals("refresh")) - { - Log.d(TAG,"refresh OrbotVPNService service!"); - - if (!mIsLollipop) - startSocksBypass(); - - if (!isRestart) - setupTun2Socks(builder); + stopVPN(); } + else if (action.equals(TorServiceConstants.LOCAL_ACTION_PORTS)) + { + Log.d(TAG,"starting OrbotVPNService service!"); + + mTorSocks = intent.getIntExtra(TorService.EXTRA_SOCKS_PROXY_PORT,-1); + mTorDns = intent.getIntExtra(TorService.EXTRA_DNS_PORT,-1); + + if (!mIsLollipop) + { + startSocksBypass(); + } + + setupTun2Socks(builder); + } + }
@@ -204,27 +211,7 @@ public class OrbotVpnManager implements Handler.Callback {
} - - /** - @Override - public void onCreate() { - super.onCreate(); - - // Set the locale to English (or probably any other language that^M - // uses Hindu-Arabic (aka Latin) numerals).^M - // We have found that VpnService.Builder does something locale-dependent^M - // internally that causes errors when the locale uses its own numerals^M - // (i.e., Farsi and Arabic).^M - Locale.setDefault(new Locale("en")); - - } -
- @Override - public void onDestroy() { - stopVPN(); - }*/ - private void stopVPN () { if (mIsLollipop) @@ -248,15 +235,11 @@ public class OrbotVpnManager implements Handler.Callback { Log.d(TAG,"error stopping tun2socks",e); } } + + stopDns();
Tun2Socks.Stop(); - - try { - killProcess(filePdnsd); - } catch (Exception e) { - e.printStackTrace(); - } - + mThreadVPN = null;
@@ -278,10 +261,11 @@ public class OrbotVpnManager implements Handler.Callback { { isRestart = true; Tun2Socks.Stop(); + + stopDns(); + }
- final int localDns = getSharedPrefs(this.mService.getApplicationContext()).getInt(VpnPrefs.PREFS_DNS_PORT, 0); - mThreadVPN = new Thread () { @@ -306,23 +290,20 @@ public class OrbotVpnManager implements Handler.Callback { final String defaultRoute = "0.0.0.0"; final String localSocks = localhost + ':' + mTorSocks; - - final String localDNS = virtualGateway + ':' + PDNSD_PORT;
- final boolean localDnsTransparentProxy = true; - - builder.setMtu(VPN_MTU); + builder.setMtu(VPN_MTU); builder.addAddress(virtualGateway,32); - builder.setSession(vpnName); + builder.setSession(vpnName); + + //route all traffic through VPN (we might offer country specific exclude lists in the future) + builder.addRoute(defaultRoute,0);
builder.addDnsServer(dummyDNS); builder.addRoute(dummyDNS,32); - - //route all traffic through VPN (we might offer country specific exclude lists in the future) - builder.addRoute(defaultRoute,0); - - //handle ipv6 + + + //handle ipv6 //builder.addAddress("fdfe:dcba:9876::1", 126); //builder.addRoute("::", 0); @@ -346,9 +327,11 @@ public class OrbotVpnManager implements Handler.Callback { isRestart = false;
//start PDNSD daemon pointing to actual DNS - startDNS(filePdnsd.getCanonicalPath(), "127.0.0.1",localDns); + int pdnsdPort = 8091; + startDNS(filePdnsd.getCanonicalPath(), localhost,mTorDns, "0.0.0.0", pdnsdPort); + final boolean localDnsTransparentProxy = true;
- Tun2Socks.Start(mInterface, VPN_MTU, virtualIP, virtualNetMask, localSocks , localDNS , localDnsTransparentProxy); + Tun2Socks.Start(mInterface, VPN_MTU, virtualIP, virtualNetMask, localSocks , virtualGateway + ":" + pdnsdPort , localDnsTransparentProxy);
} @@ -406,13 +389,10 @@ public class OrbotVpnManager implements Handler.Callback {
}
- - private void startDNS (String pdnsPath, String dns, int port) throws IOException, TimeoutException + private void startDNS (String pdnsPath, String torDnsHost, int torDnsPort, String pdnsdHost, int pdnsdPort) throws IOException, TimeoutException {
- File fileConf = makePdnsdConf(mService, dns, port,mService.getFilesDir()); - - // ArrayList<String> customEnv = new ArrayList<String>(); + File fileConf = makePdnsdConf(mService, mService.getFilesDir(), torDnsHost, torDnsPort, pdnsdHost, pdnsdPort);
String[] cmdString = {pdnsPath,"-c",fileConf.toString()}; ProcessBuilder pb = new ProcessBuilder(cmdString); @@ -424,21 +404,46 @@ public class OrbotVpnManager implements Handler.Callback {
if (proc.exitValue() != 0) { - BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = null; while ((line = br.readLine ()) != null) { Log.d(TAG,"pdnsd: " + line); } - }
} + + private boolean stopDns () + { + File filePid = new File(mService.getFilesDir(),"pdnsd.pid"); + String pid = null; + + if (filePid.exists()) + { + + try { + BufferedReader reader = new BufferedReader(new FileReader(filePid)); + pid = reader.readLine().trim(); + + VpnUtils.killProcess(pid,"-9"); + filePid.delete(); + return true; + + } catch (Exception e) { + Log.e(TAG,"error killing DNS Process: " + pid,e); + } + } + + return false; + + }
- public static File makePdnsdConf(Context context, String dns, int port, File fileDir) throws FileNotFoundException, IOException { - String conf = String.format(context.getString(R.string.pdnsd_conf), dns, port, fileDir.getCanonicalPath()); + public static File makePdnsdConf(Context context, File fileDir, String torDnsHost, int torDnsPort, String pdnsdHost, int pdnsdPort) throws FileNotFoundException, IOException { + String conf = String.format(context.getString(R.string.pdnsd_conf), torDnsHost, torDnsPort, fileDir.getCanonicalPath(), pdnsdHost, pdnsdPort); + + Log.d(TAG,"pdsnd conf:" + conf);
File f = new File(fileDir,"pdnsd.conf");
@@ -464,5 +469,6 @@ public class OrbotVpnManager implements Handler.Callback { return f; }
+
} diff --git a/orbotservice/src/main/java/org/torproject/android/service/vpn/TorVpnService.java b/orbotservice/src/main/java/org/torproject/android/service/vpn/TorVpnService.java index b02fd71a..e70753f6 100644 --- a/orbotservice/src/main/java/org/torproject/android/service/vpn/TorVpnService.java +++ b/orbotservice/src/main/java/org/torproject/android/service/vpn/TorVpnService.java @@ -1,8 +1,15 @@ package org.torproject.android.service.vpn;
import android.app.Service; +import android.content.BroadcastReceiver; +import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.net.VpnService; +import android.support.v4.content.LocalBroadcastManager; + +import org.torproject.android.service.TorService; +import org.torproject.android.service.TorServiceConstants;
import java.io.IOException; import java.util.concurrent.TimeoutException; @@ -23,6 +30,10 @@ public class TorVpnService extends VpnService { } catch (TimeoutException e) { e.printStackTrace(); } + + LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this); + lbm.registerReceiver(mLocalBroadcastReceiver, + new IntentFilter(TorServiceConstants.LOCAL_ACTION_PORTS)); }
/* (non-Javadoc) @@ -34,4 +45,35 @@ public class TorVpnService extends VpnService {
return Service.START_STICKY; } + + @Override + public void onDestroy() { + super.onDestroy(); + + LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this); + lbm.unregisterReceiver(mLocalBroadcastReceiver); + } + + /** + * The state and log info from {@link TorService} are sent to the UI here in + * the form of a local broadcast. Regular broadcasts can be sent by any app, + * so local ones are used here so other apps cannot interfere with Orbot's + * operation. + */ + private BroadcastReceiver mLocalBroadcastReceiver = new BroadcastReceiver() { + + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action == null) + return; + + if (action.equals(TorServiceConstants.LOCAL_ACTION_PORTS)) { + + mVpnManager.handleIntent(new Builder(),intent); + } + } + }; + + } diff --git a/orbotservice/src/main/java/org/torproject/android/service/vpn/VpnUtils.java b/orbotservice/src/main/java/org/torproject/android/service/vpn/VpnUtils.java index ce862b04..5a9901ff 100644 --- a/orbotservice/src/main/java/org/torproject/android/service/vpn/VpnUtils.java +++ b/orbotservice/src/main/java/org/torproject/android/service/vpn/VpnUtils.java @@ -58,6 +58,22 @@ public class VpnUtils { ()); } catch (IOException ioe) { } + killProcess(pidString, signal); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // ignored + } + + if (killAttempts > 4) + throw new Exception("Cannot kill: " + fileProcBin.getAbsolutePath()); + } + } + + public static void killProcess(String pidString, String signal) throws Exception { + + try { getRuntime().exec("toolbox kill " + signal + " " + pidString); } catch (IOException ioe) { @@ -71,14 +87,8 @@ public class VpnUtils { } catch (IOException ioe) { }
- try { - Thread.sleep(1000); - } catch (InterruptedException e) { - // ignored - }
- if (killAttempts > 4) - throw new Exception("Cannot kill: " + fileProcBin.getAbsolutePath()); - } + + } } diff --git a/orbotservice/src/main/res/values/pdnsd.xml b/orbotservice/src/main/res/values/pdnsd.xml index 89122ebc..ce4609bc 100644 --- a/orbotservice/src/main/res/values/pdnsd.xml +++ b/orbotservice/src/main/res/values/pdnsd.xml @@ -4,8 +4,8 @@ global { perm_cache=0; cache_dir="%3$s"; - server_port = 8091; - server_ip = 192.168.200.1; + server_port = %5$d; + server_ip = %4$s; query_method=udp_only; min_ttl=1m; max_ttl=1w;