Appteka Logo
Appteka
RKNHardering app icon

RKNHardering

ExclusiveOpen SourceVerified Safe
Version 2.4.0 (20400)
Published 4/16/2026
Download APK
Size
10.95 MB
Android
8.0+
Downloads
35
Architecture
x86_64, arm64-v8a, armeabi-v7a
Security Scan
Verified Safe
✓ Scanned with ClamAV, APKiD, and Quark-Engine
What's New
https://github.com/xtclovver/RKNHardering/compare/v2.3.3...v2.4.0/
Description
Android application for detecting VPN and proxy on the device. Implements the methodology used by Roskomnadzor to identify means of circumventing blocks. Minimum Android version: 8.0 (API 26). Architecture Six independent verification modules run in parallel. The final verdict is calculated by the VerdictEngine. The IpComparisonChecker result is saved and shown in the UI as a diagnostic block, but it does not participate in the VerdictEngine in the current version. VpnCheckRunner ├── GeoIpChecker — GeoIP + hosting/proxy signals ├── IpComparisonChecker — RU/non-RU IP checkers (diagnostic) ├── DirectSignsChecker — NetworkCapabilities, system proxy, installed VPN apps ├── IndirectSignsChecker — interfaces, routes, DNS, dumpsys, proxy-tech signals ├── LocationSignalsChecker — MCC/SIM/cell/Wi-Fi/BeaconDB └── BypassChecker — localhost proxy, Xray gRPC API, underlying-network leak └── VerdictEngine — final verdict logic Verification Modules 1. GeoIP (GeoIpChecker) Sources: - https://api.ipapi.is/ — primary source for GeoIP fields and proxy/VPN/Tor/datacenter signals - https://www.iplocate.io/api/lookup — fallback source for GeoIP fields and additional vote for hosting (privacy.is_hosting) Logic: countryCode != RU -> IP considered foreign -> needsReview if no hosting and no proxy simultaneously hosting -> Uses majority vote from compatible responses of the same IP (ipapi.is, iplocate.io) -> detected = true if majority of compatible sources say hosting=true proxy -> Uses compatible HTTPS providers (ipapi.is, iplocate.io) -> detected = true if at least one compatible provider indicates proxy/VPN/Tor country, isp, org, as, query -> Taken from ipapi.is; missing fields filled from iplocate.io only for compatible IP -> do not directly affect result Category result: - detected = isHosting || isProxy - needsReview = foreignIp && !isHosting && !isProxy Connection and read timeout for HTTP(S) requests: 10 seconds. GeoIpChecker uses only HTTPS providers and returns an error only if no GeoIP provider responded with data. 2. IP Comparison Checkers (IpComparisonChecker) This module compares responses from RU and non-RU public IP checkers. It is a diagnostic block: shown in the UI but does not currently participate in VerdictEngine. Service groups: RU group: Yandex IPv4, 2ip.ru, Yandex IPv6 NON_RU group: ifconfig.me IPv4, ifconfig.me IPv6, checkip.amazonaws.com, ipify, ip.sb IPv4, ip.sb IPv6 Logic: - within each group, a canonicalIp is built if services are consistent; - IP mismatch within a group, partial responses, and IPv4/IPv6 family conflict put the group into needsReview or detected depending on data completeness; - overall detected is set only if both groups have full internal consensus but RU and non-RU groups return different canonical IPs; - expected IPv6 endpoint errors may be ignored and do not break IPv4 consensus. 3. Direct Signs (DirectSignsChecker) System signs without active localhost network scanning. 3.1 NetworkCapabilities (checkVpnTransport) API: ConnectivityManager.getNetworkCapabilities(activeNetwork) NetworkCapabilities.TRANSPORT_VPN -> caps.hasTransport(TRANSPORT_VPN) -> detected = true IS_VPN -> caps.toString().contains("IS_VPN") -> detected = true VpnTransportInfo -> caps.toString().contains("VpnTransportInfo") -> detected = true IS_VPN and VpnTransportInfo are checked via string representation of NetworkCapabilities. 3.2 System Proxy (checkSystemProxy) Uses: - System.getProperty("http.proxyHost") with fallback on Proxy.getDefaultHost() - System.getProperty("http.proxyPort") with fallback on Proxy.getDefaultPort() - System.getProperty("socksProxyHost") - System.getProperty("socksProxyPort") Logic: - host missing -> proxy considered not configured - host present but port invalid -> needsReview = true - host present and port valid -> detected = true - port belongs to known proxy ports -> separate finding added Known proxy ports: 80, 443, 1080, 3127, 3128, 4080, 5555, 7000, 7044, 8000, 8080, 8081, 8082, 8888, 9000, 9050, 9051, 9150, 12345, and range 16000-16100. 3.3 Installed VPN/Proxy Apps (InstalledVpnAppDetector) This module checks two sources: - known package signatures from VpnAppCatalog; - apps that declare VpnService.SERVICE_INTERFACE via PackageManager.queryIntentServices. These are diagnostic signals of installation or VpnService declaration, not confirmation of an active tunnel. Matches put the category into needsReview but do not by themselves set DirectSignsChecker.detected = true. 4. Indirect Signs (IndirectSignsChecker) 4.1 Capability NOT_VPN (checkNotVpnCapability) ConnectivityManager.getNetworkCapabilities(activeNetwork).toString() is checked for presence of the string NOT_VPN. NOT_VPN present -> normal NOT_VPN absent -> detected = true 4.2 Network Interfaces (checkNetworkInterfaces) API: NetworkInterface.getNetworkInterfaces(). Active (isUp) interfaces are checked. VPN-like interface patterns: - tun\d+ - tap\d+ - wg\d+ - ppp\d+ - ipsec.* Any active interface matching these patterns gives detected = true. 4.3 MTU Anomaly (checkMtu) Logic: - VPN-like interface with MTU 1-1499 -> detected = true - Non-standard active interface (not wlan.*, rmnet.*, eth.*, lo) with MTU 1-1499 -> detected = true 4.4 Routing Table (checkRoutingTable) Data sources: - primarily LinkProperties.routes from Android API; - fallback: /proc/net/route if default route cannot be obtained via API. Detections: - default route through non-standard interface; - dedicated non-default routes through VPN/non-standard interface; - split tunneling pattern: tunnel routes and normal default route through standard network visible simultaneously. Default route through wlan.*, rmnet.*, eth.*, lo is considered normal if the network itself is not marked as VPN. 4.5 DNS (checkDns) API: ConnectivityManager.getLinkProperties(activeNetwork).dnsServers. DNS is evaluated together with a snapshot of underlying networks if available. - loopback DNS (127.x.x.x, ::1) -> detected = true - private DNS inherited from the same private/ULA subnet of the main non-VPN network -> normal - private DNS with active VPN and difference from underlying network -> detected = true - private DNS without sufficient context -> needsReview = true - public DNS replaced when VPN is active -> needsReview = true - link-local (169.254.x.x, fe80::/10) -> informational 4.6 Additional Proxy Technical Signals (checkProxyTechnicalSignals) Checks: - installed proxy-only utilities from VpnAppCatalog with LOCAL_PROXY signal and no VPN_SERVICE; - local listeners from /proc/net/tcp, /proc/net/tcp6, /proc/net/udp, /proc/net/udp6 on known proxy ports; - large number of localhost listeners on high ports. Logic: - listener on known localhost proxy port -> detected = true - presence of proxy-only utility or many localhost listeners -> needsReview = true Limitation noted: process checks, iptables/pf, and system certificates are incomplete without root/privileged access. 4.7 dumpsys vpn_management (checkDumpsysVpn) Android 12+ only (API 31+). Runs dumpsys vpn_management. If the parser (VpnDumpsysParser) finds active VPN records, they give detected = true. Package is extracted from records and matched against VpnAppCatalog: - known package -> high confidence; - unknown package -> detected = true and needsReview = true simultaneously. Empty output, Permission Denial, or service unavailable are considered no detection. 4.8 dumpsys activity services android.net.VpnService (checkDumpsysVpnService) Runs dumpsys activity services android.net.VpnService. If active VpnService instances are found, activeApps and evidence are created: - known package from catalog -> high confidence; - unknown package -> detected = true and needsReview = true. Empty output or no VpnService records give no detection. 5. Location Signals (LocationSignalsChecker) This module collects signs confirming the device is physically in Russia or, conversely, that telephony signals look atypical. Sources: - TelephonyManager.networkOperator, networkCountryIso, networkOperatorName - TelephonyManager.simOperator, simCountryIso, isNetworkRoaming - requestCellInfoUpdate / allCellInfo - WifiManager.scanResults and current BSSID - BeaconDB (https://api.beacondb.net/v1/geolocate) for cell/Wi-Fi geolocation - reverse geocoding for countryCode Permissions: - ACCESS_FINE_LOCATION needed for cell lookup; - on Android 13+ NEARBY_WIFI_DEVICES needed for Wi-Fi lookup. Logic: - networkMcc == 250 -> adds informational finding network_mcc_ru:true - BeaconDB/reverse geocode returns RU -> adds cell_country_ru:true and location_country_ru:true - networkMcc != 250 -> needsReview = true - missing permissions or radio data -> informational In the current implementation, LocationSignalsChecker.detected is always false. Its main role in VerdictEngine is to confirm Russia and strengthen a foreign GeoIP signal. 6. Bypass Check (BypassChecker) Three checks run in parallel: - ProxyScanner - XrayApiScanner - UnderlyingNetworkProber 6.1 Proxy Scanner (ProxyScanner + ProxyProber) Scans 127.0.0.1 and ::1. Modes: - AUTO: first popular ports, then full range - MANUAL: check a single specified port Popular ports in AUTO are formed from VpnAppCatalog.localhostProxyPorts and additionally include 1081, 7890, 7891. Full scan: - range 1024-65535 - concurrency 200 - connection timeout 80 ms - read timeout 120 ms Only proxies without authentication are detected: SOCKS5: greeting 0x05 0x01 0x00 and response 0x05 0x00 HTTP CONNECT: CONNECT ifconfig.me:443 HTTP/1.1 and response HTTP/1.x 200 An open localhost proxy alone is not considered confirmed bypass: it is recorded as needsReview. Bypass confirmation is set only if the direct IP and IP through the proxy are successfully obtained and they differ. Additionally: - if SOCKS5 is found but HTTP IP retrieval through it fails and the port does not look like Xray, MtProtoProber is launched; - a successful MTProto probe adds an informational finding but does not affect the final verdict. 6.2 Xray gRPC API Scanner (XrayApiScanner + XrayApiClient) Scans 127.0.0.1 and ::1. Parameters: - range 1024-65535 - concurrency 100 - TCP connect timeout 200 ms - gRPC deadline 2000 ms with retry on increased deadline Verification is performed not via raw HTTP/2 preface but through a real gRPC call HandlerServiceGrpc.listOutbounds(...). On success: - endpoint gives detected = true; - findings include up to 10 summary outbounds (tag, protocol, address, port, sni) and count of remaining. 6.3 Underlying Network Leak / VPN Network Binding (UnderlyingNetworkProber) If a VPN is active on the device, the module: - iterates over all ConnectivityManager.allNetworks; - looks for an internet-capable network without TRANSPORT_VPN; - binds HTTP(S) requests to that network; - requests public IP via ifconfig.me, checkip.amazonaws.com, ipv4-internet.yandex.net, ipv6-internet.yandex.net. If an underlying network is accessible while VPN is active, this is treated as a VPN gateway leak and gives detected = true. Category result: - detected = confirmed split tunnel || xrayApiFound || vpnGatewayLeak || vpnNetworkBinding - needsReview = true if open proxy found but bypass confirmation not obtained Verdict (VerdictEngine) VerdictEngine does not use all collected blocks equally. First, unconditional rules are applied: 1. DETECTED if bypass-evidence has SPLIT_TUNNEL_BYPASS. 2. DETECTED if XRAY_API is found. 3. DETECTED if VPN_GATEWAY_LEAK is found. 4. DETECTED if location signals confirm Russia (network_mcc_ru:true, cell_country_ru:true, or location_country_ru:true) and GeoIP simultaneously gives a foreign signal. After that, a matrix is calculated: - geoMatrixHit = foreign GeoIP signal (geoIp.needsReview or evidence GEO_IP) - directMatrixHit = evidence from DIRECT_NETWORK_CAPABILITIES or SYSTEM_PROXY - indirectMatrixHit = evidence from INDIRECT_NETWORK_CAPABILITIES, ACTIVE_VPN, NETWORK_INTERFACE, ROUTING, DNS, PROXY_TECHNICAL_SIGNAL Combinations: - Geo: no, Direct: no, Indirect: no -> NOT_DETECTED - Geo: no, Direct: yes, Indirect: no -> NOT_DETECTED - Geo: no, Direct: no, Indirect: yes -> NOT_DETECTED - Geo: yes, Direct: no, Indirect: no -> NEEDS_REVIEW - Geo: no, Direct: yes, Indirect: yes -> NEEDS_REVIEW - Any other combinations -> DETECTED Notes: - IpComparisonChecker does not currently participate in VerdictEngine; - INSTALLED_APP and VPN_SERVICE_DECLARATION signals are also not in the matrix and remain diagnostic.
Rate this app
0 / 1000
Ratings & Reviews
No reviews yet.