work blyattt
This commit is contained in:
@ -68,6 +68,7 @@ tasks.register("generateTestServerConfig") {
|
|||||||
{
|
{
|
||||||
"type": "server",
|
"type": "server",
|
||||||
"address": "10.1.0.1",
|
"address": "10.1.0.1",
|
||||||
|
"outInterface": "enp9s0",
|
||||||
"port": 9093
|
"port": 9093
|
||||||
}
|
}
|
||||||
""".trimIndent())
|
""".trimIndent())
|
||||||
|
|||||||
270
src/main/c/tun.c
270
src/main/c/tun.c
@ -1,5 +1,15 @@
|
|||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <linux/netlink.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
#include <linux/if_link.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <linux/if_tun.h>
|
#include <linux/if_tun.h>
|
||||||
#include <linux/if.h>
|
#include <linux/if.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
@ -10,6 +20,81 @@
|
|||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL
|
||||||
|
Java_su_sonoma_TunDevice_addDefaultRoute(
|
||||||
|
JNIEnv *env,
|
||||||
|
jobject obj,
|
||||||
|
jstring ifname
|
||||||
|
) {
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct nlmsghdr nlh;
|
||||||
|
struct rtmsg rtm;
|
||||||
|
char buf[4096];
|
||||||
|
} req;
|
||||||
|
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
|
||||||
|
const char *c_ifname = (*env)->GetStringUTFChars(env, ifname, 0);
|
||||||
|
|
||||||
|
if (c_ifname == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ifindex = if_nametoindex(c_ifname);
|
||||||
|
|
||||||
|
req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
|
||||||
|
req.nlh.nlmsg_type = RTM_NEWROUTE;
|
||||||
|
req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE;
|
||||||
|
req.nlh.nlmsg_seq = 1;
|
||||||
|
req.nlh.nlmsg_pid = getpid();
|
||||||
|
|
||||||
|
req.rtm.rtm_family = AF_INET;
|
||||||
|
req.rtm.rtm_table = RT_TABLE_MAIN;
|
||||||
|
req.rtm.rtm_protocol = RTPROT_STATIC;
|
||||||
|
req.rtm.rtm_scope = RT_SCOPE_UNIVERSE;
|
||||||
|
req.rtm.rtm_type = RTN_UNICAST;
|
||||||
|
req.rtm.rtm_dst_len = 0;
|
||||||
|
|
||||||
|
struct rtattr *rta = (struct rtattr *) (((char *) &req) + NLMSG_ALIGN(req.nlh.nlmsg_len));
|
||||||
|
rta->rta_type = RTA_OIF;
|
||||||
|
rta->rta_len = RTA_LENGTH(sizeof(int));
|
||||||
|
*(int *) RTA_DATA(rta) = ifindex;
|
||||||
|
|
||||||
|
req.nlh.nlmsg_len = NLMSG_ALIGN(req.nlh.nlmsg_len) + RTA_LENGTH(sizeof(int));
|
||||||
|
|
||||||
|
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||||
|
if (sock < 0) {
|
||||||
|
perror("socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_nl addr;
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.nl_family = AF_NETLINK;
|
||||||
|
|
||||||
|
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||||
|
perror("bind");
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_nl kernel;
|
||||||
|
memset(&kernel, 0, sizeof(kernel));
|
||||||
|
kernel.nl_family = AF_NETLINK;
|
||||||
|
|
||||||
|
if (sendto(sock, &req, req.nlh.nlmsg_len, 0,
|
||||||
|
(struct sockaddr *)&kernel, sizeof(kernel)) < 0) {
|
||||||
|
perror("sendto");
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(sock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int tun_set_up(const char *ifname) {
|
static int tun_set_up(const char *ifname) {
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
@ -99,3 +184,188 @@ Java_su_sonoma_TunDevice_ioctlTun(
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int add_route(const char *ifname, const char *cidr) {
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct nlmsghdr nlh;
|
||||||
|
struct rtmsg rtm;
|
||||||
|
char buf[256];
|
||||||
|
} req;
|
||||||
|
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
|
||||||
|
int ifindex = if_nametoindex(ifname);
|
||||||
|
|
||||||
|
if (ifindex == 0) {
|
||||||
|
perror("if_nametoindex");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char ip[64];
|
||||||
|
int prefix;
|
||||||
|
|
||||||
|
if (sscanf(cidr, "%63[^/]/%d", ip, &prefix) != 2) {
|
||||||
|
fprintf(stderr, "Invalid CIDR\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct in_addr dst;
|
||||||
|
|
||||||
|
if (inet_pton(AF_INET, ip, &dst) != 1) {
|
||||||
|
perror("inet_pton");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
|
||||||
|
req.nlh.nlmsg_type = RTM_NEWROUTE;
|
||||||
|
|
||||||
|
req.nlh.nlmsg_flags =
|
||||||
|
NLM_F_REQUEST |
|
||||||
|
NLM_F_CREATE |
|
||||||
|
NLM_F_EXCL;
|
||||||
|
|
||||||
|
req.rtm.rtm_family = AF_INET;
|
||||||
|
req.rtm.rtm_table = RT_TABLE_MAIN;
|
||||||
|
req.rtm.rtm_protocol = RTPROT_STATIC;
|
||||||
|
req.rtm.rtm_scope = RT_SCOPE_LINK;
|
||||||
|
req.rtm.rtm_type = RTN_UNICAST;
|
||||||
|
|
||||||
|
req.rtm.rtm_dst_len = prefix;
|
||||||
|
|
||||||
|
struct rtattr *rta;
|
||||||
|
|
||||||
|
rta = (struct rtattr *)
|
||||||
|
(((char *)&req) + NLMSG_ALIGN(req.nlh.nlmsg_len));
|
||||||
|
|
||||||
|
rta->rta_type = RTA_DST;
|
||||||
|
rta->rta_len = RTA_LENGTH(sizeof(dst));
|
||||||
|
|
||||||
|
memcpy(RTA_DATA(rta), &dst, sizeof(dst));
|
||||||
|
|
||||||
|
req.nlh.nlmsg_len =
|
||||||
|
NLMSG_ALIGN(req.nlh.nlmsg_len) +
|
||||||
|
RTA_LENGTH(sizeof(dst));
|
||||||
|
|
||||||
|
rta = (struct rtattr *)
|
||||||
|
(((char *)&req) + NLMSG_ALIGN(req.nlh.nlmsg_len));
|
||||||
|
|
||||||
|
rta->rta_type = RTA_OIF;
|
||||||
|
rta->rta_len = RTA_LENGTH(sizeof(int));
|
||||||
|
|
||||||
|
memcpy(RTA_DATA(rta), &ifindex, sizeof(int));
|
||||||
|
|
||||||
|
req.nlh.nlmsg_len =
|
||||||
|
NLMSG_ALIGN(req.nlh.nlmsg_len) +
|
||||||
|
RTA_LENGTH(sizeof(int));
|
||||||
|
|
||||||
|
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||||
|
|
||||||
|
if (sock < 0) {
|
||||||
|
perror("socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_nl nladdr;
|
||||||
|
memset(&nladdr, 0, sizeof(nladdr));
|
||||||
|
|
||||||
|
nladdr.nl_family = AF_NETLINK;
|
||||||
|
|
||||||
|
if (sendto(
|
||||||
|
sock,
|
||||||
|
&req,
|
||||||
|
req.nlh.nlmsg_len,
|
||||||
|
0,
|
||||||
|
(struct sockaddr *)&nladdr,
|
||||||
|
sizeof(nladdr)
|
||||||
|
) < 0) {
|
||||||
|
|
||||||
|
perror("sendto");
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(sock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL
|
||||||
|
Java_su_sonoma_TunDevice_addRoute(
|
||||||
|
JNIEnv *env,
|
||||||
|
jobject obj,
|
||||||
|
jstring ifname,
|
||||||
|
jstring cidr
|
||||||
|
) {
|
||||||
|
|
||||||
|
const char *c_ifname =
|
||||||
|
(*env)->GetStringUTFChars(env, ifname, 0);
|
||||||
|
|
||||||
|
const char *c_cidr =
|
||||||
|
(*env)->GetStringUTFChars(env, cidr, 0);
|
||||||
|
|
||||||
|
if (!c_ifname || !c_cidr) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = add_route(c_ifname, c_cidr);
|
||||||
|
|
||||||
|
(*env)->ReleaseStringUTFChars(env, ifname, c_ifname);
|
||||||
|
(*env)->ReleaseStringUTFChars(env, cidr, c_cidr);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL
|
||||||
|
Java_su_sonoma_TunDevice_enableIpForwarding(
|
||||||
|
JNIEnv *env,
|
||||||
|
jobject obj
|
||||||
|
) {
|
||||||
|
|
||||||
|
int fd = open(
|
||||||
|
"/proc/sys/net/ipv4/ip_forward",
|
||||||
|
O_WRONLY
|
||||||
|
);
|
||||||
|
|
||||||
|
if (fd < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *value = "1";
|
||||||
|
|
||||||
|
ssize_t result = write(fd, value, 1);
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return result == 1 ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL
|
||||||
|
Java_su_sonoma_TunDevice_enableMasquerade(
|
||||||
|
JNIEnv *env,
|
||||||
|
jobject obj,
|
||||||
|
jstring iface
|
||||||
|
) {
|
||||||
|
|
||||||
|
const char *c_iface =
|
||||||
|
(*env)->GetStringUTFChars(env, iface, 0);
|
||||||
|
|
||||||
|
if (c_iface == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char command[256];
|
||||||
|
|
||||||
|
snprintf(
|
||||||
|
command,
|
||||||
|
sizeof(command),
|
||||||
|
"iptables -t nat -A POSTROUTING -o %s -j MASQUERADE",
|
||||||
|
c_iface
|
||||||
|
);
|
||||||
|
|
||||||
|
int result = system(command);
|
||||||
|
|
||||||
|
(*env)->ReleaseStringUTFChars(env, iface, c_iface);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@ -1,48 +1,75 @@
|
|||||||
package su.sonoma
|
package su.sonoma
|
||||||
|
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
|
import java.io.BufferedInputStream
|
||||||
|
import java.io.BufferedOutputStream
|
||||||
import java.io.DataInputStream
|
import java.io.DataInputStream
|
||||||
import java.net.Socket
|
import java.net.Socket
|
||||||
|
|
||||||
fun startClient(host: String, address: String, port: Int) = runBlocking {
|
fun startClient(host: String, address: String, port: Int, tun: String) = runBlocking {
|
||||||
println("Client started")
|
println("Client started")
|
||||||
val tun = TunDevice(address)
|
val tun = TunDevice(address, tun)
|
||||||
|
tun.addDefaultRoute()
|
||||||
|
|
||||||
println("Client trying to connect - $host:$port")
|
println("Client trying to connect - $host:$port")
|
||||||
val socket = Socket(host, port)
|
val socket = Socket(host, port)
|
||||||
|
println("Client trying connected - $host:$port")
|
||||||
|
|
||||||
val input = socket.getInputStream()
|
launch(Dispatchers.IO) {
|
||||||
val output = socket.getOutputStream()
|
try {
|
||||||
|
handleClient(socket, tun)
|
||||||
println("Client trying to pair")
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
launch {
|
|
||||||
val buffer = ByteArray(32768)
|
|
||||||
println("Client connected - $host:$port")
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
val len = tun.input.read(buffer)
|
|
||||||
|
|
||||||
if (len > 0) {
|
|
||||||
output.write(len shr 8)
|
|
||||||
output.write(len)
|
|
||||||
|
|
||||||
output.write(buffer, 0, len)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
launch {
|
launch(Dispatchers.IO) {
|
||||||
val buffer = ByteArray(32768)
|
try {
|
||||||
|
forwardClient(socket, tun)
|
||||||
while (true) {
|
} catch (e: Exception) {
|
||||||
val hi = input.read()
|
e.printStackTrace()
|
||||||
val lo = input.read()
|
|
||||||
val len = (hi shl 8) or lo
|
|
||||||
|
|
||||||
DataInputStream(input).readFully(buffer, 0, len)
|
|
||||||
|
|
||||||
tun.output.write(buffer, 0, len)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun forwardClient(socket: Socket, tun: TunDevice) {
|
||||||
|
val buffer = ByteArray(1500)
|
||||||
|
val input = BufferedInputStream(socket.getInputStream())
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
val hi = input.read()
|
||||||
|
if (hi == -1) break
|
||||||
|
|
||||||
|
val lo = input.read()
|
||||||
|
if (lo == -1) break
|
||||||
|
|
||||||
|
val len = (hi shl 8) or lo
|
||||||
|
//println("Message length: $len")
|
||||||
|
|
||||||
|
var read = 0
|
||||||
|
while (read < len) {
|
||||||
|
val r = input.read(buffer, read, len - read)
|
||||||
|
if (r == -1) break
|
||||||
|
read += r
|
||||||
|
}
|
||||||
|
|
||||||
|
tun.output.write(buffer, 0, read)
|
||||||
|
tun.output.flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun handleClient(socket: Socket, tun: TunDevice) {
|
||||||
|
val output = BufferedOutputStream(socket.getOutputStream())
|
||||||
|
val buffer = ByteArray(1500)
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
val len = tun.input.read(buffer)
|
||||||
|
if (len <= 0) continue
|
||||||
|
|
||||||
|
output.write((len shr 8) and 0xFF)
|
||||||
|
output.write(len and 0xFF)
|
||||||
|
output.write(buffer, 0, len)
|
||||||
|
output.flush()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -8,6 +8,8 @@ import java.io.File
|
|||||||
data class Config(
|
data class Config(
|
||||||
val type: String,
|
val type: String,
|
||||||
val host: String? = null,
|
val host: String? = null,
|
||||||
|
val tun: String = "awake0",
|
||||||
|
val outInterface: String = "eth0",
|
||||||
val address: String,
|
val address: String,
|
||||||
val port: Int,
|
val port: Int,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -7,8 +7,8 @@ fun main(args: Array<String>) {
|
|||||||
val config = loadConfig(File(configArg))
|
val config = loadConfig(File(configArg))
|
||||||
|
|
||||||
when (config.type) {
|
when (config.type) {
|
||||||
"server" -> startServer(config.address, config.port)
|
"server" -> startServer(config.address, config.port, config.tun, config.outInterface)
|
||||||
"client" -> startClient(config.host ?: error("Invalid config"), config.address, config.port)
|
"client" -> startClient(config.host ?: error("Invalid config"), config.address, config.port, config.tun)
|
||||||
else -> {
|
else -> {
|
||||||
error("Invalid type")
|
error("Invalid type")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,17 @@
|
|||||||
package su.sonoma
|
package su.sonoma
|
||||||
|
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
|
import java.io.BufferedInputStream
|
||||||
|
import java.io.BufferedOutputStream
|
||||||
import java.net.ServerSocket
|
import java.net.ServerSocket
|
||||||
import java.net.Socket
|
import java.net.Socket
|
||||||
import java.io.DataInputStream
|
import java.io.DataInputStream
|
||||||
|
|
||||||
fun startServer(address: String, port: Int) = runBlocking {
|
fun startServer(address: String, port: Int, tun: String, outIntefrace: String) = runBlocking {
|
||||||
val tun = TunDevice(address)
|
val tun = TunDevice(address, "awake0")
|
||||||
|
tun.addRoute()
|
||||||
|
tun.enableIpForwarding()
|
||||||
|
tun.enableMasquerade(outIntefrace)
|
||||||
|
|
||||||
val server = ServerSocket(port)
|
val server = ServerSocket(port)
|
||||||
println("Server started on $port")
|
println("Server started on $port")
|
||||||
@ -21,55 +26,80 @@ fun startServer(address: String, port: Int) = runBlocking {
|
|||||||
try {
|
try {
|
||||||
handle(client, tun)
|
handle(client, tun)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
println("${client.inetAddress} Client disconnected: ${e.message}")
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
launch(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
forward(client, tun)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun handle(socket: Socket, tun: TunDevice) {
|
fun handle(socket: Socket, tun: TunDevice) {
|
||||||
val input = withContext(Dispatchers.IO) {
|
|
||||||
socket.getInputStream()
|
|
||||||
}
|
|
||||||
val output = withContext(Dispatchers.IO) {
|
|
||||||
socket.getOutputStream()
|
|
||||||
}
|
|
||||||
|
|
||||||
val buffer = ByteArray(32768)
|
val input = BufferedInputStream(socket.getInputStream())
|
||||||
|
|
||||||
withContext(Dispatchers.IO) {
|
val buffer = ByteArray(1500)
|
||||||
while (true) {
|
|
||||||
|
|
||||||
val hi = input.read()
|
while (true) {
|
||||||
|
|
||||||
val lo = input.read()
|
val hi = input.read()
|
||||||
|
val lo = input.read()
|
||||||
|
|
||||||
val len = (hi shl 8) or lo
|
if (hi == -1 || lo == -1) {
|
||||||
|
println("${socket.inetAddress} Client disconnected")
|
||||||
DataInputStream(input).readFully(buffer, 0, len)
|
break
|
||||||
|
|
||||||
val packet = buffer.copyOf(len)
|
|
||||||
|
|
||||||
val response = forwardPacket(packet)
|
|
||||||
|
|
||||||
//output.write(response.size shr 8)
|
|
||||||
//output.write(response.size)
|
|
||||||
//output.write(response)
|
|
||||||
tun.output.write(packet, 0, len)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val len = (hi shl 8) or lo
|
||||||
|
|
||||||
|
//println("Message length: $len")
|
||||||
|
|
||||||
|
if (len <= 0 || len > buffer.size) {
|
||||||
|
println("Invalid packet size: $len")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
var offset = 0
|
||||||
|
while (offset < len) {
|
||||||
|
val r = input.read(buffer, offset, len - offset)
|
||||||
|
|
||||||
|
//println("Read $r from client")
|
||||||
|
|
||||||
|
if (r == -1) {
|
||||||
|
println("${socket.inetAddress} Client closed stream")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
offset += r
|
||||||
|
}
|
||||||
|
|
||||||
|
runCatching {
|
||||||
|
tun.output.write(buffer, 0, len)
|
||||||
|
tun.output.flush()
|
||||||
|
}
|
||||||
|
//println("Write in tun")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun forwardPacket(packet: ByteArray): ByteArray {
|
|
||||||
val host = "localhost"
|
|
||||||
val port = 1080
|
|
||||||
|
|
||||||
val socket = Socket(host, port)
|
fun forward(socket: Socket, tun: TunDevice) {
|
||||||
|
|
||||||
socket.getOutputStream().write(packet)
|
val readBuffer = ByteArray(1500)
|
||||||
|
val output = BufferedOutputStream(socket.getOutputStream())
|
||||||
|
|
||||||
val response = socket.getInputStream().readBytes()
|
while (true) {
|
||||||
|
val responseLen = tun.input.read(readBuffer)
|
||||||
|
if (responseLen > 0) {
|
||||||
|
|
||||||
socket.close()
|
output.write((responseLen shr 8) and 0xFF)
|
||||||
|
output.write(responseLen and 0xFF)
|
||||||
|
|
||||||
return response
|
output.write(readBuffer, 0, responseLen)
|
||||||
|
output.flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -5,11 +5,13 @@ import java.io.FileDescriptor
|
|||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.io.RandomAccessFile
|
import java.io.RandomAccessFile
|
||||||
|
import java.nio.channels.DatagramChannel
|
||||||
|
import java.nio.channels.FileChannel
|
||||||
|
|
||||||
class TunDevice(
|
class TunDevice(
|
||||||
private val ip: String
|
private val ip: String,
|
||||||
|
private val name: String
|
||||||
) {
|
) {
|
||||||
val name: String = "tun0"
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
init {
|
init {
|
||||||
@ -46,4 +48,30 @@ class TunDevice(
|
|||||||
ip: String,
|
ip: String,
|
||||||
flags: Int
|
flags: Int
|
||||||
): Int
|
): Int
|
||||||
|
|
||||||
|
private external fun addDefaultRoute(
|
||||||
|
name: String,
|
||||||
|
): Int
|
||||||
|
|
||||||
|
fun addDefaultRoute() {
|
||||||
|
addDefaultRoute(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
private external fun addRoute(ifName: String, cidr: String): Int
|
||||||
|
|
||||||
|
fun addRoute() {
|
||||||
|
addRoute(name, toCidr24(ip))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toCidr24(ip: String): String {
|
||||||
|
val parts = ip.split(".")
|
||||||
|
|
||||||
|
require(parts.size == 4)
|
||||||
|
|
||||||
|
return "${parts[0]}.${parts[1]}.${parts[2]}.0/24"
|
||||||
|
}
|
||||||
|
|
||||||
|
external fun enableIpForwarding(): Int
|
||||||
|
|
||||||
|
external fun enableMasquerade(iface: String): Int
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user