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
This commit is contained in:
parent
3e2b8cff1e
commit
6d05e27793
|
@ -174,15 +174,6 @@
|
||||||
android:layout_margin="3dp"
|
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
|
<ToggleButton
|
||||||
android:id="@+id/btnVPN"
|
android:id="@+id/btnVPN"
|
||||||
|
@ -194,6 +185,17 @@
|
||||||
android:layout_margin="3dp"
|
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>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
@ -303,7 +303,7 @@
|
||||||
<string name="you_do_not_have_root_access_enabled">You do not have ROOT access enabled</string>
|
<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="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>
|
<string name="kbps">kbps</string>
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ android:enabled="true"
|
||||||
android:title="@string/pref_use_persistent_notifications_title"/>
|
android:title="@string/pref_use_persistent_notifications_title"/>
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="true"
|
||||||
android:key="pref_expanded_notifications"
|
android:key="pref_expanded_notifications"
|
||||||
android:summary="@string/pref_use_expanded_notifications"
|
android:summary="@string/pref_use_expanded_notifications"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
|
|
|
@ -27,11 +27,13 @@ import java.net.ServerSocket;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
|
import java.text.NumberFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
@ -94,6 +96,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
|
||||||
private int mPortHTTP = 8118;
|
private int mPortHTTP = 8118;
|
||||||
private int mPortSOCKS = 9050;
|
private int mPortSOCKS = 9050;
|
||||||
|
|
||||||
|
private int mVpnProxyPort = 7231;
|
||||||
|
|
||||||
private static final int NOTIFY_ID = 1;
|
private static final int NOTIFY_ID = 1;
|
||||||
private static final int TRANSPROXY_NOTIFY_ID = 2;
|
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 mTransProxyNetworkRefresh = false;
|
||||||
|
|
||||||
private boolean mUseVPN = false;
|
private boolean mUseVPN = false;
|
||||||
|
boolean mIsLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
|
||||||
|
|
||||||
|
|
||||||
private ExecutorService mExecutor = Executors.newFixedThreadPool(1);
|
private ExecutorService mExecutor = Executors.newFixedThreadPool(1);
|
||||||
|
|
||||||
|
private NumberFormat mNumberFormat = null;
|
||||||
|
|
||||||
public void debug(String msg)
|
public void debug(String msg)
|
||||||
{
|
{
|
||||||
if (ENABLE_DEBUG_LOG)
|
if (ENABLE_DEBUG_LOG)
|
||||||
|
@ -297,7 +304,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
|
||||||
|
|
||||||
if (hmBuiltNodes.size() > 0)
|
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();
|
Set<String> itBuiltNodes = hmBuiltNodes.keySet();
|
||||||
for (String key : itBuiltNodes)
|
for (String key : itBuiltNodes)
|
||||||
|
@ -626,6 +633,8 @@ public class TorService extends Service implements TorServiceConstants, TorConst
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
|
|
||||||
|
mNumberFormat = NumberFormat.getInstance(Locale.getDefault()); //localized numbers!
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -805,8 +814,8 @@ public class TorService extends Service implements TorServiceConstants, TorConst
|
||||||
boolean useBridges = prefs.getBoolean(TorConstants.PREF_BRIDGES_ENABLED, false);
|
boolean useBridges = prefs.getBoolean(TorConstants.PREF_BRIDGES_ENABLED, false);
|
||||||
|
|
||||||
if (useBridges)
|
if (useBridges)
|
||||||
if (mUseVPN)
|
if (mUseVPN && !mIsLollipop)
|
||||||
customEnv.add("TOR_PT_PROXY=socks5://127.0.0.1:9999");
|
customEnv.add("TOR_PT_PROXY=socks5://127.0.0.1:" + mVpnProxyPort);
|
||||||
|
|
||||||
String baseDirectory = fileTor.getParent();
|
String baseDirectory = fileTor.getParent();
|
||||||
Shell shellUser = Shell.startShell(customEnv, baseDirectory);
|
Shell shellUser = Shell.startShell(customEnv, baseDirectory);
|
||||||
|
@ -1407,15 +1416,15 @@ public class TorService extends Service implements TorServiceConstants, TorConst
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
boolean found = findExistingProc ();
|
boolean found = findExistingProc ();
|
||||||
|
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
killProcess(fileTor);
|
killProcess(fileTor);
|
||||||
killProcess(filePolipo);
|
killProcess(filePolipo);
|
||||||
|
|
||||||
startTor();
|
startTor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -1458,8 +1467,11 @@ public class TorService extends Service implements TorServiceConstants, TorConst
|
||||||
|
|
||||||
Intent intent = new Intent(TorService.this, OrbotVpnService.class);
|
Intent intent = new Intent(TorService.this, OrbotVpnService.class);
|
||||||
intent.setAction("start");
|
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"
|
// Under 2Mb, returns "xxx.xKb"
|
||||||
// Over 2Mb, returns "xxx.xxMb"
|
// Over 2Mb, returns "xxx.xxMb"
|
||||||
if (count < 1e6)
|
if (count < 1e6)
|
||||||
return ((float)((int)(count*10/1024))/10 + "Kbps");
|
return mNumberFormat.format(Math.round((float)((int)(count*10/1024))/10)) + "Kbps";
|
||||||
return ((float)((int)(count*100/1024/1024))/100 + "Mbps");
|
else
|
||||||
|
return mNumberFormat.format(Math.round((float)((int)(count*100/1024/1024))/100)) + "Mbps";
|
||||||
|
|
||||||
//return count+" kB";
|
//return count+" kB";
|
||||||
}
|
}
|
||||||
|
@ -1932,12 +1945,12 @@ public class TorService extends Service implements TorServiceConstants, TorConst
|
||||||
for (String value : configBuffer)
|
for (String value : configBuffer)
|
||||||
{
|
{
|
||||||
|
|
||||||
debug("removing torrc conf: " + value);
|
// debug("removing torrc conf: " + value);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.resetConf(resetBuffer);
|
// conn.resetConf(resetBuffer);
|
||||||
resetBuffer = null;
|
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
|
if (mUseVPN) //set the proxy here if we aren't using a bridge
|
||||||
{
|
{
|
||||||
String proxyType = "socks5";
|
if (!mIsLollipop)
|
||||||
String proxyHost = "127.0.0.1";
|
{
|
||||||
int proxyPort = 9999;
|
String proxyType = "socks5";
|
||||||
updateConfiguration(proxyType + "Proxy", proxyHost + ':' + proxyPort, false);
|
String proxyHost = "127.0.0.1";
|
||||||
|
updateConfiguration(proxyType + "Proxy", proxyHost + ':' + mVpnProxyPort, false);
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2178,14 +2193,16 @@ public class TorService extends Service implements TorServiceConstants, TorConst
|
||||||
bridgeDelim = ",";
|
bridgeDelim = ",";
|
||||||
}
|
}
|
||||||
|
|
||||||
showToolbarNotification(getString(R.string.notification_using_bridges) + ": " + bridgeList, TRANSPROXY_NOTIFY_ID, R.drawable.ic_stat_tor);
|
|
||||||
|
|
||||||
StringTokenizer st = new StringTokenizer(bridgeList,bridgeDelim);
|
StringTokenizer st = new StringTokenizer(bridgeList,bridgeDelim);
|
||||||
while (st.hasMoreTokens())
|
while (st.hasMoreTokens())
|
||||||
{
|
{
|
||||||
String bridgeConfigLine = st.nextToken().trim();
|
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
|
//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");
|
debug ("Using meek bridges");
|
||||||
|
|
||||||
String bridgeConfig = "meek exec " + fileMeekclient.getCanonicalPath();
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ public interface TorServiceConstants {
|
||||||
public static final String CMD_UPDATE = "update";
|
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";
|
public static final String PREF_BINARY_TOR_VERSION_INSTALLED = "BINARY_TOR_VERSION_INSTALLED";
|
||||||
|
|
||||||
//obfsproxy
|
//obfsproxy
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.torproject.android.service.TorServiceConstants;
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
import android.net.VpnService;
|
import android.net.VpnService;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
@ -47,12 +48,10 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
|
||||||
private String mSessionName = "OrbotVPN";
|
private String mSessionName = "OrbotVPN";
|
||||||
private ParcelFileDescriptor mInterface;
|
private ParcelFileDescriptor mInterface;
|
||||||
|
|
||||||
private int mSocksProxyPort = 9999;
|
private int mSocksProxyPort = -1;
|
||||||
private ProxyServer mSocksProxyServer;
|
private ProxyServer mSocksProxyServer;
|
||||||
private Thread mThreadProxy;
|
private Thread mThreadProxy;
|
||||||
|
|
||||||
// private HttpProxy mHttpProxyServer;
|
|
||||||
|
|
||||||
private final static int VPN_MTU = 1500;
|
private final static int VPN_MTU = 1500;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -64,6 +63,8 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
|
||||||
{
|
{
|
||||||
Log.d(TAG,"starting OrbotVPNService service!");
|
Log.d(TAG,"starting OrbotVPNService service!");
|
||||||
|
|
||||||
|
mSocksProxyPort = intent.getIntExtra("proxyPort", 0);
|
||||||
|
|
||||||
// The handler is only used to show messages.
|
// The handler is only used to show messages.
|
||||||
if (mHandler == null) {
|
if (mHandler == null) {
|
||||||
mHandler = new Handler(this);
|
mHandler = new Handler(this);
|
||||||
|
@ -72,7 +73,10 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
|
||||||
// Stop the previous session by interrupting the thread.
|
// Stop the previous session by interrupting the thread.
|
||||||
if (mThreadVPN == null || (!mThreadVPN.isAlive()))
|
if (mThreadVPN == null || (!mThreadVPN.isAlive()))
|
||||||
{
|
{
|
||||||
enableAppRouting ();
|
boolean isLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
|
||||||
|
if (!isLollipop)
|
||||||
|
startSocksBypass();
|
||||||
|
|
||||||
setupTun2Socks();
|
setupTun2Socks();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,21 +91,6 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
|
||||||
return START_NOT_STICKY;
|
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(){
|
private void startSocksBypass(){
|
||||||
mThreadProxy = new Thread ()
|
mThreadProxy = new Thread ()
|
||||||
|
@ -121,13 +110,6 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
|
||||||
|
|
||||||
mThreadProxy.start();
|
mThreadProxy.start();
|
||||||
|
|
||||||
/**
|
|
||||||
mHttpProxyServer = new HttpProxy(9998);
|
|
||||||
HttpProxy.setVpnService(OrbotVpnService.this);
|
|
||||||
mHttpProxyServer.setDebug(5, System.out);
|
|
||||||
mHttpProxyServer.start();
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -183,6 +165,9 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
|
||||||
// (i.e., Farsi and Arabic).^M
|
// (i.e., Farsi and Arabic).^M
|
||||||
Locale.setDefault(new Locale("en"));
|
Locale.setDefault(new Locale("en"));
|
||||||
|
|
||||||
|
boolean isLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
|
||||||
|
|
||||||
|
|
||||||
//String localhost = InetAddress.getLocalHost().getHostAddress();
|
//String localhost = InetAddress.getLocalHost().getHostAddress();
|
||||||
|
|
||||||
String vpnName = "OrbotVPN";
|
String vpnName = "OrbotVPN";
|
||||||
|
@ -201,6 +186,9 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
|
||||||
builder.addRoute("0.0.0.0",0);
|
builder.addRoute("0.0.0.0",0);
|
||||||
// builder.addDnsServer("8.8.8.8");
|
// builder.addDnsServer("8.8.8.8");
|
||||||
|
|
||||||
|
if (isLollipop)
|
||||||
|
doLollipopAppRouting(builder);
|
||||||
|
|
||||||
// Create a new interface using the builder and save the parameters.
|
// Create a new interface using the builder and save the parameters.
|
||||||
mInterface = builder.setSession(mSessionName)
|
mInterface = builder.setSession(mSessionName)
|
||||||
.setConfigureIntent(mConfigureIntent)
|
.setConfigureIntent(mConfigureIntent)
|
||||||
|
@ -220,6 +208,16 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
|
||||||
mThreadVPN.start();
|
mThreadVPN.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TargetApi(Build.VERSION_CODES.L)
|
||||||
|
private void doLollipopAppRouting (Builder builder) throws NameNotFoundException
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
builder.addDisallowedApplication("org.torproject.android");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRevoke() {
|
public void onRevoke() {
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue