Commit 9f8064a3 authored by Daniel Wolf's avatar Daniel Wolf
Browse files

Current state (sending data to tunnel works properly)

parent 844c14ad
Pipeline #4971 passed with stages
in 44 seconds
......@@ -67,7 +67,7 @@ configurations.all {
def libraryGroupId = 'com.frostnerd.utilskt'
def libraryArtifactId = 'vpntunnelproxy'
def libraryVersion = '2.3.29-test'
def libraryVersion = '2.3.29-test4'
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
......
package com.frostnerd.vpntunnelproxy
import android.os.ParcelFileDescriptor
import androidx.annotation.Size
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
......@@ -40,18 +41,28 @@ class IpWrappingUdpTunnel(val bindAddress: InetAddress = InetAddress.getLocalHos
val coroutineScope: CoroutineScope = GlobalScope,
val socketReadCoroutineContext: CoroutineContext,
val tunnelReadCoroutineContext: CoroutineContext) {
private val fileDescriptor by lazy {
private val tunnelOutputPipes by lazy {
ParcelFileDescriptor.createReliablePipe()
}
private val tunnelOutputPipe by lazy {
fileDescriptor[0]
tunnelOutputPipes[0]
}
private val tunnelOutput by lazy {
FileOutputStream(tunnelOutputPipe.fileDescriptor)
FileOutputStream(tunnelOutputPipes[1].fileDescriptor)
}
private val tunnelInputPipes by lazy {
ParcelFileDescriptor.createReliablePipe()
}
private val tunnelInputPipe by lazy {
tunnelInputPipes[1]
}
private val tunnelInput by lazy {
FileInputStream(tunnelInputPipes[0].fileDescriptor)
}
private var stopped = false
private var socketReadJob: Job? = null
private var socketWriteJob:Job? = null
private var socket:DatagramSocket? = null
fun start(tunnelProxy: VPNTunnelProxy) {
......@@ -62,6 +73,7 @@ class IpWrappingUdpTunnel(val bindAddress: InetAddress = InetAddress.getLocalHos
while (!stopped) {
val packet = DatagramPacket(receiveData, receiveData.size)
localSocket.receive(packet)
println("RECEIVED PACKET")
val udpPayload = UdpPacket.Builder()
.srcPort(UdpPort(packet.port.toShort(), ""))
.dstPort(UdpPort(bindPort.toShort(), ""))
......@@ -99,14 +111,140 @@ class IpWrappingUdpTunnel(val bindAddress: InetAddress = InetAddress.getLocalHos
tunnelOutput.write(packetToTunnel)
}
}
tunnelProxy.run(tunnelOutputPipe, ParcelFileDescriptor.fromDatagramSocket(localSocket))
socketWriteJob = coroutineScope.launch(tunnelReadCoroutineContext) {
val bytes = ByteArray(32767)
while(!stopped) {
val read = tunnelInput.read(bytes)
if(read != -1) {
val actualBytes = ByteArray(read)
System.arraycopy(bytes, 0, actualBytes, 0, read)
val packet = _parseIpPacket(actualBytes)
val datagramPacket = DatagramPacket(packet.dnsPayload!!, 0, packet.dnsPayload.size, packet.destinationAddress, packet.destinationPort)
println("SENDING PACKET TO ${packet.destinationAddress}:${packet.destinationPort}")
localSocket.send(datagramPacket)
}
}
}
tunnelProxy.run(tunnelOutputPipe, tunnelInputPipe)
}
fun stop() {
stopped = true
socketReadJob?.cancel()
socketReadJob = null
socketWriteJob?.cancel()
socketWriteJob = null
socket?.close()
socket = null
}
private fun _parseIpPacket(bytes:ByteArray):ParsedPacket {
val version = (bytes[0].toIntWithUnsigned() shr 4) and 0x0f
val sourceIpBytes:ByteArray
val targetIpBytes:ByteArray
val sourceIp:InetAddress
val targetIp:InetAddress
val sourcePort:Int
val targetPort:Int
val payload:ByteArray?
when (version) {
4 -> {
val headerLength = (bytes[0].toIntWithUnsigned() and 0x0f)*4
sourceIpBytes = ByteArray(4)
targetIpBytes = ByteArray(4)
System.arraycopy(bytes, 12, sourceIpBytes, 0, 4)
System.arraycopy(bytes, 16, targetIpBytes, 0, 4)
sourceIp = Inet4Address.getByAddress(sourceIpBytes)
targetIp = Inet4Address.getByAddress(targetIpBytes)
val udpPayload = ByteArray(bytes.size - headerLength)
if(udpPayload.isNotEmpty()) {
System.arraycopy(bytes, headerLength, udpPayload, 0, bytes.size - headerLength)
sourcePort = ((udpPayload[0].toIntWithUnsigned()and 255) shl 8) + (udpPayload[1].toIntWithUnsigned() and 255)
targetPort = ((udpPayload[2].toIntWithUnsigned()and 255) shl 8) + (udpPayload[3].toIntWithUnsigned() and 255)
payload = ByteArray(udpPayload.size - 8)
System.arraycopy(udpPayload, 8, payload, 0, udpPayload.size - 8)
} else {
sourcePort = -1
targetPort = -1
payload = null
}
return ParsedV4Packet(version, sourceIp, targetIp, sourcePort, targetPort, payload)
}
6 -> {
sourceIpBytes = ByteArray(16)
targetIpBytes = ByteArray(16)
System.arraycopy(bytes, 8, sourceIpBytes, 0, 16)
System.arraycopy(bytes, 24, targetIpBytes, 0, 16)
sourceIp = Inet6Address.getByAddress(sourceIpBytes)
targetIp = Inet6Address.getByAddress(targetIpBytes)
val trafficClass = ((bytes[0].toIntWithUnsigned() and 0x0f) shr 4) + ((bytes[1].toInt() and 0xf0) shl 4)
val flowLabel = ((bytes[1].toIntWithUnsigned() and 0x0f) shl 16) + (bytes[2].toIntWithUnsigned() shl 8) + bytes[3]
val udpPayload = ByteArray(bytes.size - 40)
if (udpPayload.isNotEmpty()) {
System.arraycopy(bytes, 40, udpPayload, 0, bytes.size - 40)
sourcePort = ((udpPayload[0].toIntWithUnsigned()and 255) shl 8) + (udpPayload[1].toIntWithUnsigned() and 255)
targetPort = ((udpPayload[2].toIntWithUnsigned()and 255) shl 8) + (udpPayload[3].toIntWithUnsigned() and 255)
payload = ByteArray(udpPayload.size - 8)
System.arraycopy(udpPayload, 8, payload, 0, udpPayload.size - 8)
} else {
sourcePort = -1
targetPort = -1
payload = null
}
return ParsedV6Packet(trafficClass.toByte(), flowLabel, version, sourceIp, targetIp, sourcePort, targetPort, payload)
}
else -> throw IllegalStateException()
}
}
private fun Byte.toIntWithUnsigned():Int {
return toUByte().toInt()
}
}
abstract class ParsedPacket(val sourceAddress: InetAddress,
val destinationAddress: InetAddress,
val sourcePort: Int,
val destinationPort: Int,
val dnsPayload: ByteArray?)
class ParsedUdpPacket(sourceAddress: InetAddress,
destinationAddress: InetAddress,
sourcePort: Int,
destinationPort: Int,
dnsPayload: ByteArray?):ParsedPacket(sourceAddress, destinationAddress, sourcePort, destinationPort, dnsPayload)
abstract class ParsedIPPacket(val ipVersion: Int,
sourceAddress: InetAddress,
destinationAddress: InetAddress,
sourcePort: Int,
destinationPort: Int,
@Size(min = 0)
dnsPayload: ByteArray?):ParsedPacket(sourceAddress, destinationAddress, sourcePort, destinationPort, dnsPayload) {
override fun toString(): String {
return "ParsedPacket(ipVersion=$ipVersion, sourceAddress=$sourceAddress, destinationAddress=$destinationAddress, sourcePort=$sourcePort, destinationPort=$destinationPort)"
}
}
class ParsedV4Packet(ipVersion: Int,
sourceAddress: InetAddress,
destinationAddress: InetAddress,
sourcePort: Int,
destinationPort: Int,
dnsPayload: ByteArray?) : ParsedIPPacket(ipVersion, sourceAddress, destinationAddress, sourcePort, destinationPort, dnsPayload) {
}
class ParsedV6Packet(val trafficClass: Byte,
val flowLabel:Int,
ipVersion: Int,
sourceAddress: InetAddress,
destinationAddress: InetAddress,
sourcePort: Int,
destinationPort: Int,
dnsPayload: ByteArray?) : ParsedIPPacket(ipVersion, sourceAddress, destinationAddress, sourcePort, destinationPort, dnsPayload) {
override fun toString(): String {
return "ParsedV6Packet(trafficClass=$trafficClass, flowLabel=$flowLabel) ${super.toString()}"
}
}
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment