Improve VPN service support - fix network switching handling
We now refresh the VPN and tun2socks interfaces when the network type switches, and we do so in a way that does not cause traffic to leak. The new interface is established before we close the old one.
This commit is contained in:
parent
d14dabb4f3
commit
75426bb9e2
|
@ -36,9 +36,16 @@
|
||||||
<item>ru</item>
|
<item>ru</item>
|
||||||
|
|
||||||
|
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="bridge_options">
|
||||||
|
<item>Obfs4 (Recommended)</item>
|
||||||
|
<item>Obfs3</item>
|
||||||
|
<item>ScrambleSuit</item>
|
||||||
|
<item>Tunnel through Azure</item>
|
||||||
|
<item>Tunnel through Amazon</item>
|
||||||
|
<item>Tunnel through Google</item>
|
||||||
|
<item></item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -315,15 +315,16 @@
|
||||||
|
|
||||||
<string name="bridges_updated">Bridges Updated</string>
|
<string name="bridges_updated">Bridges Updated</string>
|
||||||
|
|
||||||
<string name="restart_orbot_to_use_this_bridge_">"Restart Orbot to use these bridges: "</string>
|
<string name="restart_orbot_to_use_this_bridge_">Please restart Orbot to enable the changes</string>
|
||||||
|
|
||||||
<string name="menu_qr">QR Codes</string>
|
<string name="menu_qr">QR Codes</string>
|
||||||
|
|
||||||
<string name="if_your_mobile_network_actively_blocks_tor_you_can_use_a_tor_bridge_to_access_the_network_another_way_to_get_bridges_is_to_send_an_email_to_bridges_torproject_org_please_note_that_you_must_send_the_email_using_an_address_from_one_of_the_following_email_providers_riseup_gmail_or_yahoo_">If your mobile network actively blocks Tor, you can use a Tor Bridge to access the network.\n\nYou can get a bridge address from https://bridges.torproject.org or scan a bridge QR code from a friend.\n\nAnother way to get bridges is to send an email to bridges@torproject.org. Please note that you must send the email using an address from one of the following email providers: Riseup, Gmail or Yahoo.</string>
|
<string name="if_your_mobile_network_actively_blocks_tor_you_can_use_a_tor_bridge_to_access_the_network_another_way_to_get_bridges_is_to_send_an_email_to_bridges_torproject_org_please_note_that_you_must_send_the_email_using_an_address_from_one_of_the_following_email_providers_riseup_gmail_or_yahoo_">If your mobile network actively blocks Tor, you can use a Tor Bridge to access the network.\n\nYou can get a bridge address from https://bridges.torproject.org, by emailing bridges@torproject.org, or by scanning a bridge QR code.</string>
|
||||||
|
|
||||||
<string name="bridge_mode">Bridge Mode</string>
|
<string name="bridge_mode">Bridge Mode</string>
|
||||||
|
|
||||||
<string name="get_bridges">Get Bridges</string>
|
<string name="get_bridges_email">Email</string>
|
||||||
|
<string name="get_bridges_web">Web</string>
|
||||||
|
|
||||||
<string name="activate">Activate</string>
|
<string name="activate">Activate</string>
|
||||||
|
|
||||||
|
@ -332,4 +333,10 @@
|
||||||
<string name="you_can_enable_all_apps_on_your_device_to_run_through_the_tor_network_using_the_vpn_feature_of_android_">You can enable all apps on your device to run through the Tor network using the VPN feature of Android.\n\n*WARNING* This is a new, experimental feature and in some cases may not start automatically, or may stop. It should NOT be used for anonymity, and ONLY used for getting through firewalls and filters.</string>
|
<string name="you_can_enable_all_apps_on_your_device_to_run_through_the_tor_network_using_the_vpn_feature_of_android_">You can enable all apps on your device to run through the Tor network using the VPN feature of Android.\n\n*WARNING* This is a new, experimental feature and in some cases may not start automatically, or may stop. It should NOT be used for anonymity, and ONLY used for getting through firewalls and filters.</string>
|
||||||
|
|
||||||
<string name="send_email">Send Email</string>
|
<string name="send_email">Send Email</string>
|
||||||
|
|
||||||
|
<string name="you_must_get_a_bridge_address_by_email_web_or_from_a_friend_once_you_have_this_address_please_paste_it_into_the_bridges_preference_in_orbot_s_setting_and_restart_">You must can a bridge address by email, web or by scanning a bridge QR code. Once you have this address, please paste it into the \"Bridges\" preference in Orbot\'s setting and restart.</string>
|
||||||
|
|
||||||
|
<string name="install_orweb">Install Orweb</string>
|
||||||
|
|
||||||
|
<string name="standard_browser">Standard Browser</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -16,7 +16,7 @@ public interface OrbotConstants {
|
||||||
//path to check Tor against
|
//path to check Tor against
|
||||||
public final static String URL_TOR_CHECK = "https://check.torproject.org";
|
public final static String URL_TOR_CHECK = "https://check.torproject.org";
|
||||||
|
|
||||||
public final static String URL_TOR_BRIDGES = "https://bridges.torproject.org";
|
public final static String URL_TOR_BRIDGES = "https://bridges.torproject.org/bridges?transport=";
|
||||||
|
|
||||||
public final static String NEWLINE = "\n";
|
public final static String NEWLINE = "\n";
|
||||||
|
|
||||||
|
|
|
@ -661,6 +661,8 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon
|
||||||
setResult(RESULT_OK);
|
setResult(RESULT_OK);
|
||||||
|
|
||||||
mBtnBridges.setChecked(true);
|
mBtnBridges.setChecked(true);
|
||||||
|
|
||||||
|
enableBridges(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean showWizard = true;
|
private boolean showWizard = true;
|
||||||
|
@ -707,7 +709,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon
|
||||||
.setIcon(R.drawable.onion32)
|
.setIcon(R.drawable.onion32)
|
||||||
.setTitle(R.string.install_apps_)
|
.setTitle(R.string.install_apps_)
|
||||||
.setMessage(R.string.it_doesn_t_seem_like_you_have_orweb_installed_want_help_with_that_or_should_we_just_open_the_browser_)
|
.setMessage(R.string.it_doesn_t_seem_like_you_have_orweb_installed_want_help_with_that_or_should_we_just_open_the_browser_)
|
||||||
.setPositiveButton(android.R.string.ok, new Dialog.OnClickListener ()
|
.setPositiveButton(R.string.install_orweb, new Dialog.OnClickListener ()
|
||||||
{
|
{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -720,7 +722,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
.setNegativeButton(android.R.string.no, new Dialog.OnClickListener ()
|
.setNegativeButton(R.string.standard_browser, new Dialog.OnClickListener ()
|
||||||
{
|
{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -860,41 +862,56 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon
|
||||||
new AlertDialog.Builder(this)
|
new AlertDialog.Builder(this)
|
||||||
.setTitle(R.string.bridge_mode)
|
.setTitle(R.string.bridge_mode)
|
||||||
.setView(view)
|
.setView(view)
|
||||||
.setNeutralButton(R.string.get_bridges, new Dialog.OnClickListener ()
|
.setItems(R.array.bridge_options, new DialogInterface.OnClickListener() {
|
||||||
{
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
// The 'which' argument contains the index position
|
||||||
@Override
|
// of the selected item
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
|
switch (which)
|
||||||
//openBrowser(URL_TOR_BRIDGES);
|
{
|
||||||
|
case 0: //obfs 4;
|
||||||
sendGetBridgeEmail();
|
showGetBridgePrompt("obfs4");
|
||||||
}
|
|
||||||
|
break;
|
||||||
|
case 1: //obfs3
|
||||||
})
|
showGetBridgePrompt("obfs3");
|
||||||
.setPositiveButton(R.string.activate, new Dialog.OnClickListener ()
|
|
||||||
{
|
break;
|
||||||
|
case 2: //scramblesuit
|
||||||
@Override
|
showGetBridgePrompt("scramblesuit");
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
|
break;
|
||||||
enableBridges (true);
|
case 3: //azure
|
||||||
|
mPrefs.edit().putString(OrbotConstants.PREF_BRIDGES_LIST,"2").commit();
|
||||||
}
|
enableBridges(true);
|
||||||
|
|
||||||
|
break;
|
||||||
})
|
case 4: //amazon
|
||||||
.setNegativeButton(android.R.string.cancel, new Dialog.OnClickListener()
|
mPrefs.edit().putString(OrbotConstants.PREF_BRIDGES_LIST,"1").commit();
|
||||||
|
enableBridges(true);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 5: //google
|
||||||
|
mPrefs.edit().putString(OrbotConstants.PREF_BRIDGES_LIST,"0").commit();
|
||||||
|
enableBridges(true);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}).setNegativeButton(android.R.string.cancel, new Dialog.OnClickListener()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
|
||||||
mBtnBridges.setChecked(false);
|
//mBtnBridges.setChecked(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.show();
|
.show();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -903,13 +920,72 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendGetBridgeEmail ()
|
private void showGetBridgePrompt (final String type)
|
||||||
|
{
|
||||||
|
LayoutInflater li = LayoutInflater.from(this);
|
||||||
|
View view = li.inflate(R.layout.layout_diag, null);
|
||||||
|
|
||||||
|
TextView versionName = (TextView)view.findViewById(R.id.diaglog);
|
||||||
|
versionName.setText(R.string.you_must_get_a_bridge_address_by_email_web_or_from_a_friend_once_you_have_this_address_please_paste_it_into_the_bridges_preference_in_orbot_s_setting_and_restart_);
|
||||||
|
|
||||||
|
new AlertDialog.Builder(this)
|
||||||
|
.setTitle(R.string.bridge_mode)
|
||||||
|
.setView(view)
|
||||||
|
.setNegativeButton(android.R.string.cancel, new Dialog.OnClickListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
|
||||||
|
//mBtnBridges.setChecked(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNeutralButton(R.string.get_bridges_email, new Dialog.OnClickListener ()
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
|
||||||
|
|
||||||
|
sendGetBridgeEmail(type);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
.setPositiveButton(R.string.get_bridges_web, new Dialog.OnClickListener ()
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
|
||||||
|
openBrowser(URL_TOR_BRIDGES + type);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendGetBridgeEmail (String type)
|
||||||
{
|
{
|
||||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||||
intent.setType("message/rfc822");
|
intent.setType("message/rfc822");
|
||||||
intent.putExtra(Intent.EXTRA_EMAIL , new String[]{"bridges@torproject.org"});
|
intent.putExtra(Intent.EXTRA_EMAIL , new String[]{"bridges@torproject.org"});
|
||||||
intent.putExtra(Intent.EXTRA_SUBJECT, "Tor Bridge Request");
|
|
||||||
|
if (type != null)
|
||||||
|
{
|
||||||
|
intent.putExtra(Intent.EXTRA_SUBJECT, "get transport " + type);
|
||||||
|
intent.putExtra(Intent.EXTRA_TEXT, "get transport " + type);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
intent.putExtra(Intent.EXTRA_SUBJECT, "get bridges");
|
||||||
|
intent.putExtra(Intent.EXTRA_TEXT, "get bridges");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
startActivity(Intent.createChooser(intent, getString(R.string.send_email)));
|
startActivity(Intent.createChooser(intent, getString(R.string.send_email)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -917,10 +993,45 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon
|
||||||
{
|
{
|
||||||
|
|
||||||
Editor edit = mPrefs.edit();
|
Editor edit = mPrefs.edit();
|
||||||
edit.putBoolean("pref_bridges_enabled", enable);
|
edit.putBoolean(OrbotConstants.PREF_BRIDGES_ENABLED, enable);
|
||||||
edit.commit();
|
edit.commit();
|
||||||
|
|
||||||
updateSettings();
|
updateSettings();
|
||||||
|
|
||||||
|
if (torStatus == TorServiceConstants.STATUS_ON)
|
||||||
|
{
|
||||||
|
String bridgeList = mPrefs.getString(OrbotConstants.PREF_BRIDGES_LIST,null);
|
||||||
|
if (bridgeList != null && bridgeList.length() > 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//do auto restart
|
||||||
|
stopTor ();
|
||||||
|
|
||||||
|
mHandler.postDelayed(new Runnable () {
|
||||||
|
|
||||||
|
public void run ()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
startTor();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.e(TAG,"can't start orbot",e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.e(TAG,"can't stop orbot",e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void promptStartVpnService ()
|
public void promptStartVpnService ()
|
||||||
|
@ -1160,7 +1271,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon
|
||||||
//here we update the UI which is a bit sloppy and mixed up code wise
|
//here we update the UI which is a bit sloppy and mixed up code wise
|
||||||
//might be best to just call updateStatus() instead of directly manipulating UI in this method - yep makes sense
|
//might be best to just call updateStatus() instead of directly manipulating UI in this method - yep makes sense
|
||||||
imgStatus.setImageResource(R.drawable.torstarting);
|
imgStatus.setImageResource(R.drawable.torstarting);
|
||||||
// lblStatus.setText(getString(R.string.status_starting_up));
|
lblStatus.setText(getString(R.string.status_starting_up));
|
||||||
|
|
||||||
//we send a message here to the progressDialog i believe, but we can clarify that shortly
|
//we send a message here to the progressDialog i believe, but we can clarify that shortly
|
||||||
Message msg = mHandler.obtainMessage(TorServiceConstants.ENABLE_TOR_MSG);
|
Message msg = mHandler.obtainMessage(TorServiceConstants.ENABLE_TOR_MSG);
|
||||||
|
@ -1168,7 +1279,6 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon
|
||||||
mHandler.sendMessage(msg);
|
mHandler.sendMessage(msg);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//now we stop Tor! amazing!
|
//now we stop Tor! amazing!
|
||||||
|
|
|
@ -96,7 +96,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
|
||||||
private int mPortHTTP = 8118;
|
private int mPortHTTP = 8118;
|
||||||
private int mPortSOCKS = 9050;
|
private int mPortSOCKS = 9050;
|
||||||
|
|
||||||
private int mVpnProxyPort = 7231;
|
private int mVpnProxyPort = 9099;
|
||||||
|
|
||||||
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;
|
||||||
|
@ -1475,6 +1475,18 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void refreshVpnProxy () {
|
||||||
|
|
||||||
|
debug ("refreshing VPN Proxy");
|
||||||
|
|
||||||
|
Intent intent = new Intent(TorService.this, OrbotVpnService.class);
|
||||||
|
intent.setAction("refresh");
|
||||||
|
startService(intent);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void clearVpnProxy ()
|
public void clearVpnProxy ()
|
||||||
{
|
{
|
||||||
debug ("clearing VPN Proxy");
|
debug ("clearing VPN Proxy");
|
||||||
|
@ -1911,6 +1923,31 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setTorNetworkEnabled (final boolean isEnabled)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
//it is possible to not have a connection yet, and someone might try to newnym
|
||||||
|
if (conn != null)
|
||||||
|
{
|
||||||
|
new Thread ()
|
||||||
|
{
|
||||||
|
public void run ()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
|
||||||
|
conn.setConf("DisableNetwork", isEnabled ? "0" : "1");
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ioe){
|
||||||
|
debug("error requesting newnym: " + ioe.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public void newIdentity ()
|
public void newIdentity ()
|
||||||
{
|
{
|
||||||
//it is possible to not have a connection yet, and someone might try to newnym
|
//it is possible to not have a connection yet, and someone might try to newnym
|
||||||
|
@ -2048,52 +2085,75 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
|
||||||
final ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
|
final ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
final NetworkInfo netInfo = cm.getActiveNetworkInfo();
|
final NetworkInfo netInfo = cm.getActiveNetworkInfo();
|
||||||
|
|
||||||
|
boolean newConnectivityState = false;
|
||||||
|
|
||||||
if(netInfo != null && netInfo.isConnected()) {
|
if(netInfo != null && netInfo.isConnected()) {
|
||||||
// WE ARE CONNECTED: DO SOMETHING
|
// WE ARE CONNECTED: DO SOMETHING
|
||||||
mConnectivity = true;
|
newConnectivityState = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// WE ARE NOT: DO SOMETHING ELSE
|
// WE ARE NOT: DO SOMETHING ELSE
|
||||||
mConnectivity = false;
|
newConnectivityState = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doNetworKSleep)
|
//is this a change in state?
|
||||||
|
if (mConnectivity != newConnectivityState)
|
||||||
{
|
{
|
||||||
try {
|
|
||||||
updateConfiguration("DisableNetwork", mConnectivity ? "0" : "1", false);
|
if (doNetworKSleep)
|
||||||
|
{
|
||||||
if (mCurrentStatus != STATUS_OFF)
|
try {
|
||||||
{
|
|
||||||
if (!mConnectivity)
|
setTorNetworkEnabled (mConnectivity);
|
||||||
{
|
|
||||||
logNotice(context.getString(R.string.no_network_connectivity_putting_tor_to_sleep_));
|
if (mCurrentStatus != STATUS_OFF)
|
||||||
showToolbarNotification(getString(R.string.no_internet_connection_tor),NOTIFY_ID,R.drawable.ic_stat_tor_off);
|
{
|
||||||
|
if (!mConnectivity)
|
||||||
}
|
{
|
||||||
else
|
logNotice(context.getString(R.string.no_network_connectivity_putting_tor_to_sleep_));
|
||||||
{
|
showToolbarNotification(getString(R.string.no_internet_connection_tor),NOTIFY_ID,R.drawable.ic_stat_tor_off);
|
||||||
logNotice(context.getString(R.string.network_connectivity_is_good_waking_tor_up_));
|
|
||||||
showToolbarNotification(getString(R.string.status_activated),NOTIFY_ID,R.drawable.ic_stat_tor);
|
}
|
||||||
|
else
|
||||||
if (mHasRoot && mEnableTransparentProxy && mTransProxyNetworkRefresh)
|
{
|
||||||
{
|
logNotice(context.getString(R.string.network_connectivity_is_good_waking_tor_up_));
|
||||||
|
showToolbarNotification(getString(R.string.status_activated),NOTIFY_ID,R.drawable.ic_stat_tor);
|
||||||
Shell shell = Shell.startRootShell();
|
|
||||||
|
if (mHasRoot && mEnableTransparentProxy && mTransProxyNetworkRefresh)
|
||||||
disableTransparentProxy(shell);
|
{
|
||||||
enableTransparentProxy(shell);
|
|
||||||
|
Shell shell = Shell.startRootShell();
|
||||||
shell.close();
|
|
||||||
}
|
disableTransparentProxy(shell);
|
||||||
|
enableTransparentProxy(shell);
|
||||||
}
|
|
||||||
}
|
shell.close();
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
logException ("error updating state after network restart",e);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
saveConfiguration();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
logException ("error updating state after network restart",e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mUseVPN && mConnectivity && (mCurrentStatus != STATUS_OFF)) //we need to turn on VPN here so the proxy is running
|
||||||
|
{
|
||||||
|
setTorNetworkEnabled (false);
|
||||||
|
refreshVpnProxy();
|
||||||
|
setTorNetworkEnabled (true);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mConnectivity = newConnectivityState;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,10 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
|
||||||
|
|
||||||
private final static int VPN_MTU = 1500;
|
private final static int VPN_MTU = 1500;
|
||||||
|
|
||||||
|
private final static boolean isLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
|
||||||
|
|
||||||
|
private boolean isRestart = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
|
|
||||||
|
@ -76,7 +80,7 @@ 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()))
|
||||||
{
|
{
|
||||||
boolean isLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
|
|
||||||
if (!isLollipop)
|
if (!isLollipop)
|
||||||
startSocksBypass();
|
startSocksBypass();
|
||||||
|
|
||||||
|
@ -89,6 +93,13 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
|
||||||
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"))
|
||||||
|
{
|
||||||
|
if (!isLollipop)
|
||||||
|
startSocksBypass();
|
||||||
|
|
||||||
|
setupTun2Socks();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return START_NOT_STICKY;
|
return START_NOT_STICKY;
|
||||||
|
@ -102,6 +113,12 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
|
||||||
{
|
{
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
if (mSocksProxyServer != null)
|
||||||
|
{
|
||||||
|
stopSocksBypass ();
|
||||||
|
}
|
||||||
|
|
||||||
mSocksProxyServer = new ProxyServer(new ServerAuthenticatorNone(null, null));
|
mSocksProxyServer = new ProxyServer(new ServerAuthenticatorNone(null, null));
|
||||||
ProxyServer.setVpnService(OrbotVpnService.this);
|
ProxyServer.setVpnService(OrbotVpnService.this);
|
||||||
mSocksProxyServer.start(mSocksProxyPort, 5, InetAddress.getLocalHost());
|
mSocksProxyServer.start(mSocksProxyPort, 5, InetAddress.getLocalHost());
|
||||||
|
@ -115,10 +132,20 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void stopSocksBypass ()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (mSocksProxyServer != null){
|
||||||
|
mSocksProxyServer.stop();
|
||||||
|
mSocksProxyServer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
stopVPN();
|
stopVPN();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopVPN ()
|
private void stopVPN ()
|
||||||
|
@ -126,10 +153,7 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
|
||||||
|
|
||||||
Tun2Socks.Stop();
|
Tun2Socks.Stop();
|
||||||
|
|
||||||
if (mSocksProxyServer != null){
|
stopSocksBypass ();
|
||||||
mSocksProxyServer.stop();
|
|
||||||
mSocksProxyServer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mInterface != null){
|
if (mInterface != null){
|
||||||
try
|
try
|
||||||
|
@ -167,54 +191,64 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
|
||||||
|
|
||||||
public void run ()
|
public void run ()
|
||||||
{
|
{
|
||||||
if (mInterface == null)
|
try
|
||||||
{
|
{
|
||||||
try
|
|
||||||
|
// 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"));
|
||||||
|
|
||||||
|
//String localhost = InetAddress.getLocalHost().getHostAddress();
|
||||||
|
|
||||||
|
String vpnName = "OrbotVPN";
|
||||||
|
String virtualGateway = "10.0.0.1";
|
||||||
|
String virtualIP = "10.0.0.2";
|
||||||
|
String virtualNetMask = "255.255.255.0";
|
||||||
|
String localSocks = "127.0.0.1" + ':' + TorServiceConstants.PORT_SOCKS_DEFAULT;
|
||||||
|
String localDNS = "10.0.0.1" + ':' + TorServiceConstants.TOR_DNS_PORT_DEFAULT;
|
||||||
|
|
||||||
|
|
||||||
|
Builder builder = new Builder();
|
||||||
|
|
||||||
|
builder.setMtu(VPN_MTU);
|
||||||
|
builder.addAddress(virtualGateway,28);
|
||||||
|
builder.setSession(vpnName);
|
||||||
|
builder.addRoute("0.0.0.0",0);
|
||||||
|
// builder.addDnsServer("8.8.8.8");
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
|
||||||
{
|
{
|
||||||
|
doLollipopAppRouting(builder);
|
||||||
// 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"));
|
|
||||||
|
|
||||||
//String localhost = InetAddress.getLocalHost().getHostAddress();
|
|
||||||
|
|
||||||
String vpnName = "OrbotVPN";
|
|
||||||
String virtualGateway = "10.0.0.1";
|
|
||||||
String virtualIP = "10.0.0.2";
|
|
||||||
String virtualNetMask = "255.255.255.0";
|
|
||||||
String localSocks = "127.0.0.1" + ':' + TorServiceConstants.PORT_SOCKS_DEFAULT;
|
|
||||||
String localDNS = "10.0.0.1" + ':' + TorServiceConstants.TOR_DNS_PORT_DEFAULT;
|
|
||||||
|
|
||||||
|
|
||||||
Builder builder = new Builder();
|
|
||||||
|
|
||||||
builder.setMtu(VPN_MTU);
|
|
||||||
builder.addAddress(virtualGateway,28);
|
|
||||||
builder.setSession(vpnName);
|
|
||||||
builder.addRoute("0.0.0.0",0);
|
|
||||||
// builder.addDnsServer("8.8.8.8");
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
{
|
|
||||||
doLollipopAppRouting(builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new interface using the builder and save the parameters.
|
|
||||||
mInterface = builder.setSession(mSessionName)
|
|
||||||
.setConfigureIntent(mConfigureIntent)
|
|
||||||
.establish();
|
|
||||||
|
|
||||||
Tun2Socks.Start(mInterface, VPN_MTU, virtualIP, virtualNetMask, localSocks , localDNS , true);
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
|
||||||
|
// Create a new interface using the builder and save the parameters.
|
||||||
|
ParcelFileDescriptor newInterface = builder.setSession(mSessionName)
|
||||||
|
.setConfigureIntent(mConfigureIntent)
|
||||||
|
.establish();
|
||||||
|
|
||||||
|
if (mInterface != null)
|
||||||
{
|
{
|
||||||
Log.d(TAG,"tun2Socks has stopped",e);
|
isRestart = true;
|
||||||
|
|
||||||
|
Tun2Socks.Stop();
|
||||||
|
mInterface.close();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
mInterface = newInterface;
|
||||||
|
|
||||||
|
Tun2Socks.Start(mInterface, VPN_MTU, virtualIP, virtualNetMask, localSocks , localDNS , true);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.d(TAG,"tun2Socks has stopped",e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
mThreadVPN.start();
|
mThreadVPN.start();
|
||||||
|
@ -222,22 +256,23 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
private void doLollipopAppRouting (Builder builder) throws NameNotFoundException
|
private void doLollipopAppRouting (Builder builder) throws NameNotFoundException
|
||||||
{
|
{
|
||||||
|
builder.addDisallowedApplication("org.torproject.android");
|
||||||
|
|
||||||
builder.addDisallowedApplication("org.torproject.android");
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRevoke() {
|
public void onRevoke() {
|
||||||
|
|
||||||
SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext());
|
if (!isRestart)
|
||||||
prefs.edit().putBoolean("pref_vpn", false).commit();
|
{
|
||||||
|
SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext());
|
||||||
stopVPN();
|
prefs.edit().putBoolean("pref_vpn", false).commit();
|
||||||
|
stopVPN();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
isRestart = false;
|
||||||
|
|
||||||
super.onRevoke();
|
super.onRevoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue