CodeVetter
← All unpacks
CodeVetter · Repo Unpack evidence

fatedier/frp

Scanned commit d20a232996 dated 2026-09-10 — last upstream commit. Generated by codevetter 1.12.0 on 2026-09-22.

github.com/fatedier/frp ↗ · 516 files · 2.1 MB

frp README | 中文文档 Sponsors frp is an open source project with its ongoing development made possible entirely by the support of our awesome sponsors.

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

frp is a fast reverse proxy written in Go that exposes services behind NATs/firewalls via a public server (frps) and an in-NAT client (frpc). It supports TCP, UDP, HTTP, HTTPS, TCPMUX, and secret/P2P modes (stcp, sudp, xtcp) over TCP, KCP, QUIC, WebSocket, or TLS control transports, with token/OIDC auth, HTTP-based server plugins, embedded Vue dashboards, and optional dynamic proxy persistence. The codebase is split into cmd/ entrypoints, server/ and client/ runtimes, and a large pkg/ shared library (config v1, msg protocol, wire v2, auth, nathole, plugins, vnet).

System map

The repo builds two binaries from a single Go module: frps (server, cmd/frps) and frpc (client, cmd/frpc), both driven by cobra. server/service.go constructs a Service that multiplexes control-plane listeners (TCP mux, KCP, QUIC, WebSocket, raw TLS, internal SSH pipe) on shared ports and owns the ControlManager, proxy.Manager, plugin.Manager, ports.Manager and vhost routers. client/service.go constructs a Service that dials frps through a pluggable Connector and keeps a Control session alive with backoff retries. Shared protocol and config code lives under pkg/ (msg, proto/wire, config/v1, auth, transport, util). State is entirely in-memory except an optional client-side JSON store for dynamic proxies. Two Vue 3 apps under web/ provide dashboards and are embedded via the assets package, or excluded with the 'noweb' build tag.

Feature catalog

frp exposes eight proxy types (tcp, udp, http, https, tcpmux, stcp, sudp, xtcp) plus three visitor types (stcp, sudp, xtcp) for private/P2P access. Features include token and OIDC auth, per-proxy encryption/compression/bandwidth limits, load-balancer groups, health checks, PROXY protocol and host-header rewriting, HTTP server plugins, client plugins (static_file, unix_domain_socket, http(s) converters, socks5, tls2raw, virtual_net), NAT hole punching via STUN, an SSH tunnel gateway, a WireGuard-based VirtualNet, Prometheus metrics, dashboards for both daemons, and a rich frpc CLI with per-type subcommands, verify, nathole discover and admin commands.

All 15 feature catalog claims →

Data flow

Config enters as TOML/YAML/JSON (or deprecated INI), is template-rendered with environment variables, decoded into pkg/config/v1 types, completed, and validated before use. Control-plane data flows as typed msg structs (Login, NewProxy, NewWorkConn, Ping, NatHole*) over a single muxed connection, versioned by the v1/v2 wire protocol. User traffic flows: public listener on frps -> proxy -> pooled work connection -> frpc -> optional plugin -> local service, joined byte streams via libio.Join. Admin data flows through gorilla/mux routers into adminapi controllers, and reloads re-merge config via the source.Aggregator.

Behavior traces

Four flows were traced end-to-end. (1) frps startup: cobra -> LoadServerConfig -> validate -> NewService wires all listeners/managers -> Run spawns per-listener goroutines. (2) frpc startup+login: cobra -> LoadClientConfigResult -> aggregator merge -> NewService -> Run -> loopLoginUntilSuccess -> controlSessionDialer.Dial -> NewControl -> ctl.Run. (3) TCP proxy request path: TCPProxy.Run listens -> user conn -> GetWorkConn -> ReqWorkConn -> client NewWorkConn -> StartWorkConn -> InWorkConn -> join to local service. (4) Admin reload: GET /api/reload -> Reload -> UpdateConfigSource -> reloadConfigFromSourcesLocked -> UpdateAllConfigurer.

Testing signals

Unit tests use Go's testing with testify and rodaine/table, spread through pkg/, client/, server/ and cmd/ (run via `make test`/`gotest` with the noweb tag). End-to-end tests use Ginkgo/Gomega under test/e2e with a framework that spawns real frps/frpc binaries, organized into v1/basic, v1/features, plugin, legacy and mock server helpers; `make e2e` runs hack/run-e2e.sh with 16-way parallelism. Cross-version compatibility suites run released binaries via hack/run-e2e-compatibility.sh and download scripts. The web workspace uses Vitest + @vue/test-utils; linting is via golangci-lint (.golangci.yml) plus gofmt/gofumpt/gci/vet make targets and GitHub Actions workflows.

Risk map

The highest-risk areas are command-execution token sources (gated behind the TokenSourceExec unsafe feature), filesystem-serving and socket-exposing client plugins (static_file, unix_domain_socket which can expose docker.sock), the VirtualNet TUN setup that shells out to ifconfig/route on macOS, and admin web servers that depend on auth middleware correctness. Concurrency risk concentrates in server/control.go's ControlManager, which enforces a documented lock order (runMu -> cm.mu -> lifecycleMu -> registry) and generation handoff barriers; regressions there cause deadlocks or leaked controls. The deprecated INI path (pkg/config/legacy) and the testing-only --config_dir mode are legacy surface. Plugin content mutation uses a deliberate panic on wrong types.

All 13 risk map claims →

Extension points

frp is built around registries. New proxy types plug in through three coordinated tables: proxyConfigTypeMap in pkg/config/v1, server-side RegisterProxyFactory (init() per type in server/proxy), and client-side RegisterProxyFactory (init() in client/proxy). Client connection-handling plugins register via pkg/plugin/client's Register/Create; server hooks come from external HTTP plugin processes managed by pkg/plugin/server. frpc CLI subcommands are generated automatically from the proxy type list. Config extensibility goes through source.Source implementations aggregated by source.Aggregator, and embedding is supported via pkg/virtual.Client plus ServiceOptions hooks (ConnectorCreator, HandleWorkConnCb). Feature gates (pkg/policy/featuregate) guard experimental features.

Contributor handoff

Start with AGENTS.md for the command surface: `make build|frps|frpc|test|e2e|fmt|fmt-more|gci|vet`, `golangcici-lint run`, `make web`. Read cmd/frps/root.go + cmd/frpc/sub/root.go, then server/service.go and client/service.go for wiring, and server/control.go for the lifecycle/locking protocol before touching session code. Config changes must go through pkg/config/v1 types + validation and be tested for TOML/YAML/JSON and strict mode. Protocol changes must update pkg/msg on both sides and consider the v2 wire negotiation in pkg/proto/wire. E2E tests need built binaries and Ginkgo; unit tests run with the noweb tag when dashboards aren't built.

Languages

LanguageFilesShare of source
Go35177%
Vue4710%
TypeScript429%
Markdown14docs/config
YAML11docs/config
JSON10docs/config
CSS4docs/config
Sass41%

Start reading here

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

Source roots

pkg/ (189 files)

Repository structure

Top-level pathFiles
pkg/189
web/128
test/70
server/44
client/34
cmd/10
.github/9
conf/6

Docs found: AGENTS.mdCLAUDE.mdREADME.md

Package

go.mod — github.com/fatedier/frp, 0 declared dependencies.

CI & config entrypoints

Structural health signals

Average score 7.5/10 across 96 analyzed source files; 12 hotspots surfaced.

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

Recent history