Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
AndroidUtils
VPNTunnelProxy
Commits
9f8064a3
Commit
9f8064a3
authored
Jul 15, 2019
by
Daniel Wolf
Browse files
Current state (sending data to tunnel works properly)
parent
844c14ad
Pipeline
#4971
passed with stages
in 44 seconds
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
library/build.gradle
View file @
9f8064a3
...
...
@@ -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-test
4
'
task
sourcesJar
(
type:
Jar
)
{
from
android
.
sourceSets
.
main
.
java
.
srcDirs
...
...
library/src/main/java/com/frostnerd/vpntunnelproxy/IpWrappingUdpTunnel.kt
View file @
9f8064a3
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
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment