I have an application, at the moment it is represented by two classes:
class MainActivity : ComponentActivity() {
    private var socks5Address by mutableStateOf("")

    private fun startVpnService() {
        val vpnIntent = Intent(this, MyVPNService::class.java).apply {
            putExtra("SOCKS5_ADDRESS", socks5Address)
        }
        startService(vpnIntent)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MainScreen()
        }
    }

    @Preview
    @Composable
    fun MainScreen() {
        val navController = rememberNavController()
        Scaffold(bottomBar = {
            BottomNavigation {
                BottomNavigationItem(selected = false,
                    onClick = { navController.navigate("vpn") },
                    icon = { Icon(Icons.Filled.VpnKey, contentDescription = "VPN") },
                    label = { Text("VPN") })
                BottomNavigationItem(selected = false,
                    onClick = { navController.navigate("compare") },
                    icon = {
                        Icon(
                            Icons.AutoMirrored.Filled.CompareArrows,
                            contentDescription = "Compare"
                        )
                    },
                    label = { Text("Compare") })
            }
        }) { padding ->
            NavHost(
                navController = navController, startDestination = "vpn", Modifier.padding(padding)
            ) {
                composable("vpn") { VpnScreen() }
                composable("compare") { CompareScreen() }
            }
        }
    }


    @Composable
    fun VpnScreen() {
        val context = LocalContext.current
        val vpnState by remember { mutableStateOf(false) }
        val vpnRequestLauncher = rememberLauncherForActivityResult(
            contract = ActivityResultContracts.StartActivityForResult()
        ) { result ->
            if (result.resultCode == Activity.RESULT_OK) {
                context.startService(Intent(context, MyVPNService::class.java))
            } else {
                // Handle permission denied
            }
        }
        var serverAddress by remember { mutableStateOf("") }
        var vpnName by remember { mutableStateOf("") }
        var username by remember { mutableStateOf("") }
        var password by remember { mutableStateOf("") }
        var port by remember { mutableStateOf("") }
        var socks5Address by remember { mutableStateOf("") }
        val activity = LocalContext.current as? ComponentActivity

        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(16.dp),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Top
        ) {
            OutlinedTextField(
                value = serverAddress,
                onValueChange = { serverAddress = it },
                label = { Text("Server Address") },
                modifier = Modifier.fillMaxWidth()
            )

            OutlinedTextField(
                value = vpnName,
                onValueChange = { vpnName = it },
                label = { Text("VPN Name") },
                modifier = Modifier.width(300.dp)
            )

            OutlinedTextField(
                value = username,
                onValueChange = { username = it },
                label = { Text("Username") },
                modifier = Modifier.width(300.dp)
            )

            OutlinedTextField(
                value = password,
                onValueChange = { password = it },
                label = { Text("Password") },
                visualTransformation = PasswordVisualTransformation(), // Hide password
                keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
                modifier = Modifier.width(300.dp)
            )

            OutlinedTextField(
                value = port,
                onValueChange = { port = it },
                label = { Text("Port (Optional)") },
                keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
                modifier = Modifier.width(300.dp)
            )

            OutlinedTextField(
                value = socks5Address,
                onValueChange = { socks5Address = it },
                label = { Text("SOCKS5 address (host:port)") },
                modifier = Modifier.fillMaxWidth()
            )

            Spacer(Modifier.height(16.dp))

            Button(onClick = {
                val prepareIntent = VpnService.prepare(context)
                if (prepareIntent != null) {
                    activity?.let {
                        vpnRequestLauncher.launch(prepareIntent)
                    }
                } else {
                    startVpnService()
                }
            }) {
                Text("Чек VPN")
            }

            Button(
                onClick = {
                val vpnIntent = Intent(context, MyVPNService::class.java).apply {
                    putExtra("SERVER_ADDRESS", serverAddress)   // Pass vpn server address
                    putExtra("VPN_NAME", vpnName)       // Pass vpn name
                    putExtra("USERNAME", username)       // Pass username
                    putExtra("PASSWORD", password)       // Pass password
                    putExtra("PORT", port.toIntOrNull()) // Pass port (handle null)
                }

                val prepareIntent = VpnService.prepare(context)
                if (prepareIntent != null) {
                    vpnRequestLauncher.launch(prepareIntent)
                } else {
                    context.startService(vpnIntent)
                }
            }
            ) {
                Text(if (vpnState) "Выкл VPN" else "Вкл VPN")
            }

            Text("Сервер: ...")
            Text("АйПы: ...")
            Text("Статус: ${if (vpnState) "Подключено" else "Отключено"}")
        }
    }

    @Composable
    fun CompareScreen() {
        Text("Compare Screen")
    }
}
and
class MyVPNService : VpnService() {

    private var vpnInterface: ParcelFileDescriptor? = null
    private var vpnJob: Job? = null
    private var socks5Address: String = ""

    private fun startVPN(serverAddress: String, vpnName: String) {
        try {
            val builder = Builder()
                .addAddress(serverAddress, 32)  // Or appropriate subnet mask
                .addRoute("0.0.0.0", 0) // Route all traffic through VPN
                .setSession(vpnName)

            vpnInterface = builder.establish()

            vpnJob = CoroutineScope(Dispatchers.IO).launch {
                runVpnLoop()
            }
        } catch (e: Exception) {
            // Handle exceptions (e.g., network errors)
        }
    }


    private suspend fun runVpnLoop() {
        // input/output streams, packet buffer
        val inputStream = FileInputStream(vpnInterface!!.fileDescriptor)
        val outputStream = FileOutputStream(vpnInterface!!.fileDescriptor)
        val packet = ByteArray(20000)

        try {
            while (true) {
                val length = withContext(Dispatchers.IO) {
                    inputStream.read(packet)
                }
                if (length > 0) {
                    val ipPacket = packet.copyOfRange(0, length)
                    val destinationIp = getDestinationIp(ipPacket)
                    val destinationPort = getDestinationPort(ipPacket)
                    forwardPacket(ipPacket, outputStream, destinationIp, destinationPort)
                } else {
                    break
                }
            }
        } catch (e: CancellationException) {
            // Handle cancellation
        } finally {
            stopVPN()
        }
    }

    private fun getDestinationPort(packet: ByteArray): Int {
        return if (isTCP(packet)) {
            getTcpDestinationPort(packet)
        } else if (isUDP(packet)) {
            getUdpDestinationPort(packet)
        } else {
            // Handle other protocols or return a default
            -1 // Or throw an exception
        }
    }

    private fun getDestinationIp(packet: ByteArray): InetAddress? {
        if (isIPv4(packet)) {
            return getIPv4DestinationAddress(packet)
        } else if (isIPv6(packet)) {
            // Implement IPv6 address extraction
            return null // Placeholder for IPv6 implementation
        } else {
            return null // Or throw an exception
        }
    }

    private fun isTCP(packet: ByteArray): Boolean = packet[9] == 0x06.toByte()
    private fun isUDP(packet: ByteArray): Boolean = packet[9] == 0x11.toByte()
    private fun isIPv4(packet: ByteArray): Boolean = (packet[0] and 0xF0.toByte()) == 0x40.toByte()
    private fun isIPv6(packet: ByteArray): Boolean = (packet[0] and 0xF0.toByte()) == 0x60.toByte()



    private fun getTcpDestinationPort(packet: ByteArray): Int {
        val offset = getIpHeaderLength(packet) + 2  // IP header + source port
        return ((packet[offset].toInt() and 0xFF) shl 8) or (packet[offset + 1].toInt() and 0xFF)
    }

    private fun getUdpDestinationPort(packet: ByteArray): Int {
        val offset = getIpHeaderLength(packet) + 2
        return ((packet[offset].toInt() and 0xFF) shl 8) or (packet[offset + 1].toInt() and 0xFF)
    }

    private fun getIPv4DestinationAddress(packet: ByteArray): InetAddress? {
        val offset = 16 // Destination IP address offset in IPv4 header
        val ipBytes = packet.copyOfRange(offset, offset + 4)
        return try {
            InetAddress.getByAddress(ipBytes)
        } catch (e: UnknownHostException) {
            null
        }
    }

    private fun getIpHeaderLength(packet: ByteArray): Int = (packet[0].toInt() and 0x0F) * 4

    private suspend fun forwardPacket(packet: ByteArray, outputStream: OutputStream, destinationIp: InetAddress?, destinationPort: Int) {
        if (destinationIp == null) {
            Log.e("VPNService", "Invalid destination IP")
            return
        }

        withContext(Dispatchers.IO) {
            try {
                if (socks5Address.isBlank()) {
                    Log.e("VPNService", "SOCKS5 address is not set.")
                    return@withContext
                }

                val (host, portStr) = socks5Address.split(":", limit = 2)
                val port = portStr.toIntOrNull() ?: 1080

                val socks5 = Socket(host, port)
                val socksIn = socks5.getInputStream()
                val socksOut = socks5.getOutputStream()

                // SOCKS5 handshake (NO AUTHENTICATION)
                socksOut.write(byteArrayOf(0x05, 0x01, 0x00))
                val handshakeResponse = socksIn.readNBytes(2)
                if (handshakeResponse[0] != 0x05.toByte() || handshakeResponse[1] != 0x00.toByte()) {
                    Log.e("VPNService", "SOCKS5 handshake failed: ${handshakeResponse.contentToString()}")
                    socks5.close()
                    return@withContext
                }

                // SOCKS5 connect request
                val addressBytes = destinationIp.address
                val portBytes = ByteBuffer.allocate(2).order(ByteOrder.BIG_ENDIAN).putShort(destinationPort.toShort()).array()
                socksOut.write(byteArrayOf(0x05, 0x01, 0x00, 0x01) + addressBytes + portBytes)

                val connectResponse = socksIn.readNBytes(10)
                if (connectResponse[1] != 0x00.toByte()) {  // Check REP field
                    Log.e("VPNService", "SOCKS5 connection request failed: ${connectResponse[1]}")
                    socks5.close()
                    return@withContext
                }

                // Send the actual data (VPN packet)
                socksOut.write(packet)

                // Receive data from the SOCKS5 server (response from the destination)
                val incomingBuffer = ByteArray(20000)
                val bytesRead = socksIn.read(incomingBuffer)
                if (bytesRead > 0) {
                    outputStream.write(incomingBuffer, 0, bytesRead)
                }

                socks5.close()

            } catch (e: Exception) {
                Log.e("VPNService", "Error forwarding packet: ${e.message}", e) // Log the exception
            }
        }
    }



    private fun stopVPN() {
        try {
            vpnJob?.cancel()
            vpnJob = null

            vpnInterface?.close()
            vpnInterface = null
        } catch (e: Exception) {
            // Handle exceptions
        }
    }


    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        socks5Address = intent?.getStringExtra("SOCKS5_ADDRESS") ?: ""
        val serverAddress = intent?.getStringExtra("SERVER_ADDRESS") ?: ""
        val vpnName = intent?.getStringExtra("VPN_NAME") ?: "MyVPN"

        when (intent?.action) {
            "START_VPN" -> startVPN(serverAddress, vpnName)
            "STOP_VPN" -> stopVPN()
        }
        return START_NOT_STICKY
    }


    override fun onDestroy() {
        super.onDestroy()
        stopVPN()
    }


    override fun onRevoke() {
        stopVPN()
    }
}
the current task is to catch all VPN service traffic from localhost, then send it via SOCKS5 to the specified address (manually specified in the additional field).
Next, the VPN waits for a response to return the traffic back.