The Shape of frp: From Port Forwarding to Programmable Reachability

The central judgment of this series is that frp does not make a private network disappear; it makes selected reachability negotiable. frpc owns the private-side endpoint, frps supplies the public rendezvous and governance point, the control path allocates work, and the data path is either relayed or conditionally direct. This final synthesis connects those pieces into a design model: how to choose a path and exposure contract, how to carry the necessary controls with it, and how the SSH gateway, VirtualNet, and v2 direction extend the model without proving that every extension is equally mature or safe.

The invariant beneath the different modes

TCP, UDP, HTTP, HTTPS, tcpmux, STCP, and XTCP look different at the edge because they answer different questions about a request. TCP and UDP expose transport behavior. HTTP and HTTPS use host and path for routing and can transform headers. tcpmux uses an HTTP CONNECT host to share a listener. STCP makes the visitor relationship private instead of publishing an ordinary remote port. XTCP attempts to move the payload between clients when the two network edges permit it.

Underneath, the same invariant remains. A private-side client establishes and owns a relationship to a public frps server. The client declares a local service or visitor capability. The server authenticates and registers that relationship, applies whatever public routing or policy is configured, and coordinates the work needed for a request. The payload then follows the path that the selected mode and network conditions make possible. Even the direct case does not escape this structure: XTCP still uses frps for pre-checks, authorization, address exchange, detection behavior, and success reporting.

That invariant explains why frp is more than a port-forwarding command but less than an automatic private-network replacement. It can change the reachability of a selected service, route HTTP requests among registered backends, let a known visitor reach a private proxy, and attempt a peer-to-peer data path. It does not automatically route every private address to the Internet, infer an application’s authorization policy, or turn a failed NAT attempt into a working network path.

The separation between control and data is equally persistent. Login, RunID, proxy declarations, heartbeats, visitor admission, and work-connection allocation belong to the control relationship. Local service bytes belong to the data path. When the data path is relayed, frps carries it; when XTCP succeeds, the payload can travel directly between clients. In both cases, the control relationship explains who is allowed to participate and which proxy the path represents.

This is the architectural center of frp: controlled reachability through an owned client session and a public control point. Features are valuable when they make one part of that model more appropriate for a real constraint. They become misleading when they are treated as independent promises—“P2P” without NAT limits, “authentication” without a payload boundary, or “high performance” without a workload and relay capacity.

Choose the path and audience before choosing the feature

A useful frp design starts with the service and its audience, not with the most advanced transport available.

For a public web preview, HTTP or HTTPS is usually the meaningful contract when callers need a domain, URL locations, header rewriting, or a web-facing authentication condition. The public server can route by host and path, and health checks can remove a backend that repeatedly fails the configured test. That is more expressive than a raw TCP port, but it also means the operator has accepted application-aware routing, domain conflicts, header policy, and a public web entry point. TLS and application authentication remain separate decisions.

For a service that speaks an arbitrary stream protocol, TCP is often clearer.