xfrpc is an FRP client small enough to live on an OpenWrt router
xfrpc 是一个轻量级的 FRP 客户端,完美兼容 frps,采用 C 语言实现,专为 OpenWRT 和物联网等资源受限系统优化设计。它针对 ROM 和 RAM 空间有限的设备,提供高效的内网穿透解决方案。xfrpc 集成了xDPI(深度包检测)功能,增强了安全性,有效防止内网穿透中因恶意嗅探导致的安全威胁,确保数据传输和网络访问的可靠保护。购买下面的链接中的服务支持我的开源
At a glance
- What is it?
- xfrpc is a C implementation of the frp client, written for devices with limited ROM and RAM such as OpenWrt routers and other embedded systems, and it speaks the same protocol as the upstream client. The repository also publishes an honest feature table, which is the most useful document in it: kcp, websocket and wss transports, VirtualNet and the official plugins are not implemented, and SUDP is configuration only.
- Who is it for?
- Adopt xfrpc when you are putting a reverse tunnel on a router or an embedded device where the official frpc binary does not fit, and when the features you need are on the supported list. Do not adopt it if your setup needs kcp, websocket or wss transports, VirtualNet, the official plugins, or full SUDP, because the project publishes exactly what is missing.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 45 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why a second frp client exists at all
xfrpc is an implementation of the frp client written in C for OpenWrt and IoT systems, and the README gives the motivation plainly. The main motivation is to provide a lightweight solution for devices with limited resources, such as OpenWrt devices with limited ROM and RAM space, and the project aims to provide an frp client that uses less space and memory than other available options.
That is a narrow goal and a legitimate one. A router that has to run a reverse tunnel is already running a firewall, a DNS forwarder and whatever else the firmware includes, and the frp client from the upstream project is written in Go and ships as a large static binary. On a device with a few megabytes of free space, that binary is often the reason a reverse tunnel is not an option at all.
The client is compatible with frps, the server side of the FRP system, so the server does not change. A device with xfrpc talks to the same frps that every other frp client talks to, which means a mixed fleet, with xfrpc on the embedded boxes and the standard client elsewhere, is not a special case.
The development status is stated without hedging: xfrpc is partially compatible with the latest frp release, and it targets full compatibility. The repository description also mentions an xDPI, deep packet inspection, integration intended to make sniffing harder, and a sponsorship link for the author's services, which tells you this is a one person project with commercial support behind it.
The feature table is the honest part of the README
Rather than claiming parity, the README publishes a table comparing xfrpc against the official frpc from frp v0.71, feature by feature, and the missing rows are the first thing to read.
Supported in both, and therefore safe to rely on: tcp, tcpmux, http, https, custom_domains, subdomain, udp, xtcp for point to peer, stcp, use_encryption, use_compression and the quic transport. The xfrpc build also lists socks5 as a proxy type, where the official client offers it as a plugin only.
Both support the newer wire protocol, with v1 as the default, and v2 with JSON messages and an AES-256-GCM control AEAD.
The gaps are the interesting part. kcp, websocket and wss transports are not supported. VirtualNet is not supported. The official plugins, listed as http_proxy, static_file and tls2raw among others, are not supported. SUDP is partial, and the parenthetical says config only, so the option exists in the configuration parser without a working implementation behind it.
This is a better advertisement than a claim of full compatibility would be, because a user can check their own frp configuration against the table and know in a minute whether this is usable. The one row that needs care is SUDP, where a configuration that parses is not the same as a configuration that works, and a user who only reads the parser would be misled.
Building with CMake and choosing a TLS backend
The build is a small CMake project with three dependencies: libevent, json-c, and a TLS library, either wolfSSL or OpenSSL.
On Ubuntu and Debian the dependencies come from the distribution:
sudo apt-get update
sudo apt-get install -y libjson-c-dev libevent-dev libssl-devAnd the build itself is the usual clone and configure sequence:
git clone https://github.com/liudf0716/xfrpc.git
cd xfrpc
mkdir build && cd build
cmake ..
makeThe build options are the interesting part, because they reflect the target devices. -DUSE_WOLFSSL is on by default and selects wolfSSL as the TLS backend, falling back to OpenSSL if wolfSSL is not found. -DENABLE_QUIC is off by default and enables the QUIC transport through ngtcp2, which also requires nghttp3. -DDEBUG turns on a debug build with the address sanitizer.
The wolfSSL default is not arbitrary. The README notes that wolfSSL is smaller, faster, and has native QUIC support compared to OpenSSL, and that wolfSSL is the standard TLS library on OpenWrt, where it is recommended and no additional TLS package is needed for basic functionality. On a router, the TLS library is often the largest thing you install, so the default follows the platform.
To build against OpenSSL instead, the flag is passed at configure time:
cmake .. -DUSE_WOLFSSL=OFF
makeAnd for the QUIC transport:
cmake .. -DENABLE_QUIC=ON
makeQUIC and tcpmux, the two transports worth knowing
The configuration files in the README show the shape of a client, and the two extra transports are where the interesting options live.
A minimal TCP tunnel is small. The client points at the server, and a named proxy maps a remote port to a local service:
[common]
server_addr = your_server_ip
server_port = 7000
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 6128The QUIC transport is selected with protocol = quic and a quic_bind_port, and the server side needs the matching quicBindPort in its frps.ini. The README explains the appeal: QUIC is UDP based, and it provides faster connection establishment with 0-RTT, built-in encryption with TLS 1.3, and better performance on lossy networks. That last point is the one that matters on a mobile or rural link. The cost is a build dependency, since QUIC support requires building with -DENABLE_QUIC=ON and the ngtcp2 and nghttp3 libraries installed.
Tcpmux is the other transport worth understanding, and it is about efficiency rather than speed. The README describes TCPMux proxy as using HTTP CONNECT multiplexing on frps's tcpmuxHTTPConnectPort to route connections by domain, with multiple tcpmux proxies sharing a single connection pool, which makes it more resource-efficient than individual tcp proxies. On a device where every open connection and every thread has a cost, sharing one pool matters.
The configuration for it sets tcp_mux = 1 in the common section, and each proxy uses type = tcpmux with a multiplexer of httpconnect, plus custom_domains or subdomain to say where the traffic goes.
Getting it onto a router and onto a tiny filesystem
Two delivery paths matter for the target audience, and both are documented with exact commands.
The first is OpenWrt itself. xfrpc has been included in the OpenWrt community repository since version 1.04.515, which means it can be pulled into a custom firmware image without hunting for packages. The route is make menuconfig, then navigating to Network, then Web Servers/Proxies, then xfrpc, which includes it in the image that gets built. The README recommends using the latest version of xfrpc, because it may have bug fixes and new features.
The second is a static binary built in an Alpine container, for the case where you are not building an OpenWrt image but need a small executable to copy onto a device:
$ DOCKER_BUILDKIT=1 docker build --output out . -f docker/Dockerfile
$ ls out/
xfrpcThat produces a single xfrpc executable in the out directory, which is the whole point of the project: one file, small, that runs on a device with little memory.
There is a third path for developers rather than users. When a segment fault shows up, the README asks you to build with a debug configuration so the address sanitizer can detect the memory leak:
cmake -DCMAKE_BUILD_TYPE=Debug ..The README is candid that the sanitizer is not yet part of the CI flow and will be added in future, which tells you the test infrastructure is thinner than the feature set.
The server side, the versions and the remaining gaps
Using xfrpc still needs an frps server, and the README is explicit that you should get one from the frp releases page before starting. The server is the standard one, run with its own configuration file:
./frps -c frps.iniThe sample frps.ini in the example directory binds the server to port 7000, which is also the default the client configurations point at.
The release history is unusual and worth understanding before you pin a version. The tags are 5.09.982 from 2026-09-08, 5.06.909 from 2026-06-01 and 3.05.661 from 2024-05-26. The numbers are not semantic versions in the usual sense; they look like a date and a build counter, which is what you would expect from a project whose releases are cut by a script and whose branches are named after build numbers. The OpenWrt package version 1.04.515 in the community repository is the same idea.
That scheme has a practical consequence. There is no way to read a version and know whether a feature is present, so a decision to depend on a specific feature means reading the changelog for that build rather than assuming from the number. The repository has a CHANGELOG-like history in the tags, and the continuous integration configuration is spread across azure-pipelines.yml, .travis.yml and a .circleci directory, which is a sign of a project that has been kept building on several services over time.
The licence is GPL-3.0, the language is C, and the last push to the master branch was on 2026-09-08, the same day as the newest release tag.
Editorial conclusion
Adopt xfrpc when you are putting a reverse tunnel on a router or an embedded device where the official frpc binary does not fit, and when the features you need are on the supported list. Do not adopt it if your setup needs kcp, websocket or wss transports, VirtualNet, the official plugins, or full SUDP, because the project publishes exactly what is missing. Before you build, read the feature table against the frp version you deploy, decide between wolfSSL and OpenSSL since the default matters on a device with a small TLS stack, and test the QUIC path only if you build with ngtcp2 and nghttp3 present, because the QUIC option is off by default.
Frequently asked questions
What does xfrpc need to build?
libevent, json-c and a TLS library, either wolfSSL or OpenSSL. On Ubuntu and Debian the README installs libjson-c-dev, libevent-dev and libssl-dev, then configures with cmake .. and builds with make, with -DUSE_WOLFSSL, -DENABLE_QUIC and -DDEBUG as the documented options.
Which frp features does xfrpc not support?
The feature table in the README lists kcp, websocket and wss transports, VirtualNet and the official plugins such as http_proxy, static_file and tls2raw as unsupported, and SUDP as partial, with the parenthetical config only. The table is drawn against frp v0.71.
How do I use the QUIC transport with xfrpc?
Build with -DENABLE_QUIC=ON, which needs the ngtcp2 and nghttp3 libraries, set protocol = quic with a quic_bind_port in the client configuration, and add the matching quicBindPort to the frps configuration. The README points at 0-RTT connection setup, TLS 1.3 and better behaviour on lossy networks as the reasons to use it.
How do I install xfrpc on an OpenWrt device?
xfrpc has been part of the OpenWrt community repository since version 1.04.515, so it can be selected with make menuconfig under Network, then Web Servers/Proxies, and included in a custom firmware image. A static binary for other targets can be built with the Alpine container command in the README.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/liudf0716-xfrpc)Was this useful?