CodeVetter
← All unpacks
CodeVetter · Repo Unpack evidence

2dust/v2rayN

Scanned commit 28139853a8 dated 2026-09-20 — last upstream commit. Generated by codevetter 1.12.0 on 2026-09-22.

github.com/2dust/v2rayN ↗ · 418 files · 3.9 MB

v2rayN A GUI client for Windows, Linux and macOS.

Deep analysis by swe-2 via the devin CLI on 2026-09-22 (runtime not recorded) — every claim below links to its cited source files.

Overview

v2rayN is a cross-platform desktop GUI proxy client written in C# on .NET 10 that orchestrates external proxy cores — primarily Xray and sing-box, plus mihomo, hysteria, tuic and others — for Windows, Linux and macOS users. It ships as two shells over a shared ServiceLib core: a WPF app (v2rayN) for Windows and an Avalonia app (v2rayN.Desktop) for Windows/Linux/macOS, both ReactiveUI-based MVVM. Its distinctive role is translating user-managed server profiles, subscriptions, routing/DNS rules and TUN settings into generated core config JSON, spawning the right core binary, and wiring the OS-level system proxy.

System map

The solution (v2rayN.sln) has five projects: ServiceLib (all shared logic, ViewModels, managers, config generation), v2rayN (WPF Windows shell), v2rayN.Desktop (Avalonia cross-platform shell), AmazTool (a tiny console updater/relocator invoked after self-upgrade downloads), and ServiceLib.UdpTest (UDP-over-SOCKS5 tester library referenced by ServiceLib). Persistence is a JSON file guiNConfig.json plus a SQLite database guiNDB.db accessed via the SQLiteHelper singleton. External runtime boundaries are the spawned core processes (xray, sing-box, mihomo, etc. under bin/<coreType>/), OS facilities (WinInet/registry, launchctl, .desktop autostart, sudo bash scripts), a loopback Clash API, and GitHub release endpoints for updates. Build/test is .NET 10 with GitHub Actions workflows; GlobalHotKeys is a git submodule used only by the Desktop project.

All 14 system map claims →

Feature catalog

User-facing features center on managing proxy server profiles (11 share-URI protocols plus custom/outbound/group types), subscription groups with scheduled updates and optional subconvert rewriting, and one-click activation that generates a core config and launches the matching core. Around that are system-proxy control per OS (including a PAC file server on Windows), TUN mode with privilege escalation, a full Clash-compatible API panel (proxies/connections/mode switch), batch latency/speed/mixed/UDP testing, per-server traffic statistics, self/core/geo-file updating from GitHub, WebDAV backup, global hotkeys, autostart, QR/clipboard/image import, and regional presets for Russia and Iran.

All 15 feature catalog claims →

Data flow

Input boundaries are subscription URLs, share URIs (clipboard/QR/image), dialogs, and GitHub release APIs. Everything lands in the Config object (guiNConfig.json) or SQLite guiNDB.db entities via AppManager query helpers and ConfigHandler writers. The hot path to the network boundary is: ProfileItem + Config -> CoreConfigContextBuilder.Build/BuildAll -> immutable CoreConfigContext snapshot -> CoreConfigSingboxService/CoreConfigV2rayService -> config.json under binConfigs/ -> ProcessService spawning the core binary. Output boundaries are the spawned core's local SOCKS/API ports, the OS system proxy, and files under bin/, guiConfigs/, guiLogs/, guiTemps/, guiBackups/.

All 13 data flow claims →

Behavior traces

Three flows were traced end-to-end. Startup goes through single-instance guard, config load, SQLite table creation, ViewModel init, core init and a first Reload. Server activation goes through GetDefaultServer, CoreConfigContextBuilder.BuildAll, config generation, process spawn, system proxy update and an availability ping. Subscription update iterates SubItems, downloads with proxy fallback, parses into ProfileItem rows, and conditionally triggers Reload. Self-update and app-exit are also traced below.

Testing signals

Tests live exclusively in ServiceLib.Tests and use TUnit (not xUnit/NUnit) with TUnit.Assertions.Should fluent assertions. Coverage concentrates on the pure/parsing layers: Fmt share-URI round-trips, V2ray and sing-box config generation, CoreConfigContextBuilder behavior, HTTP request-header parsing, a regex guard, and CoreManager helpers. The CI test workflow runs 'dotnet test' on ubuntu-latest against .NET 10.x and publishes TRX results to PRs. There are no UI tests for either shell and no tests over SQLite persistence, process spawning, sysproxy, or the updater.

Risk map

The biggest risk surface is OS-level mutation: registry/WinInet proxy changes, autostart registration, sudo shell scripts carrying a GUI-entered sudo password, and a self-updater that extracts a network-downloaded zip over the install directory. SQL built by string interpolation in ProfileModels is only partially sanitized. The GlobalHotKeys submodule and ServiceLib.UdpTest project reference are easy build breakers. Heavy catch-all swallowing and a 3000-line ConfigHandler concentrate blast radius, and the ProfileItem ConfigVersion migration chain is delicate and untested.

All 14 risk map claims →

Extension points

Extension happens at four levels: (1) protocol support via a new *Fmt class plus entries in FmtHandler's switch/prefix dispatch, Global.ProtocolShares/ProtocolTypes, EConfigType and the two SupportConfigType sets; (2) new cores via a CoreInfo record in CoreInfoManager.InitCoreInfo and Global.CoreUrls; (3) core config generation via the per-concern services under Services/CoreConfig/{Singbox,V2ray} plus embedded Sample templates and FullConfigTemplateItem overrides; (4) UI via shared ViewModels + per-shell SimpleViewLocator view resolution and AppEvents channels. Group-type profiles (PolicyGroup/ProxyChain) and subscription prev/next chains are the built-in composition mechanism.

Contributor handoff

All logic changes belong in ServiceLib; the two shells should stay thin views over shared ViewModels. Read the order below before editing: Global.cs constants, ConfigHandler, CoreConfigContextBuilder, the relevant CoreConfig service, FmtHandler, and the target ViewModel. Build requires .NET 10 SDK (global.json) and a recursive submodule checkout for the Desktop project; test via 'dotnet test v2rayN/ServiceLib.Tests'. Respect the ConfigVersion migration chain, the {0} argument-template convention, embedded Sample resource names, and the LoadCore ordering (main config -> stop -> remove tun -> start -> wait for pre-socks port -> start pre-service).

Languages

LanguageFilesShare of source
C#28398%
YAML16docs/config
Shell72%
JSON1docs/config
Markdown1docs/config

Start reading here

Probable source entrypoint: v2rayN/ — inferred from the directory tree and manifest, not the upstream docs.

Source roots

v2rayN/ (387 files)

Source layout — v2rayN/

PathFiles
v2rayN/ServiceLib/179
v2rayN/ServiceLib.Tests/16
v2rayN/ServiceLib.UdpTest/9
v2rayN/v2rayN/68
v2rayN/v2rayN.Desktop/73
v2rayN/Directory.Build.props1
v2rayN/Directory.Packages.props1
v2rayN/v2rayN.sln1
v2rayN/v2rayN.slnx1

Repository structure

Top-level pathFiles
v2rayN/387
.github/17

Docs found: README.md

CI & config entrypoints

Structural health signals

Average score 6.4/10 across 96 analyzed source files; 65 hotspots surfaced.

These are deterministic review leads — size, churn, and structural signals — not proof of a bug in this project.

Recent history