commit 6d05e27793fd1180e20fd705b50688165a240ea2
Author: Nathan Freitas <nathan(a)freitas.net>
Date: Tue Mar 17 13:04:20 2015 -0400
Improve Bridge and VPN support, working in tandem
You can use Bridges with VPN "App Mode" proxying
On Pre-Lollipop this uses a local loop back SOCKS server to flag outbound sockets as not for the VPN network
On Lollipop+ this uses the "disallow app" feature to set anything in the Orbot process to not be sent through the VPN
---
res/layout/layout_main.xml | 20 +++--
res/values/strings.xml | 2 +-
res/xml/preferences.xml | 2 +-
src/org/torproject/android/service/TorService.java | 93 +++++++++-----------
.../android/service/TorServiceConstants.java | 2 +-
.../torproject/android/vpn/OrbotVpnService.java | 50 +++++------
6 files changed, 81 insertions(+), 88 deletions(-)
diff --git a/res/layout/layout_main.xml b/res/layout/layout_main.xml
index 2576b27..a3f0a97 100644
--- a/res/layout/layout_main.xml
+++ b/res/layout/layout_main.xml
@@ -174,15 +174,6 @@
android:layout_margin="3dp"
/>
- <ToggleButton
- android:id="@+id/btnBridges"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textOff="@string/bridges"
- android:textOn="@string/bridges"
- android:background="@drawable/toggle"
- android:layout_margin="3dp"
- />
<ToggleButton
android:id="@+id/btnVPN"
@@ -193,6 +184,17 @@
android:background="@drawable/toggle"
android:layout_margin="3dp"
/>
+
+
+ <ToggleButton
+ android:id="@+id/btnBridges"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textOff="@string/bridges"
+ android:textOn="@string/bridges"
+ android:background="@drawable/toggle"
+ android:layout_margin="3dp"
+ />
</LinearLayout>
</LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7ddbfb8..1b7b0cc 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -303,7 +303,7 @@
<string name="you_do_not_have_root_access_enabled">You do not have ROOT access enabled</string>
<string name="you_may_need_to_stop_and_start_orbot_for_settings_change_to_be_enabled_">You may need to stop and start Orbot for settings change to be enabled.</string>
- <string name="menu_vpn">VPN</string>
+ <string name="menu_vpn">Apps</string>
<string name="kbps">kbps</string>
diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml
index b84fe76..eabc9b3 100644
--- a/res/xml/preferences.xml
+++ b/res/xml/preferences.xml
@@ -16,7 +16,7 @@ android:enabled="true"
android:title="@string/pref_use_persistent_notifications_title"/>
<CheckBoxPreference
-android:defaultValue="false"
+android:defaultValue="true"
android:key="pref_expanded_notifications"
android:summary="@string/pref_use_expanded_notifications"
android:enabled="true"
diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java
index 86ca7a1..5100368 100644
--- a/src/org/torproject/android/service/TorService.java
+++ b/src/org/torproject/android/service/TorService.java
@@ -27,11 +27,13 @@ import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
import java.net.URLConnection;
+import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
@@ -94,6 +96,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
private int mPortHTTP = 8118;
private int mPortSOCKS = 9050;
+ private int mVpnProxyPort = 7231;
private static final int NOTIFY_ID = 1;
private static final int TRANSPROXY_NOTIFY_ID = 2;
@@ -142,9 +145,13 @@ public class TorService extends Service implements TorServiceConstants, TorConst
private boolean mTransProxyNetworkRefresh = false;
private boolean mUseVPN = false;
+ boolean mIsLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
+
private ExecutorService mExecutor = Executors.newFixedThreadPool(1);
+ private NumberFormat mNumberFormat = null;
+
public void debug(String msg)
{
if (ENABLE_DEBUG_LOG)
@@ -297,7 +304,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
if (hmBuiltNodes.size() > 0)
{
- //sbInfo.append(getString(R.string.your_tor_public_ips_) + '\n');
+ //sbInfo.append(getString(R.string.your_tor_public_ips_) + '\n ');
Set<String> itBuiltNodes = hmBuiltNodes.keySet();
for (String key : itBuiltNodes)
@@ -626,6 +633,8 @@ public class TorService extends Service implements TorServiceConstants, TorConst
}
}).start();
+ mNumberFormat = NumberFormat.getInstance(Locale.getDefault()); //localized numbers!
+
}
catch (Exception e)
{
@@ -805,8 +814,8 @@ public class TorService extends Service implements TorServiceConstants, TorConst
boolean useBridges = prefs.getBoolean(TorConstants.PREF_BRIDGES_ENABLED, false);
if (useBridges)
- if (mUseVPN)
- customEnv.add("TOR_PT_PROXY=socks5://127.0.0.1:9999");
+ if (mUseVPN && !mIsLollipop)
+ customEnv.add("TOR_PT_PROXY=socks5://127.0.0.1:" + mVpnProxyPort);
String baseDirectory = fileTor.getParent();
Shell shellUser = Shell.startShell(customEnv, baseDirectory);
@@ -1407,15 +1416,15 @@ public class TorService extends Service implements TorServiceConstants, TorConst
try
{
- boolean found = findExistingProc ();
-
- if (!found)
- {
- killProcess(fileTor);
- killProcess(filePolipo);
-
- startTor();
- }
+ boolean found = findExistingProc ();
+
+ if (!found)
+ {
+ killProcess(fileTor);
+ killProcess(filePolipo);
+
+ startTor();
+ }
}
catch (Exception e)
{
@@ -1458,8 +1467,11 @@ public class TorService extends Service implements TorServiceConstants, TorConst
Intent intent = new Intent(TorService.this, OrbotVpnService.class);
intent.setAction("start");
- startService(intent);
+ if (!mIsLollipop)
+ intent.putExtra("proxyPort",mVpnProxyPort);
+
+ startService(intent);
}
@@ -1585,8 +1597,9 @@ public class TorService extends Service implements TorServiceConstants, TorConst
// Under 2Mb, returns "xxx.xKb"
// Over 2Mb, returns "xxx.xxMb"
if (count < 1e6)
- return ((float)((int)(count*10/1024))/10 + "Kbps");
- return ((float)((int)(count*100/1024/1024))/100 + "Mbps");
+ return mNumberFormat.format(Math.round((float)((int)(count*10/1024))/10)) + "Kbps";
+ else
+ return mNumberFormat.format(Math.round((float)((int)(count*100/1024/1024))/100)) + "Mbps";
//return count+" kB";
}
@@ -1932,12 +1945,12 @@ public class TorService extends Service implements TorServiceConstants, TorConst
for (String value : configBuffer)
{
- debug("removing torrc conf: " + value);
+ // debug("removing torrc conf: " + value);
}
- conn.resetConf(resetBuffer);
+ // conn.resetConf(resetBuffer);
resetBuffer = null;
}
@@ -2119,10 +2132,12 @@ public class TorService extends Service implements TorServiceConstants, TorConst
if (mUseVPN) //set the proxy here if we aren't using a bridge
{
- String proxyType = "socks5";
- String proxyHost = "127.0.0.1";
- int proxyPort = 9999;
- updateConfiguration(proxyType + "Proxy", proxyHost + ':' + proxyPort, false);
+ if (!mIsLollipop)
+ {
+ String proxyType = "socks5";
+ String proxyHost = "127.0.0.1";
+ updateConfiguration(proxyType + "Proxy", proxyHost + ':' + mVpnProxyPort, false);
+ };
}
else
@@ -2177,15 +2192,17 @@ public class TorService extends Service implements TorServiceConstants, TorConst
{
bridgeDelim = ",";
}
-
- showToolbarNotification(getString(R.string.notification_using_bridges) + ": " + bridgeList, TRANSPROXY_NOTIFY_ID, R.drawable.ic_stat_tor);
StringTokenizer st = new StringTokenizer(bridgeList,bridgeDelim);
while (st.hasMoreTokens())
{
String bridgeConfigLine = st.nextToken().trim();
- debug("Adding bridge: " + bridgeConfigLine);
- updateConfiguration(bridgeCfgKey, bridgeConfigLine, false);
+
+ if (bridgeConfigLine != null && bridgeConfigLine.length() > 0)
+ {
+ debug("Adding bridge: " + bridgeConfigLine);
+ updateConfiguration(bridgeCfgKey, bridgeConfigLine, false);
+ }
}
@@ -2206,30 +2223,6 @@ public class TorService extends Service implements TorServiceConstants, TorConst
{
//time to do autobridges, aka meek
- String proxyBridge = "";
- String proxyType = prefs.getString("pref_proxy_type", null);
-
- if (mUseVPN)
- {
- proxyType = "http"; //"socks5";
- String proxyHost = "127.0.0.1";
- int proxyPort = 9998; //9999;
-
- //proxyBridge = " proxy=" + proxyType + "://" + proxyHost + ':' + proxyPort; //proxy=http://127.0.0.1:9998
- // updateConfiguration(proxyType + "Proxy", proxyHost + ':' + proxyPort, false);
-
-
- }
- else if (proxyType != null && proxyType.length() > 0)
- {
- String proxyHost = prefs.getString("pref_proxy_host", null);
- String proxyPort = prefs.getString("pref_proxy_port", null);
-
- //proxyBridge = " proxy=" + proxyType + "://" + proxyHost + ':' + proxyPort;
- updateConfiguration(proxyType + "Proxy", proxyHost + ':' + proxyPort, false);
-
- }
-
debug ("Using meek bridges");
String bridgeConfig = "meek exec " + fileMeekclient.getCanonicalPath();
@@ -2260,7 +2253,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
}
}
- updateConfiguration(bridgeCfgKey, meekBridge[meekIdx] + proxyBridge, false);
+ updateConfiguration(bridgeCfgKey, meekBridge[meekIdx], false);
}
diff --git a/src/org/torproject/android/service/TorServiceConstants.java b/src/org/torproject/android/service/TorServiceConstants.java
index 1dc25d5..8808976 100644
--- a/src/org/torproject/android/service/TorServiceConstants.java
+++ b/src/org/torproject/android/service/TorServiceConstants.java
@@ -86,7 +86,7 @@ public interface TorServiceConstants {
public static final String CMD_UPDATE = "update";
- public static final String BINARY_TOR_VERSION = "0.2.5.10-openssl1.0.1i-PIE-bridgepatch-obfs4proxy";
+ public static final String BINARY_TOR_VERSION = "0.2.6-RC6-PT-UPDATE-2";
public static final String PREF_BINARY_TOR_VERSION_INSTALLED = "BINARY_TOR_VERSION_INSTALLED";
//obfsproxy
diff --git a/src/org/torproject/android/vpn/OrbotVpnService.java b/src/org/torproject/android/vpn/OrbotVpnService.java
index 56f3b1d..ae40fa9 100644
--- a/src/org/torproject/android/vpn/OrbotVpnService.java
+++ b/src/org/torproject/android/vpn/OrbotVpnService.java
@@ -24,6 +24,7 @@ import org.torproject.android.service.TorServiceConstants;
import android.annotation.TargetApi;
import android.app.PendingIntent;
import android.content.Intent;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.net.VpnService;
import android.os.Build;
import android.os.Handler;
@@ -47,12 +48,10 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
private String mSessionName = "OrbotVPN";
private ParcelFileDescriptor mInterface;
- private int mSocksProxyPort = 9999;
+ private int mSocksProxyPort = -1;
private ProxyServer mSocksProxyServer;
private Thread mThreadProxy;
- // private HttpProxy mHttpProxyServer;
-
private final static int VPN_MTU = 1500;
@Override
@@ -64,6 +63,8 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
{
Log.d(TAG,"starting OrbotVPNService service!");
+ mSocksProxyPort = intent.getIntExtra("proxyPort", 0);
+
// The handler is only used to show messages.
if (mHandler == null) {
mHandler = new Handler(this);
@@ -72,7 +73,10 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
// Stop the previous session by interrupting the thread.
if (mThreadVPN == null || (!mThreadVPN.isAlive()))
{
- enableAppRouting ();
+ boolean isLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
+ if (!isLollipop)
+ startSocksBypass();
+
setupTun2Socks();
}
}
@@ -87,21 +91,6 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
return START_NOT_STICKY;
}
- private void enableAppRouting ()
- {
-
- boolean isLollipop = false;
-
- if (isLollipop)
- {
- //allow for specific apps to be sent through VPN based on list selection
- }
- else
- {
- //do socks bypass trick
- startSocksBypass();
- }
- }
private void startSocksBypass(){
mThreadProxy = new Thread ()
@@ -121,13 +110,6 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
mThreadProxy.start();
- /**
- mHttpProxyServer = new HttpProxy(9998);
- HttpProxy.setVpnService(OrbotVpnService.this);
- mHttpProxyServer.setDebug(5, System.out);
- mHttpProxyServer.start();
- */
-
}
@Override
@@ -183,6 +165,9 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
// (i.e., Farsi and Arabic).^M
Locale.setDefault(new Locale("en"));
+ boolean isLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
+
+
//String localhost = InetAddress.getLocalHost().getHostAddress();
String vpnName = "OrbotVPN";
@@ -201,6 +186,9 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
builder.addRoute("0.0.0.0",0);
// builder.addDnsServer("8.8.8.8");
+ if (isLollipop)
+ doLollipopAppRouting(builder);
+
// Create a new interface using the builder and save the parameters.
mInterface = builder.setSession(mSessionName)
.setConfigureIntent(mConfigureIntent)
@@ -219,6 +207,16 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
mThreadVPN.start();
}
+
+ @TargetApi(Build.VERSION_CODES.L)
+ private void doLollipopAppRouting (Builder builder) throws NameNotFoundException
+ {
+
+
+ builder.addDisallowedApplication("org.torproject.android");
+
+
+ }
@Override
public void onRevoke() {