# System map — fatedier/frp

> Canonical page: https://codevetter.com/unpack/frp/system-map

# System map — fatedier/frp

Scanned commit d20a232996007dfe6ab425abc0a39a3ae9a0889b (2026-09-10). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

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.
- frps entrypoint is cmd/frps/root.go: cobra rootCmd.RunE loads config via config.LoadServerConfig, validates with validation.NewConfigValidator, then calls runServer -> server.NewService -> svr.Run. — [cmd/frps/root.go#L53-127](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/cmd/frps/root.go#L53-L127) [server/service.go#L139](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/server/service.go#L139)
- frpc entrypoint is cmd/frpc/sub/root.go: runClient -> config.LoadClientConfigResult -> source.NewAggregator -> client.NewService -> svr.Run; a --config_dir flag runs one Service per file via runMultipleClients. — [cmd/frpc/sub/root.go#L59-134](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/cmd/frpc/sub/root.go#L59-L134) [client/service.go#L163](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/client/service.go#L163)
- server.Service multiplexes the bind port with golib mux.Mux: default listener for TCP control, a prefix-matched websocket listener ('GET /~frp'), and a TLS listener that sniffs first byte 0x16 / FRPTLSHeadByte. — [server/service.go#L245-253](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/server/service.go#L245-L253) [server/service.go#L290-294](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/server/service.go#L290-L294) [server/service.go#L352-355](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/server/service.go#L352-L355)
- Optional listeners are created for KCP (netpkg.ListenKcp on KCPBindPort), QUIC (quic.ListenAddr with ALPN 'frp'), SSH tunnel gateway (ssh.NewGateway), and a tcpmux HTTPConnect multiplexer on TCPMuxHTTPConnectPort. — [server/service.go#L256-287](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/server/service.go#L256-L287) [server/service.go#L191-204](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/server/service.go#L191-L204) [pkg/ssh/gateway.go](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/pkg/ssh/gateway.go)
- The wire protocol has two versions: acceptConnection calls wire.CheckMagic to detect v2, then negotiates crypto/UDP-codec via ClientHello/ServerHello frames before reading the first msg. — [server/service.go#L555-593](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/server/service.go#L555-L593) [server/service.go#L623-680](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/server/service.go#L623-L680) [pkg/proto/wire](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/pkg/proto/wire)
- The client dials frps through a Connector interface (client/connector.go) supporting tcp, kcp, quic (one quic.Conn, streams converted via QuicStreamToNetConn), websocket/wss, and tls; ServiceOptions.ConnectorCreator allows swapping in a virtual pipe connector. — [client/connector.go#L33-60](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/client/connector.go#L33-L60) [client/connector.go#L104-137](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/client/connector.go#L104-L137) [client/connector.go#L216-226](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/client/connector.go#L216-L226) [client/service.go#L83-90](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/client/service.go#L83-L90)
- Server state is in-memory: registry.ClientRegistry tracks logical clients by user.clientID, proxy.Manager tracks live proxies, ports.Manager allocates TCP/UDP remote ports honoring AllowPorts, and vhost.Routers route HTTP(S) vhosts. — [server/service.go#L167-180](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/server/service.go#L167-L180) [server/registry](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/server/registry) [server/ports/ports.go](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/server/ports/ports.go) [pkg/util/vhost](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/pkg/util/vhost)
- The only persistent state is the optional client-side StoreSource: a JSON file (store.path) holding dynamic proxies/visitors, merged with file config by source.Aggregator. — [pkg/config/source/store.go](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/pkg/config/source/store.go) [pkg/config/source/aggregator.go](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/pkg/config/source/aggregator.go) [cmd/frpc/sub/root.go#L143-163](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/cmd/frpc/sub/root.go#L143-L163)
- Dashboards are Vue 3 apps web/frps and web/frpc (npm workspaces under web/), embedded into Go via the assets package; Makefile adds a 'noweb' build tag when web/*/dist is absent. — [web/package.json](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/web/package.json) [assets/assets.go](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/assets/assets.go) [Makefile#L4](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/Makefile#L4) [web/frps/package.json](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/web/frps/package.json) [web/frpc/package.json](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/web/frpc/package.json)
- Build produces CGO_ENABLED=0 binaries with build tags 'frps'/'frpc' plus optional 'noweb' (Makefile frps/frpc targets); go.mod pins go 1.25.0 with quic-go, kcp-go, yamux, gorilla/mux, go-oidc, prometheus, wireguard as key deps. — [Makefile#L40-44](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/Makefile#L40-L44) [go.mod#L3-39](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/go.mod#L3-L39)
- server/http and client/http packages implement admin API controllers behind gorilla/mux routers registered by registerRouteHandlers on each Service's webServer (httppkg.Server). — [server/api_router.go#L27-71](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/server/api_router.go#L27-L71) [client/api_router.go#L26-64](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/client/api_router.go#L26-L64) [server/http](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/server/http) [client/http](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/client/http)
- Both services disable quic-go receive-buffer warnings and ECN via env vars in package init, and set crypto.DefaultSalt = 'frp' for golib crypto. — [server/service.go#L70-78](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/server/service.go#L70-L78) [client/service.go#L47-55](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/client/service.go#L47-L55)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
