This document describes the architecture of the client-side plugin system in frp, which allows extending proxy functionality without modifying core logic. Plugins intercept connections from the server before they reach the local service, enabling protocol translation, authentication, and service integration.
For details about specific built-in plugins (unix_domain_socket, http_proxy, socks5, etc.), see Built-in Client Plugins. For server-side plugin extensibility, see Server Plugin System.
The client plugin system operates as a connection interceptor in the proxy data path. When a plugin is configured for a proxy, connections from the work connection are routed to the plugin instead of being directly forwarded to the local service specified by localIP and localPort.
Diagram: Plugin Position in Proxy Data Flow
Sources: pkg/proxy/proxy.go95-136
Plugins implement the Plugin interface defined in the pkg/plugin/client package. The interface requires three methods:
| Method | Purpose |
|---|---|
Handle(context.Context, *ConnectionInfo) | Process incoming connection, called for each work connection |
Name() string | Return plugin type identifier |
Close() error | Clean up resources when proxy stops |
Diagram: Plugin Interface and Implementation Pattern
The ConnectionInfo structure provides access to:
Conn: The processed connection (after encryption/compression if configured) pkg/plugin/client/plugin.go50-51UnderlyingConn: Raw TCP connection before processing pkg/plugin/client/plugin.go52SrcAddr, DstAddr: Source and destination addresses pkg/plugin/client/plugin.go53-54ProxyProtocolHeader: Pre-built proxy protocol header if configured pkg/plugin/client/plugin.go55Sources: pkg/plugin/client/plugin.go42-56 pkg/plugin/client/http2https.go31-69 pkg/plugin/client/unix_domain_socket.go33-73
Plugins use a factory registration pattern during initialization:
Diagram: Plugin Registration and Instantiation Flow
The registration mechanism uses init() functions in each plugin implementation:
Register(pluginType, factoryFunc) in its init() function pkg/plugin/client/http2https.go27-29func(PluginContext, v1.ClientPluginOptions) (Plugin, error) pkg/plugin/client/plugin.go61BaseProxy and managed throughout the proxy lifecycle.Sources: pkg/plugin/client/plugin.go58-75 pkg/plugin/client/http2https.go27-29 pkg/plugin/client/socks5.go30-32
Frp provides several built-in plugins that leverage different network and application layer strategies.
Plugins like https2http, http2https, https2https, and http2http use a shared httpBridgePlugin structure. They utilize httputil.ReverseProxy to transform requests.
Host) and forwards to a local HTTP service pkg/plugin/client/http2http.go35-52These plugins turn frpc into a proxy gateway:
CONNECT methods for tunneling pkg/plugin/client/http_proxy.go166-191armon/go-socks5 library to provide SOCKS5 proxying pkg/plugin/client/socks5.go34-57Sources: pkg/plugin/client/https2http.go1-69 pkg/plugin/client/http_proxy.go1-226 pkg/plugin/client/tls2raw.go1-93
Plugins are configured via the Plugin field in the proxy configuration. Each plugin type has its own options structure.
Diagram: Plugin Configuration Options
Sources: pkg/config/v1/plugin.go
The plugin lifecycle is tied to the proxy lifecycle:
| Phase | Action | Code Location |
|---|---|---|
| Creation | Plugin created during proxy initialization via plugin.Create() | pkg/plugin/client/plugin.go66-75 |
| Active | Handle() called for each incoming work connection | pkg/plugin/client/plugin.go45 |
| Shutdown | Close() called when proxy stops | pkg/plugin/client/plugin.go47 |
When a connection is handled by a plugin, the plugin is responsible for the full lifecycle of the ConnectionInfo.Conn. For example, in the Socks5Plugin, the plugin serves the connection and then closes it pkg/plugin/client/socks5.go53-57 In UnixDomainSocketPlugin, the plugin joins the local UDS connection and the proxy connection pkg/plugin/client/unix_domain_socket.go68
Sources: pkg/plugin/client/plugin.go42-48 pkg/plugin/client/socks5.go53-57 pkg/plugin/client/unix_domain_socket.go52-69
Several plugins handle TLS termination or initiation. The pkg/transport package provides utilities for this:
NewServerTLSConfig: Used by plugins like tls2raw and https2http to load certificates for terminating incoming TLS pkg/transport/tls.go96-126NewClientTLSConfig: Used for initiating secure connections to local backends pkg/transport/tls.go128-155Sources: pkg/transport/tls.go96-155 pkg/plugin/client/tls2raw.go49-53
Refresh this wiki