diff --git a/clients/android/app/build.gradle b/clients/android/app/build.gradle index 459c8ee..281d3e8 100644 --- a/clients/android/app/build.gradle +++ b/clients/android/app/build.gradle @@ -30,8 +30,8 @@ android { applicationId "su.cin.rapvpn" minSdk 26 targetSdk 35 - versionCode 204 - versionName "0.2.204" + versionCode 205 + versionName "0.2.205" buildConfigField "String", "DEFAULT_BACKEND_URL", "\"${normalizeGradleString(defaultBackendUrl)}\"" buildConfigField "String", "DEFAULT_CLUSTER_ID", "\"${normalizeGradleString(defaultClusterId)}\"" buildConfigField "String", "DEFAULT_ORGANIZATION_ID", "\"${normalizeGradleString(defaultOrganizationId)}\"" diff --git a/clients/android/app/src/main/java/su/cin/rapvpn/RapDiagnosticService.java b/clients/android/app/src/main/java/su/cin/rapvpn/RapDiagnosticService.java index 566ea6d..9b27355 100644 --- a/clients/android/app/src/main/java/su/cin/rapvpn/RapDiagnosticService.java +++ b/clients/android/app/src/main/java/su/cin/rapvpn/RapDiagnosticService.java @@ -442,7 +442,7 @@ public class RapDiagnosticService extends Service { } else if ("http_get".equals(type)) { result = runHttpGet(params.optString("url", "http://192.168.200.61:18080/")); } else if ("vpn_http_get".equals(type)) { - result = runVPNHttpGet(params.optString("url", "http://192.168.200.61:18080/")); + result = runVPNHttpGet(params.optString("url", "http://192.168.200.61:18080/"), params.optInt("timeout_ms", 15000)); } else if ("vpn_page_probe".equals(type)) { result = runVPNPageProbe(params); } else if ("vpn_tcp_connect".equals(type) || "vpn_rdp_probe".equals(type)) { @@ -679,7 +679,7 @@ public class RapDiagnosticService extends Service { private String runVPNProbeCommand(String type, JSONObject payload, boolean recoveryAttempt) { if ("vpn_http_get".equals(type)) { - return runVPNHttpGet(payload.optString("url", "http://192.168.200.61:18080/")); + return runVPNHttpGet(payload.optString("url", "http://192.168.200.61:18080/"), payload.optInt("timeout_ms", 15000)); } if ("vpn_page_probe".equals(type)) { return runVPNPageProbe(payload); @@ -1167,8 +1167,8 @@ public class RapDiagnosticService extends Service { result.append("network={").append(deviceNetworkSnapshot()).append("}"); result.append(" | stats=").append(collectVPNStats(client, clusterId)); result.append(" | dns=").append(runVPNDNSLookup(host)); - result.append(" | vpn_http=").append(runVPNHttpGet(url)); - result.append(" | vpn_local_http=").append(runVPNHttpGet(localUrl)); + result.append(" | vpn_http=").append(runVPNHttpGet(url, 15000)); + result.append(" | vpn_local_http=").append(runVPNHttpGet(localUrl, 15000)); result.append(" | download=").append(runVPNDownloadTest(payload.optString("download_url", "http://192.168.200.61:18080/downloads/rap-android-rdp-vpn-build.json"))); return compact(result.toString(), 2500); } @@ -1501,7 +1501,10 @@ public class RapDiagnosticService extends Service { } } - private String runVPNHttpGet(String target) { + private String runVPNHttpGet(String target, int timeoutMs) { + int effectiveTimeoutMs = Math.max(1000, Math.min(timeoutMs, 30000)); + int connectTimeoutMs = Math.max(1000, Math.min(effectiveTimeoutMs, 10000)); + int readTimeoutMs = Math.max(1000, effectiveTimeoutMs - connectTimeoutMs); try { Network vpn = vpnNetwork(); if (vpn == null) { @@ -1521,8 +1524,8 @@ public class RapDiagnosticService extends Service { connection = (HttpURLConnection) vpn.openConnection(url); } try { - connection.setConnectTimeout(15000); - connection.setReadTimeout(15000); + connection.setConnectTimeout(connectTimeoutMs); + connection.setReadTimeout(readTimeoutMs); connection.setInstanceFollowRedirects(false); int code = connection.getResponseCode(); connection.disconnect(); @@ -1535,8 +1538,8 @@ public class RapDiagnosticService extends Service { URL resolvedURL = new URL(url.getProtocol(), fallbackResolved, url.getPort(), url.getFile()); connection = (HttpURLConnection) vpn.openConnection(resolvedURL); connection.setRequestProperty("Host", hostHeader(url)); - connection.setConnectTimeout(15000); - connection.setReadTimeout(15000); + connection.setConnectTimeout(connectTimeoutMs); + connection.setReadTimeout(readTimeoutMs); connection.setInstanceFollowRedirects(false); int code = connection.getResponseCode(); connection.disconnect(); diff --git a/clients/android/app/src/main/java/su/cin/rapvpn/RapVpnService.java b/clients/android/app/src/main/java/su/cin/rapvpn/RapVpnService.java index 6ed040f..3ee8da0 100644 --- a/clients/android/app/src/main/java/su/cin/rapvpn/RapVpnService.java +++ b/clients/android/app/src/main/java/su/cin/rapvpn/RapVpnService.java @@ -2281,7 +2281,16 @@ public class RapVpnService extends VpnService { boolean syn = (flow.flags & 0x02) != 0; boolean fin = (flow.flags & 0x01) != 0; boolean rst = (flow.flags & 0x04) != 0; - return syn || fin || rst; + boolean ack = (flow.flags & 0x10) != 0; + boolean psh = (flow.flags & 0x08) != 0; + int ipTotalLength = u16(packet, 2); + if (ipTotalLength <= 0 || ipTotalLength > length) { + ipTotalLength = length; + } + int ihl = (packet[0] & 0x0f) * 4; + int tcpHeaderLength = ((packet[ihl + 12] >> 4) & 0x0f) * 4; + int tcpPayloadLength = Math.max(0, ipTotalLength - ihl - tcpHeaderLength); + return syn || fin || rst || (ack && tcpPayloadLength == 0) || (psh && tcpPayloadLength <= 96); } private boolean clampIPv4TCPMSS(byte[] packet, int length, int maxMss) {