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 create(String baseConfig) async { final decoded = jsonDecode(baseConfig); if (decoded is! Map) { 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 = []; 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({ 'tag': inboundTag, 'port': port, 'listen': '127.0.0.1', 'protocol': 'socks', 'settings': { 'auth': 'password', 'udp': true, 'ip': '127.0.0.1', 'users': >[ {'user': username, 'pass': password}, ], }, 'sniffing': { 'enabled': true, 'destOverride': ['http', 'tls'], }, }); decoded['inbounds'] = inbounds; return SecureSocksSession._( port: port, username: username, password: password, configJson: jsonEncode(decoded), ); } static String _token(int byteCount) { final bytes = List.generate(byteCount, (_) => _random.nextInt(256)); return bytes.map((value) => value.toRadixString(16).padLeft(2, '0')).join(); } }