Skip to content

Repository files navigation

VCore

English · 简体中文 · Русский

VCore is a standalone, host-agnostic Rust client proxy core. It provides proxy graphs, static select proxy groups, DNS, routing rules, GeoData, an HTTP listener, a TUN data plane, and a loopback Controller through strict YAML configuration and Invoke API v5. The internal configuration schema revision is 13; the revision appears only in the version response and buildIdentity, not in YAML.

Features

  • Outbounds: VLESS + XHTTP + TLS/REALITY, SOCKS5 CONNECT/UDP ASSOCIATE, AnyTLS TCP/UoT, and DIRECT.
  • Proxy chains: dialer-proxy forms a directed acyclic graph of arbitrary length. If node A points to B, the physical path is client -> B -> A -> target.
  • Proxy groups: static select groups keep ordered members, including concrete nodes, nested groups, DIRECT, and REJECT; their current-session selection can be changed live through the Controller. dialer-proxy remains node-only.
  • Routing: ordered DOMAIN, DOMAIN-SUFFIX, DOMAIN-KEYWORD, GEOSITE, GEOIP, IP-CIDR, IP-CIDR6, DST-PORT, NETWORK, and final MATCH rules.
  • DNS: fixed-IP UDP/TCP nameservers, explicit outbounds, ordered policy/failover, typed and opaque caches, singleflight, and TUN UDP/TCP port 53 interception.
  • TUN: raw IPv4/IPv6, TCP/UDP, local ICMPv4/ICMPv6 Echo replies, HTTP/TLS/QUIC sniffing, and four per-session traffic counters.
  • Listener: an optional loopback-only HTTP CONNECT/forward listener with mandatory Basic authentication.
  • GeoData: VCore manages geosite.dat and geoip.dat under dataDir/geodata, loads them on demand, and can update them through a proxy chain.
  • Delay measurement: measureDelay accepts 1–5 node-only configurations per call, uses up to five private workers, and preserves input order in its results.

Configuration

docs/config.yaml is the only complete example. Key constraints:

  • YAML is limited to 256 KiB and rejects unknown fields, anchors, aliases, custom tags, and obsolete structures.
  • The top level must contain at least one proxy and either port or an enabled tun.
  • Proxy and group definition names share one exact, case-sensitive namespace. Names are 1–64 UTF-8 bytes, reject surrounding Unicode whitespace, controls, , # / ? & = % \, . and .., and reserve DIRECT, REJECT, and RULES; internal ordinary spaces, CJK, and emoji are allowed.
  • proxy-groups accepts only select. Member order and duplicates are preserved; an omitted default-selected selects the first member, while an explicit value must name a direct member. Proxy chains and nested groups must each be acyclic.
  • rules is required and must end with exactly one MATCH targeting a configured proxy node or proxy group.
  • DIRECT and REJECT are built-in actions and group members; every other route target must be a configured proxy node or proxy group. DNS alone also reserves RULES.
  • Configuration is delivered inline through configYaml / configYamls; VCore does not read host configuration paths.
  • Runtime values such as the Controller, TUN fd, Controller port, and secret are generated by the host and are not stored in user RAW YAML.

Lifecycle and ABI

Cross-platform entry points:

char *VCoreInvoke(const char *request_json);
void VCoreFree(char *response);

Windows packages also use the revision-3 host bridge for the all-app VPN policy, profiles, Session Snapshots, and the optional session backend:

char *VCoreWindowsVpnInvoke(const char *request_json);

The public runtime has one instance:

initialize
  -> createInstance
  -> prepare(configYaml)
  -> start
  -> stop
  -> destroyInstance

instanceId is a generation token that is never reused by the current runtime. Commands for the same instance fail fast when another command is active; pure validateConfig calls may run concurrently. See docs/invoke-api.md for the complete envelope, methods, fd ownership, and Android protect contract.

Runtime state is exposed through a session-local loopback Controller:

GET /traffic
GET /group
GET /group/{name}
GET /proxies/{name}
PUT /proxies/{name}
Authorization: Bearer <secret>

GET /traffic is a one-time up/down/upTotal/downTotal TUN snapshot. The group endpoints expose and change the selected direct member of static select groups; a successful change affects only new physical TCP, UDP, and DNS transports in the current session. It does not migrate existing connections, UDP associations, DNS state, or pooled TCP transports, and it never performs automatic failover. A Controller that manages groups requires one Bearer secret for all routes and may run without TUN. See docs/controller-api.md.

Platforms

Platform Data plane Status
iOS / macOS The host provides a utun fd; VCore duplicates it and uses a synchronous rust-tun device with Tokio AsyncFd Implemented; the release iOS device footprint remains a release gate
Android VpnService provides a raw-IP fd; every outbound socket must pass the protect callback first Implemented; the physical-device matrix remains a release gate
Windows Windows.Networking.Vpn AppContainer Provider plus one full-trust runtime per session; package-local named pipes carry raw IP A development-signed Windows 11 ARM64 package passed functionality, lifecycle, pressure, and bounded-batching acceptance
Linux Unsupported; startup fails closed

Windows does not use an fd emulation layer. The Provider owns only VpnChannel, buffers, routes, physical-network monitoring, the packet gateway, and fail-closed Stop. The complete VCore runtime, Controller, DNS, rules, and outbounds live in the Session Host. The packet channel keeps protocol-v1 framing and batches at most eight already-ready frames without waiting for future packets.

Resource Bounds

The current TUN profile keeps local structural bounds rather than a fixed admission limit on the total number of business flows:

raw packet / MTU                 1,500 bytes
packet queue                     256
ordinary event / UDP response    128
DNS ingress / DNS response       128 / 128
TCP buffer                       32 KiB per direction
TLS / XHTTP buffer               64 KiB
DNS typed cache                  256 entries
DNS opaque cache                 64 entries / 256 KiB
GeoData allocation capacity      8 MiB

Windows advertises a 1,400-byte L3 MTU as required by StartWithMainTransport and caps TUN UDP responses at 1,352 bytes; 1,500 bytes remain the cross-platform parser ceiling.

TCP sessions, ordinary UDP associations, half-open connections, outbound handshakes, and active DNS transports are created on demand. Bounded queues, per-flow buffers, wire/parser limits, timeouts, idle cleanup, and caches provide structural safety. The iOS 35/45 MiB targets are best-effort observations and do not change lifecycle results.

Documentation

Example

Validation

cargo fmt --all -- --check
cargo test --all-features --all-targets
cargo clippy --locked --all-features --lib --bins -- -D warnings
cargo test --manifest-path crates/vcore-netstack/Cargo.toml --all-targets
cargo clippy --manifest-path crates/vcore-netstack/Cargo.toml --all-targets -- -D warnings
uv run --project scripts --locked vcore-scripts check c-header
uv run --project scripts --locked vcore-scripts check tls-dependencies
uv run --project scripts --locked python -m unittest discover -s scripts/tests
uv run --project scripts --locked ruff check scripts
uv run --project scripts --locked ruff format --check scripts

Platform artifacts (see scripts/README.md for complete commands and environment variables):

uv run --project scripts --locked vcore-scripts build apple
uv run --project scripts --locked vcore-scripts build android
uv run --project scripts --locked vcore-scripts build windows

See docs/acceptance.md for the current validated scope and deferred physical-device and Windows release gates.

Credits

VCore's dependencies, maintained forks, public API/protocol references, architectural references, and interoperability counterparts include:

License

VCore is licensed under the MIT License.

About

Cross-platform proxy core for VPN apps.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages