The FRP transport
How the embedded FRP client carries traffic, and why tunnelctl forks frp.
Under the hood, tunnelctl moves traffic with FRP (fast
reverse proxy). FRP carries all three tunnel protocols — HTTP/HTTPS via its http/https
proxies (routed by hostname) and raw TCP/UDP via its tcp/udp proxies (a dedicated edge
port). What's unusual is that the FRP client is embedded in the CLI — there's no
separate frpc process to install or configure, and no .toml file is written to disk.
The CLI builds the client config in memory and runs the FRP service in-process.
The path of a request
wss on port 443.<slug>.intunnel.eu, or a TCP/UDP proxy bound to a remote port (tcp.intunnel.eu:<port>).host:port.Tuning
A couple of up http flags map onto FRP behaviour (HTTP tunnels only):
--pool-countpre-allocates work connections so the first requests don't pay a connection-setup cost.--host-header-rewriterewrites the outgoingHostheader, which matters for local apps that route by virtual host.
Why a fork
Upstream frpc exposes no signal for control-channel connect/disconnect events.
tunnelctl maintains a small fork that adds a login-state callback, so the per-tunnel
daemon can detect when the control channel drops and transition to Reconnecting without
polling. The fork tracks upstream closely and is published under the
git.nubeo.eu/microservices/frp module path.
Daemon state from FRP
The connect/disconnect callback is what drives the Connected ↔ Reconnecting states
you see in tunnelctl status.