From 9d60f71713eb20cc7ad89ee9e392d36c4ac5982b Mon Sep 17 00:00:00 2001 From: Arne Schwabe Date: Thu, 22 Mar 2018 13:51:25 +0100 Subject: Improve socks proxy handling --- .../main/java/de/blinkt/openvpn/VpnProfile.java | 13 +++- .../java/de/blinkt/openvpn/core/Connection.java | 8 ++- .../openvpn/core/OpenVpnManagementThread.java | 78 +++++++++++----------- .../java/de/blinkt/openvpn/core/OrbotHelper.java | 31 ++++++--- .../blinkt/openvpn/core/TestConfigGenerator.java | 11 +-- 5 files changed, 78 insertions(+), 63 deletions(-) (limited to 'main/src') diff --git a/main/src/main/java/de/blinkt/openvpn/VpnProfile.java b/main/src/main/java/de/blinkt/openvpn/VpnProfile.java index 5056a111..838604e2 100644 --- a/main/src/main/java/de/blinkt/openvpn/VpnProfile.java +++ b/main/src/main/java/de/blinkt/openvpn/VpnProfile.java @@ -362,7 +362,7 @@ public class VpnProfile implements Serializable, Cloneable { boolean canUsePlainRemotes = true; if (mConnections.length == 1) { - cfg += mConnections[0].getConnectionBlock(); + cfg += mConnections[0].getConnectionBlock(configForOvpn3); } else { for (Connection conn : mConnections) { canUsePlainRemotes = canUsePlainRemotes && conn.isOnlyRemote(); @@ -374,7 +374,7 @@ public class VpnProfile implements Serializable, Cloneable { if (canUsePlainRemotes) { for (Connection conn : mConnections) { if (conn.mEnabled) { - cfg += conn.getConnectionBlock(); + cfg += conn.getConnectionBlock(configForOvpn3); } } } @@ -604,7 +604,7 @@ public class VpnProfile implements Serializable, Cloneable { for (Connection conn : mConnections) { if (conn.mEnabled) { cfg += "\n"; - cfg += conn.getConnectionBlock(); + cfg += conn.getConnectionBlock(configForOvpn3); cfg += "\n"; } } @@ -965,7 +965,14 @@ public class VpnProfile implements Serializable, Cloneable { if (mAuthenticationType == TYPE_PKCS12 || mAuthenticationType == TYPE_USERPASS_PKCS12) { return R.string.openvpn3_pkcs12; } + for (Connection conn : mConnections) { + if (conn.mProxyType == Connection.ProxyType.ORBOT || conn.mProxyType == Connection.ProxyType.SOCKS5) + return R.string.openvpn3_socksproxy; + } } + if (!OrbotHelper.checkTorReceier(context)) + return R.string.no_orbotfound; + // Everything okay return R.string.no_error_found; diff --git a/main/src/main/java/de/blinkt/openvpn/core/Connection.java b/main/src/main/java/de/blinkt/openvpn/core/Connection.java index 748455ec..88748d1d 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/Connection.java +++ b/main/src/main/java/de/blinkt/openvpn/core/Connection.java @@ -33,7 +33,7 @@ public class Connection implements Serializable, Cloneable { private static final long serialVersionUID = 92031902903829089L; - public String getConnectionBlock() { + public String getConnectionBlock(boolean isOpenVPN3) { String cfg = ""; // Server Address @@ -49,6 +49,12 @@ public class Connection implements Serializable, Cloneable { if (mConnectTimeout != 0) cfg += String.format(Locale.US, " connect-timeout %d\n", mConnectTimeout); + // OpenVPN 2.x manages proxy connection via management interface + if (isOpenVPN3 && mProxyType == ProxyType.HTTP) + { + cfg+=String.format(Locale.US,"http-proxy %s %s\n", mProxyName, mProxyPort); + } + if (!TextUtils.isEmpty(mCustomConfiguration) && mUseCustomConfig) { cfg += mCustomConfiguration; diff --git a/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java b/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java index cc777c79..30c61beb 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java +++ b/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java @@ -36,6 +36,7 @@ import de.blinkt.openvpn.VpnProfile; public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { + public static final int ORBOT_TIMEOUT_MS = 20 * 1000; private static final String TAG = "openvpn"; private static final Vector active = new Vector<>(); private final Handler mResumeHandler; @@ -51,12 +52,45 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { private pauseReason lastPauseReason = pauseReason.noNetwork; private PausedStateCallback mPauseCallback; private boolean mShuttingDown; - private Runnable mResumeHoldRunnable = new Runnable() { + private Runnable mResumeHoldRunnable = () -> { + if (shouldBeRunning()) { + releaseHoldCmd(); + } + }; + private Runnable orbotStatusTimeOutRunnable = new Runnable() { @Override public void run() { - if (shouldBeRunning()) { - releaseHoldCmd(); - } + sendProxyCMD(Connection.ProxyType.SOCKS5, "127.0.0.1", Integer.toString(OrbotHelper.SOCKS_PROXY_PORT_DEFAULT)); + OrbotHelper.get(mOpenVPNService).removeStatusCallback(statusCallback); + + } + }; + private OrbotHelper.StatusCallback statusCallback = new OrbotHelper.StatusCallback() { + + @Override + public void onStatus(Intent statusIntent) { + String extras = ""; + for (String key : statusIntent.getExtras().keySet()) + extras += String.format(Locale.ENGLISH, "%s - '%s'", key, statusIntent.getExtras().getString(key, "[]")); + VpnStatus.logDebug("Got Orbot status: " + extras); + + } + + @Override + public void onNotYetInstalled() { + VpnStatus.logDebug("Orbot not yet installed"); + } + + @Override + public void onOrbotReady(Intent intent, String socksHost, int socksPort) { + mResumeHandler.removeCallbacks(orbotStatusTimeOutRunnable); + sendProxyCMD(Connection.ProxyType.SOCKS5, socksHost, Integer.toString(socksPort)); + OrbotHelper.get(mOpenVPNService).removeStatusCallback(this); + } + + @Override + public void onDisabled(Intent intent) { + VpnStatus.logWarning("Orbot integration for external applications is disabled. Waiting %ds before connecting to the default port. Enable external app integration in Orbot or use Socks v5 config instead of Orbot to avoid this delay."); } }; @@ -429,7 +463,7 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { if (!orbotHelper.checkTorReceier(mOpenVPNService)) VpnStatus.logError("Orbot does not seem to be installed!"); - mResumeHandler.postDelayed(orbotStatusTimeOutRunnable, 20 * 1000); + mResumeHandler.postDelayed(orbotStatusTimeOutRunnable, ORBOT_TIMEOUT_MS); orbotHelper.addStatusCallback(mOpenVPNService, statusCallback); orbotHelper.sendOrbotStartAndStatusBroadcast(); @@ -439,40 +473,6 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { } } - - private OrbotHelper.StatusCallback statusCallback = new OrbotHelper.StatusCallback() { - - @Override - public void onStatus(Intent statusIntent) { - String extras = ""; - for (String key : statusIntent.getExtras().keySet()) - extras += String.format(Locale.ENGLISH, "%s - '%s'", key, statusIntent.getExtras().getString(key, "[]")); - VpnStatus.logDebug("Got Orbot status: " + extras); - - } - - @Override - public void onNotYetInstalled() { - VpnStatus.logDebug("Orbot not yet installed"); - } - - @Override - public void onOrbotReady(Intent intent, String socksHost, int socksPort) { - mResumeHandler.removeCallbacks(orbotStatusTimeOutRunnable); - sendProxyCMD(Connection.ProxyType.SOCKS5, socksHost, Integer.toString(socksPort)); - OrbotHelper.get(mOpenVPNService).removeStatusCallback(this); - } - }; - - private Runnable orbotStatusTimeOutRunnable = new Runnable() { - @Override - public void run() { - sendProxyCMD(Connection.ProxyType.SOCKS5, "127.0.0.1", Integer.toString(OrbotHelper.SOCKS_PROXY_PORT_DEFAULT)); - OrbotHelper.get(mOpenVPNService).removeStatusCallback(statusCallback); - - } - }; - private void sendProxyCMD(Connection.ProxyType proxyType, String proxyname, String proxyport) { if (proxyType != Connection.ProxyType.NONE && proxyname != null) { diff --git a/main/src/main/java/de/blinkt/openvpn/core/OrbotHelper.java b/main/src/main/java/de/blinkt/openvpn/core/OrbotHelper.java index f2d7e0b9..68f5835f 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/OrbotHelper.java +++ b/main/src/main/java/de/blinkt/openvpn/core/OrbotHelper.java @@ -51,6 +51,8 @@ public class OrbotHelper { */ public final static String ACTION_STATUS = "org.torproject.android.intent.action.STATUS"; public final static String STATUS_ON = "ON"; + public final static String STATUS_STARTS_DISABLED = "STARTS_DISABLED"; + public final static String STATUS_STARTING = "STARTING"; public final static String STATUS_STOPPING = "STOPPING"; public final static String EXTRA_STATUS = "org.torproject.android.intent.extra.STATUS"; @@ -84,6 +86,9 @@ public class OrbotHelper { for (StatusCallback cb : statusCallbacks) { cb.onOrbotReady(intent, socksHost, socksPort); } + } else if (TextUtils.equals(status, STATUS_STARTS_DISABLED)) { + for (StatusCallback cb : statusCallbacks) + cb.onDisabled(intent); } } @@ -112,6 +117,16 @@ public class OrbotHelper { return intent; } + public static boolean checkTorReceier(Context c) { + Intent startOrbot = getOrbotStartIntent(c); + PackageManager pm = c.getPackageManager(); + Intent result = null; + List receivers = + pm.queryBroadcastReceivers(startOrbot, 0); + + return receivers != null && receivers.size() > 0; + } + /** * Adds a StatusCallback to be called when we find out that * Orbot is ready. If Orbot is ready for use, your callback @@ -156,16 +171,6 @@ public class OrbotHelper { mContext.startService(clearVPNMode); } - boolean checkTorReceier(Context c) { - Intent startOrbot = getOrbotStartIntent(c); - PackageManager pm = c.getPackageManager(); - Intent result = null; - List receivers = - pm.queryBroadcastReceivers(startOrbot, 0); - - return receivers != null && receivers.size() > 0; - } - public interface StatusCallback { /** * Called when Orbot is operational @@ -187,5 +192,11 @@ public class OrbotHelper { void onNotYetInstalled(); void onOrbotReady(Intent intent, String socksHost, int socksPort); + + /** + * Called if Orbot background control is disabled. + * @param intent the intent delivered + */ + void onDisabled(Intent intent); } } diff --git a/main/src/test/java/de/blinkt/openvpn/core/TestConfigGenerator.java b/main/src/test/java/de/blinkt/openvpn/core/TestConfigGenerator.java index 58e5c268..66e69ca5 100644 --- a/main/src/test/java/de/blinkt/openvpn/core/TestConfigGenerator.java +++ b/main/src/test/java/de/blinkt/openvpn/core/TestConfigGenerator.java @@ -6,9 +6,7 @@ package de.blinkt.openvpn.core; import android.content.Context; -import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.test.mock.MockContext; import junit.framework.Assert; @@ -18,17 +16,10 @@ import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; -import java.io.File; - -import static de.blinkt.openvpn.VpnProfile.TYPE_USERPASS; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - import de.blinkt.openvpn.VpnProfile; import static de.blinkt.openvpn.VpnProfile.AUTH_RETRY_NOINTERACT; +import static de.blinkt.openvpn.VpnProfile.TYPE_USERPASS; /** * Created by arne on 14.03.18. -- cgit v1.2.3