Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Obfuscation with V2Ray lite #367

Open
wants to merge 2 commits into
base: feature/v2ray
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ android {

sourceSets {
main {
jniLibs.srcDir 'src/main/libs'
jniLibs.srcDir 'libs'
assets.srcDirs = ["src/main/assets", "build/ovpnassets"]
}
}
Expand Down
89 changes: 89 additions & 0 deletions core/src/main/java/com/wireguard/android/backend/GoBackend.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<WireGuardVpnService> vpnService = new GhettoCompletableFuture<>();
Expand Down Expand Up @@ -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 + ')');
Expand All @@ -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<String> 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<String> disallowedApps = packagesPreference.getDisallowedPackages();
for (String app : disallowedApps) {
Expand Down
143 changes: 134 additions & 9 deletions core/src/main/java/net/ivpn/core/common/v2ray/V2RayCore.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,33 +22,73 @@ package net.ivpn.core.common.v2ray
along with the IVPN Android app. If not, see <https://www.gnu.org/licenses/>.
*/

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) {
Expand All @@ -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
}
}

}
27 changes: 15 additions & 12 deletions core/src/main/java/net/ivpn/core/vpn/wireguard/ConfigManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class ConfigManager @Inject constructor(

fun startWireGuard() {
applyConfigToTunnel(generateConfig())
v2ray.start()
GlobalScope.launch {
tunnel?.setState(Tunnel.State.UP)
}
Expand All @@ -69,6 +70,7 @@ class ConfigManager @Inject constructor(
fun stopWireGuard() {
GlobalScope.launch {
tunnel?.setState(Tunnel.State.DOWN)
v2ray.stop()
}
}

Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion v2ray/build.gradle
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
configurations.maybeCreate("default")
artifacts.add("default", file("libs/V2RayControl.aar"))
artifacts.add("default", file("libv2ray.aar"))
Loading