A powerful, extremely lightweight, encrypted port forwarder built on a reliable UDP transport.
Status: Stable
kcptun-libev is a TCP port forwarder that converts the transport to a UDP‑based protocol called KCP. KCP is more configurable and typically performs much better on lossy, lightly congested networks. This project can help you achieve higher throughput in such situations.
Example: wrap your service to use KCP instead of TCP:
client -> kcptun-libev client ->
lossy network (carried by KCP)
-> kcptun-libev server -> server
A common setup is to pair kcptun-libev with a proxy to speed up Internet access over lossy links:
network access -> proxy client -> kcptun-libev client ->
lossy network (carried by KCP)
-> kcptun-libev server -> proxy server -> stable network
Reliable UDP can also help connect to TCP services behind NAT; see Rendezvous Mode.
client -> NAT1 -> rendezvous server
server -> NAT2 -> rendezvous server
client -> NAT1 -> NAT2 -> server
Because KCP retransmits packets aggressively, we recommend enabling proper QoS at the NIC level when running on public networks.
Read more about KCP
- Secure: Proper integration with modern authenticated encryption.
- Responsive: No multiplexer; one TCP connection maps to one KCP connection with 0‑RTT opening.
- Precise: KCP flushes on demand; no artificial latency introduced.
- Simple: Does one thing well — acts as a Layer 4 forwarder.
- Modern: Full IPv6 support.
- Dynamic DNS aware: Dynamic IP addresses can be resolved automatically.
- NAT traversal: Servers behind certain types of NAT can connect directly via a well‑known rendezvous server.
- Configurable: When used with other encryption (e.g., udp2raw, WireGuard), built‑in encryption can be disabled or omitted at build time.
- Portable: Compliant with ISO C; supports both GNU/Linux and POSIX APIs.
There is a previous implementation of kcptun which is written in Go.
Compared to it, kcptun-libev is much more lightweight. The main executable is 100~200 KiB on most platforms* and it also has much lower CPU usage and memory footprint.
* Some required libraries are dynamically linked; see runtime dependencies below. Statically linked executables can be larger due to these libraries.
For your convenience, some statically-linked executables are also provided in the Releases section.
kcptun-libev can encrypt packets with a password or pre-shared key. Security and privacy can only be guaranteed if encryption is enabled. We use the authenticated encryption methods provided by libsodium.
In config file:
"method": "// name here"If encryption is disabled or not compiled in, there is no packet overhead. However, no authentication tag is added to protect the server from crafted packets. In this case, security relies on third‑party components. We recommend disabling encryption only when unsolicited packets cannot reach the service, or when the traffic is already protected (e.g., WireGuard).
In practice, we suggest using the --genpsk command‑line argument to generate a strong random pre‑shared key instead of a simple password.
| Encryption Method | Since | Form | Packet Overhead | Notes |
|---|---|---|---|---|
| xchacha20poly1305_ietf | v1.0 | AEAD | 40 bytes | recommended |
| xsalsa20poly1305 | v2.2 | AE | 40 bytes | |
| chacha20poly1305_ietf | v2.0 | AEAD | 28 bytes | |
| aes256gcm | v2.0 | AEAD | 28 bytes | requires specific hardware* |
* Specifically: x86 CPU with SSSE3, AES‑NI, and PCLMUL.
kcptun-libev ships with additional encryption methods to ensure that users have alternatives for specific reasons. Although the strength of each method is discussed, in most cases the recommended one just works.
Obfuscation is optional and helps evade inspection. This feature is available on Linux only.
In config file:
"obfs": "// name here"Currently one obfuscator is implemented: dpi/tcp-wnd. It behaves like a HTTP service and cannot be probed without the pre‑shared key.
With obfuscation enabled, kcptun-libev sends IP packets over raw sockets. Therefore, Linux capability CAP_NET_RAW is required. For example, the following commands may work on some Linux distributions:
# run as root and drop privileges after necessary setup
sudo ./kcptun-libev -u nobody:nogroup -c server.json
# or grant the capability and run as a normal user
sudo setcap cap_net_raw+ep kcptun-libev
./kcptun-libev -c server.jsonAll systems that support ISO C11 and POSIX.1‑2008.
| System | Tier | Notes |
|---|---|---|
| Ubuntu | developed | |
| OpenWrt | tested | |
| Other Linux / Android | supported | |
| macOS | supported | without obfuscator |
| Windows (MSYS2) | supported | without obfuscator |
For security reasons, kcptun-libev does NOT provide compatibility with any other KCP implementation.
We use semantic versioning.
Given a version number MAJOR.MINOR.PATCH:
-
As long as
MAJORremains unchanged, the versions should speak a compatible protocol. -
As long as
MAJOR.MINORremains unchanged, later versions should be compatible with working configuration files from previous versions.
| Name | Version | Required | Feature |
|---|---|---|---|
| json-c | >= 0.15 | yes | config file |
| libev | >= 4.31 | yes | |
| libsodium | >= 1.0.18 | no | encryption |
# Debian / Ubuntu
sudo apt install libjson-c-dev libev-dev libsodium-dev
# Alpine Linux
apk add json-c-dev libev-dev libsodium-devgit clone https://github.com/hexian000/kcptun-libev.git
mkdir -p kcptun-libev-build && cd kcptun-libev-build
cmake -DCMAKE_BUILD_TYPE="Release" \
../kcptun-libev
cmake --build . --parallelSee m.sh for cross‑compiling support.
Easiest option: Download a -static build from the Releases section — no additional runtime dependencies are needed.
# Debian / Ubuntu
sudo apt install libjson-c5 libev4 libsodium23
# Alpine Linux
apk add json-c libev libsodium
# OpenWRT
opkg install libjson-c5 libev libsodiumGenerate a random key for encryption:
./kcptun-libev --genpsk xchacha20poly1305_ietfCreate a server.json file and fill in the options:
{
"kcp_bind": "0.0.0.0:12345",
"connect": "127.0.0.1:1080",
"method": "xchacha20poly1305_ietf",
"psk": "// your key here"
}Start the server:
./kcptun-libev -c server.jsonCreate a client.json file and fill in the options:
{
"listen": "127.0.0.1:1080",
"kcp_connect": "203.0.113.1:12345",
"method": "xchacha20poly1305_ietf",
"psk": "// your key here"
}Start the client:
./kcptun-libev -c client.json127.0.0.1:1080 on the client is now forwarded to the server via kcptun-libev.
See server.json and client.json in the repository for more tunables.
Common fields in server.json/client.json:
- Client:
listendefines the local TCP address; traffic is sent tokcp_connect. - Server: receives on
kcp_bindand forwards connections toconnect. - Setting
passwordorpskis strongly recommended on public networks. loglevel: 0–7 map to Silence, Fatal, Error, Warning, Notice, Info, Debug, Verbose. The default is 4 (Notice). Higher levels can affect performance.
Rendezvous mode helps access servers behind NAT. The rendezvous server only bootstraps the connection; traffic flows directly between client and server.
Rendezvous mode requires UDP at the transport layer; it is incompatible with non‑UDP obfuscators.
The method is non-standard and may not work with all NAT implementations.
rendezvous_server.json: The rendezvous server should have an address which is reachable by both client and server.
{
"kcp_bind": "0.0.0.0:12345",
"method": "xchacha20poly1305_ietf",
"psk": "// your key here"
}server.json: The server may be behind one or more levels of NAT.
{
"connect": "127.0.0.1:25565",
"rendezvous_server": "203.0.113.1:12345",
"service_id": "myservice",
"method": "xchacha20poly1305_ietf",
"psk": "// your key here"
}client.json: The client may be behind one or more levels of NAT, which may or may not be the same ones as the server.
{
"listen": "127.0.0.1:25565",
"rendezvous_server": "203.0.113.1:12345",
"service_id": "myservice",
"method": "xchacha20poly1305_ietf",
"psk": "// your key here"
}rendezvous_server : server : client = 1 : m : m*n
All peers must be either all IPv4 or all IPv6.
kcptun-libev works out of the box. In most cases, the default options are recommended.
Some tunables are the same as KCP; read their docs for a full explanation. Hints:
kcp.sndwnd,kcp.rcvwnd:- Tune according to RTT.
- To estimate theoretical bandwidth, start an idle client with
loglevel >= 5and wait ~1 minute. - On memory‑constrained systems, reduce these values to save memory.
kcp.nodelay: Enabled by default. Note: not equivalent toTCP_NODELAY.kcp.interval:- Because KCP runs differently here, the recommended value is higher than in previous implementations and saves CPU.
- Not intended for traffic shaping. On Linux, see sqm-scripts and CAKE.
kcp.resend: Disabled by default.kcp.nc: Enabled by default.kcp.mtu: Specifies the final IP packet size, including all overhead.
kcptun-libev–specific options:
kcp.flush: 0 = periodic only; 1 = flush after sending; 2 = also flush ACKs (for benchmarking).tcp.sndbuf,tcp.rcvbuf,udp.sndbuf,udp.rcvbuf: Socket buffer sizes; see your OS manual.- Defaults usually work.
- Larger UDP buffers (e.g., 1048576) can help; however, overly large receive buffers may be counterproductive here.
- Avoid too‑small buffers to prevent performance degradation.
user: switch to this user to drop privileges, e.g.,"user": "nobody:"means the user named "nobody" and that user's login group
There is a built‑in HTTP server for monitoring service status.
Add this line to your config file:
"http_listen": "127.0.1.1:8081"Then run the commands below from shell:
watch curl -sX POST http://127.0.1.1:8081/statsThe URI "/healthy" always responds with HTTP 200; use it for health checks.
Thanks to: