Skip to main content

nova-client-proxy

Cross-platform VPN client built on Flutter and sing-box with Nova Radar clean-IP scanner, supporting VLESS/VMess/Trojan/Shadowsocks protocols

설치로 이동

소스 정보

저장소
reason-machines/devtools-skills
최근 소스 활동
2026년 7월 31일 14:18
감지된 SKILL.md 언어
영어
스타
4
포크
0

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
nova-client-proxy
description
Cross-platform VPN client built on Flutter and sing-box with Nova Radar clean-IP scanner, supporting VLESS/VMess/Trojan/Shadowsocks protocols
triggers
["how do I use Nova Client proxy","set up Nova Client VPN on Android iOS Windows","configure Nova Proxy subscription","scan Cloudflare clean IPs with Nova Radar","add proxy profiles to Nova Client","troubleshoot Nova Client connection issues","use sing-box with Nova Client","route Iranian sites directly in Nova Client"]
# Nova Client Proxy Skill > Skill by [ara.so](https://ara.so) — Devtools Skills collection. ## Overview Nova Client is a cross-platform VPN/proxy client built with Flutter that wraps the sing-box core. It's a streamlined fork of Karing with the Nova Proxy design language and integrates the Nova Radar Cloudflare clean-IP scanner. Supports Android, iOS, Windows, macOS, and Linux. **Key capabilities:** - Multi-protocol support: VLESS, VMess, Trojan, Shadowsocks, Hysteria2, TUIC - Subscription management with auto-update - Built-in Nova Radar scanner for finding clean Cloudflare IPs - Smart routing (`.ir` direct bypass for Iranian sites) - Per-node latency testing and auto-fastest selection - Bilingual (English/Persian) with RTL support ## Installation ### Android ```bash # Direct APK download from releases wget https://github.com/IRNova/Nova-Client/releases/latest/download/nova-client-android.apk # Install via adb adb install nova-client-android.apk ``` ### iOS/iPadOS - TestFlight beta or App Store (when available) - Download from GitHub releases page ### Windows ```powershell # Download installer Invoke-WebRequest -Uri "https://github.com/IRNova/Nova-Client/releases/latest/download/nova-client-windows.exe" -OutFile "nova-client-setup.exe" # Run installer .\nova-client-setup.exe # Or use portable ZIP version ``` ### macOS ```bash # Download DMG curl -LO https://github.com/IRNova/Nova-Client/releases/latest/download/nova-client-macos.dmg # Mount and install hdiutil attach nova-client-macos.dmg cp -R "/Volumes/Nova Client/Nova Client.app" /Applications/ ``` ### Linux ```bash # AppImage (no installation required) wget https://github.com/IRNova/Nova-Client/releases/latest/download/nova-client-linux.AppImage chmod +x nova-client-linux.AppImage ./nova-client-linux.AppImage # Or tarball tar xf nova-client-linux.tar.xz cd nova-client ./nova-client ``` ## Configuration Files Nova Client stores configuration in platform-specific directories: - **Android**: `/data/data/com.irnova.client/files/` - **iOS**: App sandbox documents directory - **Windows**: `%APPDATA%\NovaClient\` - **macOS**: `~/Library/Application Support/NovaClient/` - **Linux**: `~/.config/nova-client/` ### Key Files ``` config/ ├── profiles.json # Subscription and manual profiles ├── routing.json # Routing rules and modes ├── sing-box-config.json # Generated sing-box configuration └── radar-sources.json # Nova Radar IP sources ``` ## Adding Proxy Profiles ### Subscription URL ```json { "profiles": [ { "id": "uuid-here", "name": "Nova Proxy Official", "type": "subscription", "url": "https://example.com/subscription", "autoUpdate": true, "updateInterval": 86400 } ] } ``` ### Manual Node (VLESS Example) ```json { "profiles": [ { "id": "manual-1", "name": "Custom VLESS", "type": "manual", "protocol": "vless", "address": "example.com", "port": 443, "uuid": "YOUR_UUID", "flow": "xtls-rprx-vision", "encryption": "none", "network": "tcp", "security": "reality", "sni": "www.google.com", "fingerprint": "chrome", "publicKey": "YOUR_PUBLIC_KEY", "shortId": "SHORT_ID" } ] } ``` ### VMess Configuration ```json { "protocol": "vmess", "address": "server.example.com", "port": 443, "uuid": "YOUR_UUID", "alterId": 0, "security": "auto", "network": "ws", "path": "/vmess-path", "host": "server.example.com", "tls": true, "sni": "server.example.com", "alpn": ["h2", "http/1.1"] } ``` ### Trojan Configuration ```json { "protocol": "trojan", "address": "trojan.example.com", "port": 443, "password": "YOUR_PASSWORD", "sni": "trojan.example.com", "alpn": ["h2"], "fingerprint": "firefox", "allowInsecure": false } ``` ## Routing Configuration ### Smart Routing for Iran ```json { "routing": { "mode": "rule", "rules": [ { "type": "direct", "domain_suffix": [".ir"], "description": "Iranian sites bypass proxy" }, { "type": "block", "domain_keyword": ["ads", "analytics", "tracker"], "description": "Ad blocking" }, { "type": "direct", "ip_cidr": ["192.168.0.0/16", "10.0.0.0/8"], "description": "LAN bypass" }, { "type": "proxy", "domain": "*", "description": "Default proxy" } ] } } ``` ### Routing Modes - **proxy**: Route all traffic through proxy - **direct**: No proxy (direct connection) - **rule**: Use custom routing rules (recommended) - **auto**: Automatic fastest node selection ## Nova Radar Scanner Usage The Nova Radar scanner finds clean Cloudflare IPs for use in CDN-based proxies. ### Scanner Configuration (Dart/Flutter) ```dart import 'package:nova_client/radar/scanner.dart'; class RadarScanner { final List<String> sources = [ 'https://www.cloudflare.com/ips-v4', 'https://raw.githubusercontent.com/vfarid/cf-clean-ips/main/list.txt', // Add more sources ]; Future<List<CleanIP>> scanCleanIPs({ required int count, required int threads, required int timeout, Function(double)? onProgress, }) async { final ips = await _fetchIPsFromSources(sources); final results = <CleanIP>[]; int scanned = 0; final total = ips.length; // Phase 1: TCP connectivity test await Future.wait( ips.map((ip) async { final socket = await _testTCPConnect(ip, timeout); if (socket != null) { socket.close(); // Phase 2: TLS handshake test final latency = await _testTLSHandshake(ip, timeout); if (latency > 0) { results.add(CleanIP(ip: ip, latency: latency)); } } scanned++; onProgress?.call(scanned / total); }), eagerError: false, ); // Sort by latency results.sort((a, b) => a.latency.compareTo(b.latency)); return results.take(count).toList(); } Future<Socket?> _testTCPConnect(String ip, int timeout) async { try { return await Socket.connect( ip, 443, timeout: Duration(milliseconds: timeout), ); } catch (_) { return null; } } Future<int> _testTLSHandshake(String ip, int timeout) async { final stopwatch = Stopwatch()..start(); try { final socket = await SecureSocket.connect( ip, 443, timeout: Duration(milliseconds: timeout), onBadCertificate: (_) => true, ); await socket.close(); return stopwatch.elapsedMilliseconds; } catch (_) { return -1; } } Future<List<String>> _fetchIPsFromSources(List<String> sources) async { final allIPs = <String>{}; for (final source in sources) { try { final response = await http.get(Uri.parse(source)); if (response.statusCode == 200) { final ips = response.body .split('\n') .where((line) => _isValidIP(line.trim())) .toList(); allIPs.addAll(ips); } } catch (e) { print('Failed to fetch from $source: $e'); } } return allIPs.toList(); } bool _isValidIP(String ip) { final ipPattern = RegExp( r'^(\d{1,3}\.){3}\d{1,3}(/\d{1,2})?$' ); return ipPattern.hasMatch(ip); } } class CleanIP { final String ip; final int latency; CleanIP({required this.ip, required this.latency}); } ``` ### Using Scanner Results ```dart // Scan and get clean IPs final scanner = RadarScanner(); final cleanIPs = await scanner.scanCleanIPs( count: 10, threads: 100, timeout: 2000, onProgress: (progress) { print('Progress: ${(progress * 100).toStringAsFixed(1)}%'); }, ); // Export results final export = cleanIPs.map((ip) => '${ip.ip},${ip.latency}ms').join('\n'); await File('clean-ips.txt').writeAsString(export); // Use best IP in proxy config final bestIP = cleanIPs.first.ip; final config = { 'address': bestIP, 'port': 443, 'sni': 'cdn.cloudflare.com', }; ``` ## Latency Testing ### Test Single Node ```dart import 'package:nova_client/core/latency.dart'; Future<int> testNodeLatency(ProxyNode node) async { final stopwatch = Stopwatch()..start(); try { final socket = await Socket.connect( node.address, node.port, timeout: Duration(seconds: 5), ); await socket.close(); return stopwatch.elapsedMilliseconds; } catch (e) { return -1; // Connection failed } } ``` ### Batch Latency Test ```dart Future<Map<String, int>> testAllNodes(List<ProxyNode> nodes) async { final results = <String, int>{}; await Future.wait( nodes.map((node) async { final latency = await testNodeLatency(node); results[node.id] = latency; }), ); return results; } // Auto-select fastest ProxyNode selectFastest(List<ProxyNode> nodes, Map<String, int> latencies) { return nodes.reduce((best, node) { final bestLatency = latencies[best.id] ?? 999999; final nodeLatency = latencies[node.id] ?? 999999; return nodeLatency < bestLatency && nodeLatency > 0 ? node : best; }); } ``` ## sing-box Core Integration ### Generate sing-box Config ```dart Map<String, dynamic> generateSingBoxConfig(ProxyNode node, RoutingRules rules) { return { 'log': {'level': 'info'}, 'dns': { 'servers': [ {'tag': 'google', 'address': '8.8.8.8'}, {'tag': 'local', 'address': '223.5.5.5', 'detour': 'direct'} ], 'rules': [ {'domain_suffix': ['.ir'], 'server': 'local'} ] }, 'inbounds': [ { 'type': 'tun', 'tag': 'tun-in', 'interface_name': 'nova0',
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기