diff options
author | Mikael Magnusson <mikma@users.sourceforge.net> | 2022-12-29 00:23:17 +0100 |
---|---|---|
committer | Mikael Magnusson <mikma@users.sourceforge.net> | 2023-07-05 21:40:32 +0200 |
commit | 7a12989f6241fe4ab2f56707c20e7aa7810f1212 (patch) | |
tree | c3fd2edda45018963a9608af68350b5478246404 /tunnel/src/main/java/com/wireguard/android | |
parent | a0c1973bda70efb17490ac42c2111e8f1da2b4c3 (diff) |
ui,tunnel: auto-detect IPv6/IPv4 preference
Detect IP address change.
Request non-VPN network.
Update endpoint when needed.
Unregister network on wgTurnOff and use IPv4 if network is not known.
Diffstat (limited to 'tunnel/src/main/java/com/wireguard/android')
-rw-r--r-- | tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java | 52 |
1 files changed, 49 insertions, 3 deletions
diff --git a/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java b/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java index 242f81d8..19f328f2 100644 --- a/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java +++ b/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java @@ -7,6 +7,11 @@ package com.wireguard.android.backend; import android.content.Context; import android.content.Intent; +import android.net.ConnectivityManager; +import android.net.LinkProperties; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.net.NetworkRequest; import android.net.ProxyInfo; import android.os.Build; import android.os.ParcelFileDescriptor; @@ -23,6 +28,7 @@ import com.wireguard.config.Peer; import com.wireguard.crypto.Key; import com.wireguard.crypto.KeyFormatException; import com.wireguard.util.NonNullForAll; +import com.wireguard.util.Resolver; import java.net.InetAddress; import java.net.URL; @@ -52,6 +58,9 @@ public final class GoBackend implements Backend { @Nullable private Config currentConfig; @Nullable private Tunnel currentTunnel; private int currentTunnelHandle = -1; + private ConnectivityManager connectivityManager; + private ConnectivityManager.NetworkCallback myNetworkCallback = new MyNetworkCallback(); + @Nullable private Network activeNetwork; /** * Public constructor for GoBackend. @@ -61,6 +70,7 @@ public final class GoBackend implements Backend { public GoBackend(final Context context) { SharedLibraryLoader.loadSharedLibrary(context, "wg-go"); this.context = context; + connectivityManager = context.getSystemService(ConnectivityManager.class); } /** @@ -79,6 +89,8 @@ public final class GoBackend implements Backend { private static native int wgGetSocketV6(int handle); + private static native int wgSetConfig(int handle, String settings); + private static native void wgTurnOff(int handle); private static native int wgTurnOn(String ifName, int tunFd, String settings); @@ -258,13 +270,19 @@ public final class GoBackend implements Backend { } + activeNetwork = connectivityManager.getActiveNetwork(); + if (!connectivityManager.getNetworkCapabilities(activeNetwork).hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)) { + Log.w(TAG, "VPN network is active, null activeNetwork"); + activeNetwork = null; + } + final Resolver resolver = new Resolver(activeNetwork, connectivityManager.getLinkProperties(activeNetwork)); dnsRetry: for (int i = 0; i < DNS_RESOLUTION_RETRIES; ++i) { // Pre-resolve IPs so they're cached when building the userspace string for (final Peer peer : config.getPeers()) { final InetEndpoint ep = peer.getEndpoint().orElse(null); if (ep == null) continue; - if (ep.getResolved().orElse(null) == null) { + if (ep.getResolved(resolver, true).orElse(null) == null) { if (i < DNS_RESOLUTION_RETRIES - 1) { Log.w(TAG, "DNS host \"" + ep.getHost() + "\" failed to resolve; trying again"); Thread.sleep(1000); @@ -277,7 +295,7 @@ public final class GoBackend implements Backend { } // Build config - final String goConfig = config.toWgUserspaceString(); + final String goConfig = config.toWgUserspaceString(resolver); // Create the vpn tunnel with android API final VpnService.Builder builder = service.getBuilder(); @@ -339,6 +357,9 @@ public final class GoBackend implements Backend { service.protect(wgGetSocketV4(currentTunnelHandle)); service.protect(wgGetSocketV6(currentTunnelHandle)); + + NetworkRequest req = new NetworkRequest.Builder().addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN).build(); + connectivityManager.requestNetwork(req, myNetworkCallback); } else { if (currentTunnelHandle == -1) { Log.w(TAG, "Tunnel already down"); @@ -348,6 +369,8 @@ public final class GoBackend implements Backend { currentTunnel = null; currentTunnelHandle = -1; currentConfig = null; + connectivityManager.unregisterNetworkCallback(myNetworkCallback); + activeNetwork = null; wgTurnOff(handleToClose); try { vpnService.get(0, TimeUnit.NANOSECONDS).stopSelf(); @@ -415,8 +438,11 @@ public final class GoBackend implements Backend { if (owner != null) { final Tunnel tunnel = owner.currentTunnel; if (tunnel != null) { - if (owner.currentTunnelHandle != -1) + if (owner.currentTunnelHandle != -1) { + owner.connectivityManager.unregisterNetworkCallback(owner.myNetworkCallback); + owner.activeNetwork = null; wgTurnOff(owner.currentTunnelHandle); + } owner.currentTunnel = null; owner.currentTunnelHandle = -1; owner.currentConfig = null; @@ -442,4 +468,24 @@ public final class GoBackend implements Backend { this.owner = owner; } } + + private class MyNetworkCallback extends ConnectivityManager.NetworkCallback { + @Override + public void onAvailable(Network network) { + activeNetwork = network; + Log.w(TAG, "onAvailable: " + activeNetwork); + } + + @Override + public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) { + Log.w(TAG, "onLinkPropertiesChanged: " + network + " is default:" + (network.equals(activeNetwork))); + if (network.equals(activeNetwork) && currentConfig != null && currentTunnelHandle > -1) { + final Resolver resolver = new Resolver(network, linkProperties); + final String goConfig = currentConfig.toWgEndpointsUserspaceString(resolver); + Log.w(TAG, "is default network, config:" + goConfig); + + wgSetConfig(currentTunnelHandle, goConfig); + } + } + } } |