feat(app): add secure routing and runtime resilience

Add explicit TUN and SOCKS5 connection modes, app routing controls, authenticated per-session local SOCKS5, Android network monitoring, persistent haptics, resilient session recovery, notification hardening and client-side Hivemind cleanup.

Keep the hosted flutter_vless_android 1.1.5 runtime as the base and apply the Android compatibility/security patches at build time instead of restoring the unstable vendored runtime.
This commit is contained in:
Naveax committed 2026-08-31 19:31:12 +03:00
1 parent 371db8da9f
commit 8ead3ff249
30 files changed
+3959 -484

No files matched your search

+89
View File
@@ -0,0 +1,89 @@
import 'dart:convert';
import 'dart:io';
import 'dart:math';
class SecureSocksSession {
static const String inboundTag = 'revolt-secure-socks';
static final Random _random = Random.secure();
final int port;
final String username;
final String password;
final String configJson;
const SecureSocksSession._({
required this.port,
required this.username,
required this.password,
required this.configJson,
});
static Future<SecureSocksSession> create(String baseConfig) async {
final decoded = jsonDecode(baseConfig);
if (decoded is! Map<String, dynamic>) {
throw const FormatException('VLESS configuration must be a JSON object.');
}
final reservation = await ServerSocket.bind(
InternetAddress.loopbackIPv4,
0,
shared: false,
);
final port = reservation.port;
await reservation.close();
if (port <= 1024 || port > 65535) {
throw StateError('Could not allocate a safe local SOCKS5 port.');
}
final username = _token(16);
final password = _token(32);
final sourceInbounds = decoded['inbounds'];
final inbounds = <dynamic>[];
if (sourceInbounds is List) {
for (final value in sourceInbounds) {
if (value is Map) {
final protocol = value['protocol']?.toString().toLowerCase();
// ReVolt owns local proxy ingress on Android. Drop imported SOCKS/HTTP
// listeners so a stale no-auth proxy cannot remain reachable beside
// the authenticated session listener.
if (protocol == 'socks' || protocol == 'http') continue;
}
inbounds.add(value);
}
}
inbounds.add(<String, dynamic>{
'tag': inboundTag,
'port': port,
'listen': '127.0.0.1',
'protocol': 'socks',
'settings': <String, dynamic>{
'auth': 'password',
'udp': true,
'ip': '127.0.0.1',
'users': <Map<String, String>>[
<String, String>{'user': username, 'pass': password},
],
},
'sniffing': <String, dynamic>{
'enabled': true,
'destOverride': <String>['http', 'tls'],
},
});
decoded['inbounds'] = inbounds;
return SecureSocksSession._(
port: port,
username: username,
password: password,
configJson: jsonEncode(decoded),
);
}
static String _token(int byteCount) {
final bytes = List<int>.generate(byteCount, (_) => _random.nextInt(256));
return bytes.map((value) => value.toRadixString(16).padLeft(2, '0')).join();
}
}