summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2021-04-15 19:21:13 +0200
committerArne Schwabe <arne@rfc2549.org>2021-04-15 19:21:13 +0200
commit6f12f5fffbe9f4eeb4a94e1b3d22b6cc9a3603a5 (patch)
tree1f6b18c238fa4ad59a476a61eda09391757182f6 /main
parent4c7280b50e4fe044f39c42fadf1b3f1789c99658 (diff)
Implement VPN http proxy support (Android 10+) (closes #1263)
Use dhcp-option PROXY_HTTP 1.2.3.4 8080 or push "dhcp-option PROXY_HTTP 1.2.3.4 8080" from a server to use the feature.
Diffstat (limited to 'main')
-rw-r--r--main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java45
-rw-r--r--main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java8
-rwxr-xr-xmain/src/main/res/values/strings.xml1
-rw-r--r--main/src/ui/java/de/blinkt/openvpn/core/OpenVPNThreadv3.java13
4 files changed, 60 insertions, 7 deletions
diff --git a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
index 23940760..d37f34ed 100644
--- a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
+++ b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
@@ -21,6 +21,7 @@ import android.content.pm.ShortcutManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.net.ConnectivityManager;
+import android.net.ProxyInfo;
import android.net.Uri;
import android.net.VpnService;
import android.os.Build;
@@ -141,6 +142,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
private Handler guiHandler;
private Toast mlastToast;
private Runnable mOpenVPNThread;
+ private ProxyInfo mProxyInfo;
// From: http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java
public static String humanReadableByteCount(long bytes, boolean speed, Resources res) {
@@ -744,6 +746,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
cfg += "dns: " + TextUtils.join("|", mDnslist);
cfg += "domain: " + mDomain;
cfg += "mtu: " + mMtu;
+ cfg += "proxyInfo: " + mProxyInfo;
return cfg;
}
@@ -869,20 +872,18 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
int ipv4len;
- if (mLocalIP!=null) {
- ipv4len=mLocalIP.len;
- ipv4info=mLocalIP.mIp;
+ if (mLocalIP != null) {
+ ipv4len = mLocalIP.len;
+ ipv4info = mLocalIP.mIp;
} else {
ipv4len = -1;
}
- if (mLocalIPv6!=null)
- {
+ if (mLocalIPv6 != null) {
ipv6info = mLocalIPv6;
}
- if ((!mRoutes.getNetworks(false).isEmpty() || !mRoutesv6.getNetworks(false).isEmpty()) && isLockdownEnabledCompat())
- {
+ if ((!mRoutes.getNetworks(false).isEmpty() || !mRoutesv6.getNetworks(false).isEmpty()) && isLockdownEnabledCompat()) {
VpnStatus.logInfo("VPN lockdown enabled (do not allow apps to bypass VPN) enabled. Route exclusion will not allow apps to bypass VPN (e.g. bypass VPN for local networks)");
}
@@ -890,6 +891,9 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
VpnStatus.logInfo(R.string.dns_server_info, TextUtils.join(", ", mDnslist), mDomain);
VpnStatus.logInfo(R.string.routes_info_incl, TextUtils.join(", ", mRoutes.getNetworks(true)), TextUtils.join(", ", mRoutesv6.getNetworks(true)));
VpnStatus.logInfo(R.string.routes_info_excl, TextUtils.join(", ", mRoutes.getNetworks(false)), TextUtils.join(", ", mRoutesv6.getNetworks(false)));
+ if (mProxyInfo != null) {
+ VpnStatus.logInfo(R.string.proxy_info, mProxyInfo.getHost(), mProxyInfo.getPort());
+ }
VpnStatus.logDebug(R.string.routes_debug, TextUtils.join(", ", positiveIPv4Routes), TextUtils.join(", ", positiveIPv6Routes));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
setAllowedVpnPackages(builder);
@@ -919,6 +923,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
if (mDnslist.size() == 0)
VpnStatus.logInfo(R.string.warn_no_dns);
+ setHttpProxy(builder);
+
mLastTunCfg = getTunConfigString();
// Reset information
@@ -928,6 +934,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
mLocalIP = null;
mLocalIPv6 = null;
mDomain = null;
+ mProxyInfo = null;
builder.setConfigureIntent(getGraphPendingIntent());
@@ -948,6 +955,17 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
+ private void setHttpProxy(Builder builder) {
+ if (mProxyInfo != null && Build.VERSION.SDK_INT >= 29)
+ {
+ builder.setHttpProxy(mProxyInfo);
+ }
+ else if (mProxyInfo != null)
+ {
+ VpnStatus.logWarning("HTTP Proxy needs Android 10 or later.");
+ }
+ }
+
private boolean isLockdownEnabledCompat() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
return isLockdownEnabled();
@@ -1068,6 +1086,17 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
mRoutes.addIP(route, include);
}
+ public boolean addHttpProxy(String proxy, int port) {
+ try {
+ mProxyInfo = ProxyInfo.buildDirectProxy(proxy, port);
+ } catch (Exception e)
+ {
+ VpnStatus.logError("Could not set proxy" + e.getLocalizedMessage());
+ return false;
+ }
+ return true;
+ }
+
public void addRoute(String dest, String mask, String gateway, String device) {
CIDRIP route = new CIDRIP(dest, mask);
boolean include = isAndroidTunDevice(device);
@@ -1342,4 +1371,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
mNotificationManager.notify(notificationId, notification);
}
+
+
}
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 305ab2a8..8228ccc2 100644
--- a/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java
+++ b/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java
@@ -612,6 +612,14 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {
// This not nice or anything but setFileDescriptors accepts only FilDescriptor class :(
break;
+ case "HTTPPROXY":
+ String[] httpproxy = extra.split(" ");
+ if (httpproxy.length == 2) {
+ mOpenVPNService.addHttpProxy(httpproxy[0], Integer.parseInt(httpproxy[1]));
+ } else {
+ VpnStatus.logError("Unrecognized HTTPPROXY cmd: " + Arrays.toString(httpproxy) + " | " + argument);
+ }
+ break;
default:
Log.e(TAG, "Unknown needok command " + argument);
return;
diff --git a/main/src/main/res/values/strings.xml b/main/src/main/res/values/strings.xml
index fc4f5a74..9a8e5958 100755
--- a/main/src/main/res/values/strings.xml
+++ b/main/src/main/res/values/strings.xml
@@ -502,5 +502,6 @@
<string name="faq_ncp">There are some variation of this message depending on the exact situation. They all have in common that server and client could not agree on a common cipher. The main reasons are: &lt;ul>&lt;li> You are still relying on the fact that OpenVPN 2.4 and older allowed BF-CBC in the default configuration (if no --cipher was set). OpenVPN 2.5 does not allow it per default anymore since it is a &lt;a href="https://community.openvpn.net/openvpn/wiki/SWEET32">broken/outdated cipher&lt;/a>.&lt;/li>&lt;li>The server runs OpenVPN 2.3 (or even older) with --enable-small (at least 4-5 year old OpenVPN)&lt;/li>&lt;li>Broken configuration (e.g., mismatching data-ciphers on client and server)&lt;/li> &lt;p> The &lt;a href=\"https://github.com/OpenVPN/openvpn/blob/master/doc/man-sections/cipher-negotiation.rst\">OpenVPN manual section on cipher negotiation&lt;/a> explains the different scenarios of cipher negotiation very well and what to do in these situation.&lt;p>TP-Link devices use a at least 5 year old OpenVPN 2.3.x version (possibly older) on their devices, even in the 2019/2020 models.&lt;p>Last but not least, there is a popular VPN provider that has a broken server that always says it is using \'BF-CBC\' because its developer thought it would be a good idea to create a proprietary cipher negotiation patch that is incompatible with standard OpenVPN.&lt;p>In summary: all sane configurations should not get these errors. But (apart from the broken VPN provider\'s server) the client can be persuaded to still connect (fixing the sympton and not the real problem).</string>
<string name="check_peer_fingerprint">Check peer certificate fingerprint</string>
<string name="fingerprint">(Enter the SHA256 fingerprint of the server certificate(s))</string>
+ <string name="proxy_info">HTTP Proxy: %1$s %2$d</string>
</resources>
diff --git a/main/src/ui/java/de/blinkt/openvpn/core/OpenVPNThreadv3.java b/main/src/ui/java/de/blinkt/openvpn/core/OpenVPNThreadv3.java
index c250dc5e..419f49e2 100644
--- a/main/src/ui/java/de/blinkt/openvpn/core/OpenVPNThreadv3.java
+++ b/main/src/ui/java/de/blinkt/openvpn/core/OpenVPNThreadv3.java
@@ -108,6 +108,18 @@ public class OpenVPNThreadv3 extends ClientAPI_OpenVPNClient implements Runnable
}
@Override
+ public boolean tun_builder_set_proxy_http(String host, int port)
+ {
+ return mService.addHttpProxy(host, port);
+ }
+
+ @Override
+ public boolean tun_builder_set_proxy_https(String host, int port)
+ {
+ return false;
+ }
+
+ @Override
public int tun_builder_establish() {
return mService.openTun().detachFd();
}
@@ -271,6 +283,7 @@ public class OpenVPNThreadv3 extends ClientAPI_OpenVPNClient implements Runnable
public void setPauseCallback(PausedStateCallback callback) {
}
+
@Override
public void sendCRResponse(String response) {
post_cc_msg("CR_RESPONSE," + response + "\n");