A powerful and extremely lightweight encrypted port forwarder based on reliable UDP protocol.
Status: Stable
kcptun-libev is a TCP port forwarder which converts the actual transferring protocol into a UDP based one, called KCP. KCP is more configurable and usually has a much better performance in a lossy but not really congested network. This project can help you to get better bandwidth in such situation.
For example, wrap your server to use KCP instead of TCP:
client -> kcptun-libev client ->
lossy network (carried by KCP)
-> kcptun-libev server -> server
Or typically, the people who using a lossy network may setup kcptun-libev with a proxy server. To get the internet access speeded up.
network access -> proxy client -> kcptun-libev client ->
lossy network (carried by KCP)
-> kcptun-libev server -> proxy server -> stable network
Reliable UDP can also help users connect to TCP services behind NAT, see rendezvous mode.
client -> NAT1 -> rendezvous server
server -> NAT2 -> rendezvous server
client -> NAT1 -> NAT2 -> server
Since KCP retransmits packets more aggressively. It is recommended to enable proper QoS at the NIC level when running on a public network.
Read more about KCP
There is a previous implementation of kcptun which is written in Go.
Compared to that, kcptun-libev should be much more lightweight. The main executable is around 100~200KiB on most platforms* and it also have a much lower cpu/mem footprint.
* Some required libraries are dynamically linked, see runtime dependencies below. Statically linked executable 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 the encryption is not enabled or not even compiled, no packet overhead is consumed. However, no authentication tag is added to protect the server from well-crafted packets by an attacker. In this case, security relies on third-party components. We recommend that users only disable encryption when unexpected packets cannot be received. For example: the traffic is already protected by Wireguard etc.
In practice, we suggest user to use --genpsk
command-line argument to generate a strong random pre-shared key instead of using 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 | limited hardware* |
* Specifically: x86 CPU with SSSE3, aesni 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.
The obfuscator is an optional tool to fool eavesdroppers. This feature is only available on Linux.
In config file:
"obfs": "// name here"
Currently only one obfuscator implemented: dpi/tcp-wnd
. It behaves like a HTTP service and cannot be probed without knowing the pre-shared key.
With obfuscator enabled, kcptun-libev will directly send IP packets over raw sockets. Therefore, Linux capability CAP_NET_RAW is required. For example, the following command may works 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.json
Theoretically all 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 to any other KCP implementations.
We use semantic versioning.
Given a version number MAJOR.MINOR.PATCH
:
As long as MAJOR
remains unchanged, the versions should speak a compatible protocol.
As long as MAJOR.MINOR
remains unchanged, later versions should be compatible with working configuration files from previous versions.
Name | Version | Required | Feature |
---|---|---|---|
libev | >= 4.31 | yes | |
libsodium | >= 1.0.18 | no | encryption |
# Debian & Ubuntu
sudo apt install libev-dev libsodium-dev
# Alpine Linux
apk add libev-dev libsodium-dev
git 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 . --parallel
See m.sh for more information about cross compiling support.
Simple solution: Download a -static
build in the Releases section so no dependencies need to be installed.
# Debian & Ubuntu
sudo apt install libev4 libsodium23
# Alpine Linux
apk add libev libsodium
# OpenWRT
opkg install libev libsodium
Generate a random key for encryption:
./kcptun-libev --genpsk xchacha20poly1305_ietf
Create 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.json
Create 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.json
Now 127.0.0.1:1080 on client is forwarded to server by kcptun-libev.
See server.json/client.json in the source repo for more tunables.
Let's explain some common fields in server.json/client.json:
Rendezvous mode may be useful for accessing servers behind NAT. The rendezvous server only helps establish the connection, the traffic goes directly between client and server.
Rendezvous mode requires UDP in transport layer, i.e. 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",
"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",
"method": "xchacha20poly1305_ietf",
"psk": "// your key here"
}
rendezvous_server : server : client = 1 : 1 : n
Peers should be 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 full explaination. Here are some hints:
TCP_NODELAY
.Again, there is some kcptun-libev specific options:
"user": "nobody:"
means the user named "nobody" and that user's login groupThere is a builtin 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/stats
The URI "/healthy" always responds with HTTP 200, feel free to use it for healthy checks.
Thanks to: