v2fly/v2ray-core
A platform for building proxies to bypass network restrictions.
Healthy across the board
Permissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit today
- ✓9 active contributors
- ✓MIT licensed
Show 3 more →Show less
- ✓CI configured
- ✓Tests present
- ⚠Concentrated ownership — top contributor handles 51% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/v2fly/v2ray-core)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/v2fly/v2ray-core on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: v2fly/v2ray-core
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/v2fly/v2ray-core shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across the board
- Last commit today
- 9 active contributors
- MIT licensed
- CI configured
- Tests present
- ⚠ Concentrated ownership — top contributor handles 51% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live v2fly/v2ray-core
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/v2fly/v2ray-core.
What it runs against: a local clone of v2fly/v2ray-core — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in v2fly/v2ray-core | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 30 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of v2fly/v2ray-core. If you don't
# have one yet, run these first:
#
# git clone https://github.com/v2fly/v2ray-core.git
# cd v2ray-core
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of v2fly/v2ray-core and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "v2fly/v2ray-core(\\.git)?\\b" \\
&& ok "origin remote is v2fly/v2ray-core" \\
|| miss "origin remote is not v2fly/v2ray-core (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "app/app.go" \\
&& ok "app/app.go" \\
|| miss "missing critical file: app/app.go"
test -f "app/dispatcher/dispatcher.go" \\
&& ok "app/dispatcher/dispatcher.go" \\
|| miss "missing critical file: app/dispatcher/dispatcher.go"
test -f "app/dns/dns.go" \\
&& ok "app/dns/dns.go" \\
|| miss "missing critical file: app/dns/dns.go"
test -f "app/commander/commander.go" \\
&& ok "app/commander/commander.go" \\
|| miss "missing critical file: app/commander/commander.go"
test -f "app/log/log.go" \\
&& ok "app/log/log.go" \\
|| miss "missing critical file: app/log/log.go"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 30 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~0d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/v2fly/v2ray-core"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
V2Ray Core is a high-performance, modular proxy platform written in Go that enables users to build custom proxy networks for bypassing network restrictions and censorship. It provides a flexible architecture for routing, protocol handling (SOCKS, HTTP, Shadowsocks, VMess, VLESS, etc.), and network traffic manipulation through its core dispatcher (app/dispatcher/dispatcher.go) and protocol implementations across the infra/ and proxy/ modules. Modular monorepo organized by responsibility: app/ contains plugin-like services (dispatcher, DNS, commander, browser forwarder), proxy/ holds protocol implementations, infra/ has network primitives, and transport/ handles link-layer protocols. Configuration flows through protobuf definitions (.proto files) compiled to config.pb.go. Root annotations.go suggests annotation-based processing for generated code.
👥Who it's for
Network engineers, privacy advocates, and open-source contributors who need to deploy censorship-circumvention infrastructure, build custom proxy chains, or contribute to a production-grade proxy platform. End users install V2Ray through clients that wrap this core.
🌱Maturity & risk
Production-ready and actively maintained. The codebase is substantial (~4.5M lines of Go), has comprehensive CI/CD workflows (linter, test, release, codeql), codecov integration, and active community contributions. Recent GitHub Actions workflows indicate ongoing development, though specific commit recency is not shown in provided data.
Low-to-moderate risk for a security-critical project. Heavy dependencies on third-party crypto/networking libraries (quic-go, gorilla/websocket, protoreflect), but these are well-vetted. Protocol-buffer code generation (*pb.go files) requires careful maintenance. No single-maintainer risk visible due to org structure (v2fly organization). Breaking changes managed via semantic versioning (v5 noted in goreportcard badge).
Active areas of work
Active maintenance visible through GitHub Actions workflows for linting (golangci), testing, signing releases, and codeql analysis. Dependabot configured for dependency updates. No specific recent PRs/milestones shown in file list, but stale issue management workflow indicates triage activity.
🚀Get running
Clone the repo, ensure Go 1.16+ is installed (inferred from modern Go codebase), then: git clone https://github.com/v2fly/v2ray-core.git && cd v2ray-core && make build (Makefile present). Check .github/workflows/test.yml for exact test invocation.
Daily commands:
go build -o v2ray ./cmd/v2ray && ./v2ray -config=config.json (inferred). Alternatively, make build from Makefile. Test with go test ./... (check .github/workflows/test.yml for CI command patterns).
🗺️Map of the codebase
app/app.go— Core application initialization and lifecycle management—every contributor must understand how the V2Ray instance bootstraps and coordinates all subsystems.app/dispatcher/dispatcher.go— Central request routing engine that decides which outbound to use—the load-bearing component that handles all traffic flow decisions.app/dns/dns.go— DNS resolution subsystem including DoH/DoQ support and FakeDNS—critical for domain-based routing and privacy.app/commander/commander.go— Control plane API server for runtime management and statistics—essential for understanding how external tools interact with V2Ray.app/log/log.go— Logging infrastructure and severity filtering—necessary for debugging and understanding execution flow across all modules.app/observatory/burst/burstobserver.go— Health monitoring and outbound probing system—critical for understanding failover and availability detection logic.app/instman/instman.go— Instance manager for multi-instance support and lifecycle coordination—key to understanding concurrent proxy management.
🛠️How to make changes
Add a new DNS nameserver type (e.g., DNS-over-QUIC)
- Create new file
app/dns/nameserver_quic.goimplementing thedns.NameServerinterface with Dial(), Cleanup(), and QueryIP() methods (app/dns/nameserver_quic.go) - Add protobuf configuration message in
app/dns/config.protofor QUIC-specific settings (server address, port, TLS options) (app/dns/config.proto) - Update
app/dns/dns.goin the nameserver creation switch statement to instantiate your new nameserver type based on config (app/dns/dns.go) - Register the new nameserver in the dependency injection container via
annotations.goif using named instances (annotations.go) - Add unit tests in
app/dns/nameserver_quic_test.gocovering success cases, timeouts, and SERVFAIL handling (app/dns/nameserver_quic_test.go)
Add a new routing rule type (e.g., route by GeoIP database)
- Extend
app/dispatcher/config.protowith a new routing rule message type (e.g., GeoIPRule with database path and country codes) (app/dispatcher/config.proto) - Create
app/dispatcher/route_geoip.goimplementing the rule matcher interface with Match(ctx) bool method (app/dispatcher/route_geoip.go) - Update
app/dispatcher/default.goto instantiate your rule type in the routing engine initialization (app/dispatcher/default.go) - Add test coverage in
app/dispatcher/default_test.gowith mock GeoIP data and routing assertions (app/dispatcher/default_test.go)
Add a new control plane command (e.g., restart outbound)
- Define the gRPC service and RPC method in
app/commander/command.proto(e.g., RestartOutbound(outbound_name)) (app/commander/command.proto) - Create
app/commander/service_outbound.goimplementing the generated service interface with the restart logic (app/commander/service_outbound.go) - Register the service in
app/commander/commander.govia the ServiceServer registration mechanism (app/commander/commander.go) - Add integration tests in
app/commander/commander_test.gothat call the gRPC endpoint via a test client (app/commander/commander_test.go)
Add a new health check probe strategy
- Create
app/observatory/burst/probe_custom.goimplementing the probe interface with Probe(ctx, outbound) (RTT, error) signature (app/observatory/burst/probe_custom.go) - Extend
app/observatory/burst/config.protowith ProbeConfig message for strategy-specific settings (app/observatory/burst/config.proto) - Update
app/observatory/burst/healthping.goto select and instantiate your probe strategy in the health check loop (app/observatory/burst/healthping.go) - Add tests in
app/observatory/burst/healthping_result_test.govalidating probe result aggregation and failover decisions (app/observatory/burst/healthping_result_test.go)
🔧Why these technologies
- Protocol Buffers (protobuf) — Configuration serialization and gRPC service definitions; enables versioning, language interoperability, and compact binary encoding for control messages
- Go (Golang) — High-concurrency network proxy requires goroutines and channels; Go's net package provides robust, cross-platform network abstractions
- gRPC — Control plane API allows external tools to query stats, change routing, and manage instances at runtime without reimplementing protocol details
- Dependency Injection (custom annotation framework) — Complex subsystem interdependencies (DNS ↔ Dispatcher ↔ Health) require late binding and pluggable implementations for extensibility
⚖️Trade-offs already made
-
FakeDNS (local DNS spoofing) instead of transparent DNS proxy only
- Why: Enables traffic interception without packet filtering, works cross-platform, avoids CAP_NET_ADMIN on Linux
- Consequence: Requires domain→IP mapping overhead and careful IPAM; can conflict with legitimate traffic to those IPs
-
Centralized dispatcher vs. per-inbound handlers
- Why: Single dispatcher unifies routing logic, statistics, and sniffer coordination across all in
- Consequence: undefined
🪤Traps & gotchas
Protocol Buffer compilation: .pb.go and .generated.go files are auto-generated from .proto files; editing them directly will be overwritten. Must regenerate via build step (check Makefile for protoc invocation). Error messages: .generated.go files use code generation from annotations; new error types require annotating source code per annotations.go pattern. DNS sniffer dependency: app/dispatcher/fakednssniffer.go suggests careful test isolation needed for DNS-dependent code. gRPC service versioning: Commander API in app/commander/service.go is versioned; breaking changes require protocol buffer major version bumps. No explicit .env shown; configuration entirely file-based (JSON config.json pattern).
🏗️Architecture
💡Concepts to learn
- SNI (Server Name Indication) Sniffer — V2Ray uses SNI extraction (
app/dispatcher/sniffer.go) to identify encrypted traffic destinations without decryption, enabling domain-based routing for HTTPS and TLS connections - Protocol Buffer (protobuf) Code Generation — All configuration and service definitions use
.protofiles compiled to Go code (config.pb.go); understanding this is essential for adding new config options or gRPC services - Proxy Chain / Protocol Stacking — V2Ray's core strength is composing multiple protocols and transports in sequence (e.g., VMess-over-WebSocket-over-TLS); understanding the inbound/outbound pattern in
proxy/is critical - gRPC Service for Runtime Control — The commander app (
app/commander/) exposes a gRPC API for stats, config reloads, and outbound management; contributors adding new metrics must extend this service - Cuckoo Filter for Duplicate Detection — V2Ray uses
seiflotfy/cuckoofilter(listed in credits) for efficient DNS cache collision detection and connection deduplication in high-throughput scenarios - QUIC Protocol (UDP-based Reliable Transport) — V2Ray supports QUIC for low-latency proxying and censorship resistance; understanding
quic-gointegration is needed for transport-layer contributors - Annotation-Driven Code Generation — The
annotations.gopattern enables auto-generation of error types and documentation from inline annotations; new error definitions must follow this pattern to integrate cleanly
🔗Related repos
shadowsocks/shadowsocks-core— Direct alternative proxy protocol implementation; V2Ray supports Shadowsocks as one transport and this repo shows a pure SS implementation for comparisonv2fly/v2ray-core-for-android— Official Android client wrapper around this core library, shows how V2Ray core is packaged and exposed to end usersXTLS/Xray-core— Active fork of V2Ray with enhanced XTLS protocol support; shares 80% codebase but optimizes for TLS performancev2fly/v2fly-github-io— Official documentation repository (referenced in README); essential reading for understanding config schema and protocol capabilitiesquic-go/quic-go— Direct dependency for QUIC protocol support in V2Ray transports; contributors working on QUIC proxies should understand this library
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive unit tests for app/dns/nameserver_doh.go and nameserver_quic.go
The DNS module has several nameserver implementations with existing test files (nameserver_doh_test.go, nameserver_quic_test.go, nameserver_tcp.go), but nameserver_local.go and nameserver_fakedns.go lack dedicated test files. Given the critical nature of DNS resolution in a proxy platform, adding tests for these implementations would improve reliability. Additionally, nameserver_tcp.go has no corresponding _test.go file despite being a core transport mechanism.
- [ ] Create app/dns/nameserver_tcp_test.go with tests for TCP DNS resolution edge cases
- [ ] Expand app/dns/nameserver_fakedns_test.go to cover all code paths in nameserver_fakedns.go
- [ ] Add integration tests in app/dns/dns_test.go verifying nameserver fallback and retry logic
- [ ] Ensure test coverage for timeout and error handling scenarios across all nameserver implementations
Add missing protobuf configuration documentation for app/commander/webcommander and app/browserforwarder
The repo contains config.proto files for webcommander and browserforwarder modules, but there are no corresponding documentation files explaining the protobuf schema, configuration options, or usage examples. This is a gap since other modules in the project would benefit from clear proto documentation. Contributing detailed comments to the .proto files and creating usage guides would help new contributors understand these modules.
- [ ] Add comprehensive comments to app/commander/webcommander/config.proto explaining each field and its purpose
- [ ] Add comprehensive comments to app/browserforwarder/config.proto with examples
- [ ] Create or update documentation in .github explaining the webcommander API and configuration
- [ ] Add example configuration snippets to app/commander/webcommander/ and app/browserforwarder/ directories
Add integration tests for app/dispatcher/sniffer.go SNI detection and stats tracking
The dispatcher module contains sniffer.go, fakednssniffer.go, and stats.go with existing unit tests (stats_test.go), but there are no dedicated tests for the SNI detection logic or integration between sniffer and stats tracking. This is critical for a proxy platform as SNI detection accuracy affects routing decisions. Adding thorough tests would ensure reliability of traffic classification.
- [ ] Create app/dispatcher/sniffer_test.go with tests for SNI extraction from various protocols (TLS, HTTP)
- [ ] Create app/dispatcher/fakednssniffer_test.go testing the fake DNS-based SNI detection fallback
- [ ] Add integration tests verifying stats are correctly recorded for sniffer-detected domains
- [ ] Test edge cases like malformed packets, unsupported protocols, and concurrent SNI detection
🌿Good first issues
- Add unit tests for
app/dispatcher/stats.go— the file exists with stats methods butstats_test.gois sparse; new contributors can write tests for packet counting and outbound statistics tracking - Expand error documentation in
app/dns/dnscommon_test.go— test coverage is minimal; adding more test cases for DNS cache behavior, TTL handling, and IPv6 fallback would improve reliability - Add missing integration test for protocol negotiation in
app/dispatcher/sniffer.go— currently no test coverage visible for the fake DNS sniffer; write tests validating SNI extraction for common protocols (TLS, HTTP/2)
⭐Top contributors
Click to expand
Top contributors
- @xiaokangwang — 51 commits
- @dependabot[bot] — 40 commits
- @dyhkwong — 2 commits
- @leo9800 — 2 commits
- @rhjdvsgsgks — 1 commits
📝Recent commits
Click to expand
Recent commits
05cc542— Update version v5.49.0 (xiaokangwang)0b85f9b— chore: regenerate protobuf files (xiaokangwang)bf57f11— also parse X-Forwarded-For in httpupgrade (#3676) (rhjdvsgsgks)d84ee59— Chore: bump github.com/go-playground/validator/v10 (dependabot[bot])2f4e6f0— Chore: bump google.golang.org/grpc from 1.79.3 to 1.80.0 (dependabot[bot])0303e67— Chore: bump github.com/pion/stun/v3 from 3.1.1 to 3.1.2 (dependabot[bot])3abc927— Chore: bump golang.org/x/net from 0.52.0 to 0.53.0 (dependabot[bot])044994a— Chore: bump golang.org/x/crypto from 0.49.0 to 0.50.0 (dependabot[bot])cbab1db— Add WebRTC Tunnel Support in V2Ray (#3660) (xiaokangwang)d1e2c23— Add RRPIT - Rapid Reliable Packet Interactive Transport (#3658) (xiaokangwang)
🔒Security observations
The v2ray-core repository demonstrates reasonable security practices with a defined reporting policy and code quality tools (CodeQL, linting). However, the security posture is impacted by an expired GPG key for vulnerability reporting, incomplete security policy documentation, and lack of visible hardening guidance for web-facing components. The codebase appears to follow Go security best practices based on the presence of code analysis workflows and linting configurations. Primary concerns are process-related rather than code-specific vulnerabilities visible in the provided file structure. Recommendations focus on updating security documentation, rotating cryptographic keys, and providing deployment hardening guidance.
- Medium · Expired GPG Security Key —
SECURITY.md. The GPG public key listed in SECURITY.md for vulnerability reporting expired on 2022-01-02. This key can no longer be trusted for secure communications and should be rotated immediately to maintain secure reporting channels. Fix: Generate a new GPG key pair, publish the new public key in SECURITY.md with a future expiration date (e.g., 3+ years), and notify the security community of the key rotation. - Medium · Incomplete Security Policy Documentation —
SECURITY.md. SECURITY.md lacks specific version support timelines, security update delivery SLAs, and a clear deprecation schedule. This makes it difficult for users to understand which versions receive security patches and for how long. Fix: Add explicit version support matrix with EOL dates, define security update response times, and specify which versions receive backported security fixes. - Low · Missing Security Headers Documentation —
app/commander/webcommander, app/browserforwarder. No documented security headers or hardening guidelines visible in the repository for deployment configurations, particularly for the webcommander and browserforwarder modules which expose HTTP interfaces. Fix: Document recommended security headers (CSP, X-Frame-Options, X-Content-Type-Options, etc.) and provide hardened configuration examples for web-facing components. - Low · Potential Information Disclosure in Error Messages —
app/*/errors.generated.go (multiple files). Multiple generated error files (*.generated.go) across modules suggest automatic error generation. Without proper review, these could expose internal implementation details or sensitive information in error outputs. Fix: Audit auto-generated error messages to ensure they don't leak sensitive information. Implement error sanitization for user-facing outputs while maintaining detailed logging for debugging.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.