commit 6d05e27793fd1180e20fd705b50688165a240ea2 Author: Nathan Freitas nathan@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() {