From c3f194b58823a03fac264b2d36d75aa9b4be35e8 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Sat, 2 Mar 2024 17:58:19 +0100 Subject: [PATCH] feat: update GoBackend.java --- .gitignore | 3 + core/build.gradle | 2 +- .../wireguard/android/backend/GoBackend.java | 89 +++++++++++ .../net/ivpn/core/common/v2ray/V2RayCore.kt | 143 ++++++++++++++++-- .../ivpn/core/vpn/wireguard/ConfigManager.kt | 27 ++-- v2ray/build.gradle | 2 +- 6 files changed, 243 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index 2220135e9..cece8ab65 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,10 @@ keystore.properties /.idea/ /core/.cxx/ core/.cxx/ +core/libs/ v2ray/libs/ +v2ray/*.jar +v2ray/*.aar /store/production/ /production/ liboqs-android/**/*.so diff --git a/core/build.gradle b/core/build.gradle index 9b54f9166..44740fbe7 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -73,7 +73,7 @@ android { sourceSets { main { - jniLibs.srcDir 'src/main/libs' + jniLibs.srcDir 'libs' assets.srcDirs = ["src/main/assets", "build/ovpnassets"] } } diff --git a/core/src/main/java/com/wireguard/android/backend/GoBackend.java b/core/src/main/java/com/wireguard/android/backend/GoBackend.java index d1f90b69a..506743c50 100644 --- a/core/src/main/java/com/wireguard/android/backend/GoBackend.java +++ b/core/src/main/java/com/wireguard/android/backend/GoBackend.java @@ -34,7 +34,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.File; +import java.io.FileDescriptor; +import java.io.IOException; import java.net.InetAddress; +import java.util.ArrayList; import java.util.Collection; import java.util.Objects; import java.util.Set; @@ -49,8 +53,22 @@ import de.blinkt.openvpn.core.CIDRIP; import de.blinkt.openvpn.core.NetworkSpace; +import android.net.LocalSocket; +import android.net.LocalSocketAddress; + @ApplicationScope public final class GoBackend implements Backend { + + private static final int VPN_MTU = 1280; + private static final String PRIVATE_VLAN4_CLIENT = "26.26.26.1"; + private static final String PRIVATE_VLAN4_ROUTER = "26.26.26.2"; + private static final String PRIVATE_VLAN6_CLIENT = "da26:2626::1"; + private static final String PRIVATE_VLAN6_ROUTER = "da26:2626::2"; + private static final String TUN2SOCKS = "libtun2socks.so"; + + private Process process; + private ParcelFileDescriptor mInterface; + private static final Logger LOGGER = LoggerFactory.getLogger(GoBackend.class); private static GhettoCompletableFuture vpnService = new GhettoCompletableFuture<>(); @@ -254,6 +272,8 @@ private void setStateInternal(final Tunnel tunnel, @Nullable final Config config throw new Exception("Go backend v" + wgVersion()); LOGGER.info("Tunnel already up"); currentTunnelHandle = wgTurnOn(tunnel.getName(), tun.detachFd(), goConfig); + mInterface = tun; + runTun2socks(tun); } if (currentTunnelHandle < 0) throw new Exception("Unable to turn tunnel on (wgTurnOn return " + currentTunnelHandle + ')'); @@ -280,6 +300,75 @@ private void setStateInternal(final Tunnel tunnel, @Nullable final Config config tunnel.onStateChange(state); } + private void runTun2socks(ParcelFileDescriptor tun) { + int socksPort = 16661; + ArrayList cmd = new ArrayList<>(); + cmd.add(new File(context.getApplicationInfo().nativeLibraryDir, TUN2SOCKS).getAbsolutePath()); + cmd.add("--netif-ipaddr"); + cmd.add(PRIVATE_VLAN4_ROUTER); + cmd.add("--netif-netmask"); + cmd.add("255.255.255.252"); + cmd.add("--socks-server-addr"); + cmd.add("127.0.0.1:" + socksPort); + cmd.add("--tunmtu"); + cmd.add(Integer.toString(VPN_MTU)); + cmd.add("--sock-path"); + cmd.add(new File(context.getFilesDir(), "sock_path").getAbsolutePath()); + cmd.add("--enable-udprelay"); + cmd.add("--loglevel"); + cmd.add("notice"); + + try { + ProcessBuilder proBuilder = new ProcessBuilder(cmd); + proBuilder.redirectErrorStream(true); + process = proBuilder + .directory(context.getFilesDir()) + .start(); + + new Thread(() -> { + Log.d("INFO RUN", TUN2SOCKS + " check"); + try { + process.waitFor(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + Log.d("INFO RUN", TUN2SOCKS + " exited"); + Log.d("INFO RUN", TUN2SOCKS + " restart"); + runTun2socks(tun); + }).start(); + + Log.d("INFO RUN", process.toString()); + + sendFd(tun); + } catch (IOException e) { + Log.d("INFO RUN", e.toString()); + } + } + + private void sendFd(ParcelFileDescriptor tun) { + int tries = 0; + while (true) { + try { + Thread.sleep(50L << tries); + Log.d("INFO SEND", "sendFd tries: " + tries); + FileDescriptor fd = tun.getFileDescriptor(); + String path = new File(context.getFilesDir(), "sock_path").getAbsolutePath(); + Log.d("INFO SEND", path); + + LocalSocket localSocket = new LocalSocket(); + localSocket.connect(new LocalSocketAddress(path, LocalSocketAddress.Namespace.FILESYSTEM)); + localSocket.setFileDescriptorsForSend(new FileDescriptor[]{fd}); + localSocket.getOutputStream().write(42); + + break; + } catch (Exception e) { + Log.d("INFO SEND", e.toString()); + if (tries > 5) break; + tries += 1; + } + } + } + private void addNotAllowedApps(android.net.VpnService.Builder builder) { Set disallowedApps = packagesPreference.getDisallowedPackages(); for (String app : disallowedApps) { diff --git a/core/src/main/java/net/ivpn/core/common/v2ray/V2RayCore.kt b/core/src/main/java/net/ivpn/core/common/v2ray/V2RayCore.kt index 55c692cb8..fd7f13289 100644 --- a/core/src/main/java/net/ivpn/core/common/v2ray/V2RayCore.kt +++ b/core/src/main/java/net/ivpn/core/common/v2ray/V2RayCore.kt @@ -22,33 +22,73 @@ package net.ivpn.core.common.v2ray along with the IVPN Android app. If not, see . */ +import android.net.LocalSocket +import android.net.LocalSocketAddress +import android.os.Build +import android.os.ParcelFileDescriptor +import android.util.Log +import android.content.Context +import kotlinx.coroutines.DelicateCoroutinesApi +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch import net.ivpn.core.common.dagger.ApplicationScope import net.ivpn.core.common.prefs.Settings -import v2rayControl.Instance -import v2rayControl.V2rayControl +import libv2ray.Libv2ray +import libv2ray.V2RayPoint +import libv2ray.V2RayVPNServiceSupportsSet +import java.io.File import javax.inject.Inject @ApplicationScope class V2RayCore @Inject constructor( - private val settings: Settings + private val settings: Settings, + private val context: Context ) { - private var instance: Instance? = null + companion object { + private const val VPN_MTU = 1500 + private const val PRIVATE_VLAN4_CLIENT = "26.26.26.1" + private const val PRIVATE_VLAN4_ROUTER = "26.26.26.2" + private const val PRIVATE_VLAN6_CLIENT = "da26:2626::1" + private const val PRIVATE_VLAN6_ROUTER = "da26:2626::2" + private const val TUN2SOCKS = "libtun2socks.so" + } + + private val v2rayPoint: V2RayPoint = Libv2ray.newV2RayPoint(V2RayCallback(), Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) + private lateinit var process: Process + private lateinit var mInterface: ParcelFileDescriptor + + fun start() { + if (isRunning()) { + return + } - fun start(){ - stop() val config = makeConfig() if (config != null) { - instance = V2rayControl.start(config.jsonString()) + v2rayPoint.configureFileContent = config.jsonString() + v2rayPoint.domainName = "127.0.0.1:16661" + try { + v2rayPoint.runLoop(false) +// runTun2socks() + } catch (e: Exception) { + println("Error system fucked up: " + e.message) + } } } fun stop() { - if (instance != null) { - V2rayControl.stop(instance) + try { + v2rayPoint.stopLoop() + } catch (e: Exception) { + println("Error system fucked up: " + e.message) } } + fun isRunning(): Boolean { + return v2rayPoint.isRunning + } + private fun makeConfig(): V2RayConfig? { val v2raySettings = settings.v2raySettings if (v2raySettings != null) { @@ -64,4 +104,89 @@ class V2RayCore @Inject constructor( return null } +// private fun runTun2socks() { +// val socksPort = 16661 +// val cmd = arrayListOf( +// File(context.applicationInfo.nativeLibraryDir, TUN2SOCKS).absolutePath, +// "--netif-ipaddr", PRIVATE_VLAN4_ROUTER, +// "--netif-netmask", "255.255.255.252", +// "--socks-server-addr", "127.0.0.1:${socksPort}", +// "--tunmtu", VPN_MTU.toString(), +// "--sock-path", File(context.filesDir, "sock_path").absolutePath,//File(applicationContext.filesDir, "sock_path").absolutePath, +// "--enable-udprelay", +// "--loglevel", "notice") +// +// try { +// val proBuilder = ProcessBuilder(cmd) +// proBuilder.redirectErrorStream(true) +// process = proBuilder +// .directory(context.filesDir) +// .start() +// Thread(Runnable { +// Log.d("INFO","$TUN2SOCKS check") +// process.waitFor() +// Log.d("INFO","$TUN2SOCKS exited") +// Log.d("INFO","$TUN2SOCKS restart") +// runTun2socks() +// }).start() +// Log.d("INFO", process.toString()) +// +// sendFd() +// } catch (e: Exception) { +// Log.d("INFO", e.toString()) +// } +// } + +// @OptIn(DelicateCoroutinesApi::class) +// private fun sendFd() { +// val fd = mInterface.fileDescriptor +// val path = File(context.filesDir, "sock_path").absolutePath +// Log.d("INFO", path) +// +// GlobalScope.launch(Dispatchers.IO) { +// var tries = 0 +// while (true) try { +// Thread.sleep(50L shl tries) +// Log.d("INFO", "sendFd tries: $tries") +// LocalSocket().use { localSocket -> +// localSocket.connect(LocalSocketAddress(path, LocalSocketAddress.Namespace.FILESYSTEM)) +// localSocket.setFileDescriptorsForSend(arrayOf(fd)) +// localSocket.outputStream.write(42) +// } +// break +// } catch (e: Exception) { +// Log.d("INFO", e.toString()) +// if (tries > 5) break +// tries += 1 +// } +// } +// } + + private class V2RayCallback : V2RayVPNServiceSupportsSet { + override fun shutdown(): Long { + println("V2RayCallback shutdown") + return 0 + } + + override fun prepare(): Long { + println("V2RayCallback prepare") + return 0 + } + + override fun protect(l: Long): Boolean { + println("V2RayCallback protect $l") + return true + } + + override fun onEmitStatus(l: Long, s: String?): Long { + println("V2RayCallback onEmitStatus $l $s") + return 0 + } + + override fun setup(s: String): Long { + println("V2RayCallback setup $s") + return 0 + } + } + } diff --git a/core/src/main/java/net/ivpn/core/vpn/wireguard/ConfigManager.kt b/core/src/main/java/net/ivpn/core/vpn/wireguard/ConfigManager.kt index 1fa1b1735..8272795ea 100644 --- a/core/src/main/java/net/ivpn/core/vpn/wireguard/ConfigManager.kt +++ b/core/src/main/java/net/ivpn/core/vpn/wireguard/ConfigManager.kt @@ -61,6 +61,7 @@ class ConfigManager @Inject constructor( fun startWireGuard() { applyConfigToTunnel(generateConfig()) + v2ray.start() GlobalScope.launch { tunnel?.setState(Tunnel.State.UP) } @@ -69,6 +70,7 @@ class ConfigManager @Inject constructor( fun stopWireGuard() { GlobalScope.launch { tunnel?.setState(Tunnel.State.DOWN) + v2ray.stop() } } @@ -116,7 +118,8 @@ class ConfigManager @Inject constructor( val peer = Peer().also { it.setAllowedIPsString("0.0.0.0/0, ::/0") - it.setEndpointString(host.host + ":" + port.portNumber) +// it.setEndpointString(host.host + ":" + port.portNumber) + it.setEndpointString("127.0.0.1:16661") it.publicKey = host.publicKey } @@ -192,17 +195,17 @@ class ConfigManager @Inject constructor( } private fun setV2ray(host: Host, port: Int) { - if (settings.v2ray) { - val v2raySettings = settings.v2raySettings - if (v2raySettings != null) { - v2raySettings.inboundIp = host.host - v2raySettings.inboundPort = v2raySettings.singleHopInboundPort - v2raySettings.outboundIp = host.v2ray - v2raySettings.outboundPort = port - v2raySettings.dnsName = host.dnsName - settings.v2raySettings = v2raySettings - } - } +// if (settings.v2ray) { + val v2raySettings = settings.v2raySettings + if (v2raySettings != null) { + v2raySettings.inboundIp = host.host + v2raySettings.inboundPort = v2raySettings.singleHopInboundPort + v2raySettings.outboundIp = host.v2ray + v2raySettings.outboundPort = port + v2raySettings.dnsName = host.dnsName + settings.v2raySettings = v2raySettings + } +// } } private fun getDNS(host: Host): String { diff --git a/v2ray/build.gradle b/v2ray/build.gradle index f6549d0c2..9641441b9 100644 --- a/v2ray/build.gradle +++ b/v2ray/build.gradle @@ -1,2 +1,2 @@ configurations.maybeCreate("default") -artifacts.add("default", file("libs/V2RayControl.aar")) +artifacts.add("default", file("libv2ray.aar"))