discover · compare · collections · requirements · contribute · feed · watching · stats · help with your tokens
heiher/hev-socks5-tunnel · source
Snapshot 0 · 2026-11-04T12:47:25Z · C · MIT
Content fingerprint
41bfd78c6972af32dd3a067175729e1e49953940b9b9ead003b13671c753039fGitHub description at capture
A lightweight, fast and reliable tun2socks
README at capture
# HevSocks5Tunnel
[](https://github.com/heiher/hev-socks5-tunnel)
A simple, lightweight tunnel over Socks5 proxy (tun2socks).
## Features
* IPv4/IPv6. (dual stack)
* Redirect TCP connections.
* Redirect UDP packets. (Fullcone NAT, UDP-in-UDP and UDP-in-TCP [^1])
* Optional local ICMP Echo (ping) replies.
* Linux/Android/FreeBSD/macOS/iOS/Windows.
## Benchmarks
See [here](https://github.com/heiher/hev-socks5-tunnel/wiki/Benchmarks) for more details.
### Speed


### CPU usage


### Memory usage


## How to Build
### Unix
```bash
git clone --recursive https://github.com/heiher/hev-socks5-tunnel
cd hev-socks5-tunnel
make
```
### Android
```bash
mkdir hev-socks5-tunnel
cd hev-socks5-tunnel
git clone --recursive https://github.com/heiher/hev-socks5-tunnel jni
ndk-build
```
### iOS and macOS
```bash
git clone --recursive https://github.com/heiher/hev-socks5-tunnel
cd hev-socks5-tunnel
# will generate HevSocks5Tunnel.xcframework
./build-apple.sh
```
### Windows (MSVC + Clang)
The same `Makefile` builds with clang targeting MSVC. Open a Visual
Studio developer prompt (clang from the VS LLVM component or `PATH`), make
sure GNU make and a POSIX `sh.exe` (for example the one of Git for Windows,
`C:\Program Files\Git\usr\bin`) are on `PATH`, then:
```bat
git clone --recursive https://github.com/heiher/hev-socks5-tunnel
cd hev-socks5-tunnel
make
make ARCH=x86
make ARCH=arm64
make shared
```
`ARCH` is `x64` (default), `x86` or `arm64` and must match the developer
prompt architecture. The executable is `bin/hev-socks5-tunnel.exe`; the shared
library is `bin/hev-socks5-tunnel.dll` with the import library
`bin/hev-socks5-tunnel.dll.lib`, it embeds the third-parts. Run `make clean`
when switching between the executable and the shared library.
The [Wintun](https://www.wintun.net/) driver is loaded at runtime, put the
`wintun.dll` of the same architecture next to the executable and run it as
Administrator. On Windows there is no daemon mode (`pid-file` only writes
the process id), no `limit-nofile` and no `mark`. Stop the tunnel with Ctrl+C.
### Library
```bash
git clone --recursive https://github.com/heiher/hev-socks5-tunnel
cd hev-socks5-tunnel
# Static library
make static
# Shared library
make shared
```
## How to Use
### Config
```yaml
tunnel:
# Interface name
name: tun0
# Interface GUID (Windows)
# guid: 12345678-9abc-def0-1234-56789abcdef0
# Interface MTU
mtu: 8500
# Multi-queue
multi-queue: false
# IPv4 address
ipv4: 198.18.0.1
# IPv6 address
ipv6: 'fc00::1'
# ICMP Echo mode (off|reply)
icmp: 'off'
# Offloads (Linux), each one is used only if the kernel supports it
# offload:
# TCP segmentation offload
# tso: true
# UDP segmentation offload
# uso: true
# Send TCP segments larger than the MTU without TSO, only for local
# delivery, disable it if the traffic is forwarded to other interfaces
# jumbo: true
# Post up script
# post-up-script: up.sh
# Pre down script
# pre-down-script: down.sh
socks5:
# Socks5 server port
port: 1080
# Socks5 server address (ipv4/ipv6)
address: 127.0.0.1
# Socks5 UDP relay mode (tcp|udp)
udp: 'udp'
# Override the UDP address provided by the Socks5 server (ipv4/ipv6)
# udp-address: ''
# Socks5 handshake using pipeline mode
# pipeline: false
# Socks5 server username
# username: 'username'
# Socks5 server password
# password: 'password'
# Socket mark
# mark: 0
# TCP fastopen
# tcp-fastopen: false
#mapdns:
# Mapped DNS address
# address: 198.18.0.2
# Mapped DNS port
# port: 53
# Mapped IP network base
# network: 100.64.0.0
# Mapped IP network mask
# netmask: 255.192.0.0
# Mapped DNS cache size
# cache-size: 10000
#misc:
# task stack size (bytes)
# task-stack-size: 86016
# wintun ring buffer capacity (bytes, windows only, power of two,
# range: 131072 - 67108864)
# wintun-ring-capacity: 524288
# tcp buffer size (bytes)
# tcp-buffer-size: 65536
# udp socket recv buffer (SO_RCVBUF) size (bytes)
# udp-recv-buffer-size: 524288
# number of udp buffers in splice, 1500 bytes per buffer.
# udp-copy-buffer-nums: 10
# maximum session count (0: unlimited)
# max-session-count: 0
# connect timeout (ms)
# connect-timeout: 10000
# TCP read-write timeout (ms)
# tcp-read-write-timeout: 300000
# UDP read-write timeout (ms)
# udp-read-write-timeout: 60000
# null, stdout, stderr or file-path
# log-file: null
# debug, info, warn or error
# log-level: warn
# If present, run as a daemon with this pid file
# pid-file: /run/hev-socks5-tunnel.pid
# If present, set rlimit nofile; else use default value
# limit-nofile: 65535
```
### Run
#### Linux
```bash
# Set socks5.mark = 438
bin/hev-socks5-tunnel conf/main.yml
# Disable reverse path filter
sudo sysctl -w net.ipv4.conf.all.rp_filter=0
sudo sysctl -w net.ipv4.conf.tun0.rp_filter=0
# Bypass upstream socks5 server
sudo ip rule add fwmark 438 lookup main pref 10
sudo ip -6 rule add fwmark 438 lookup main pref 10
# Route others
sudo ip route add default dev tun0 table 20
sudo ip rule add lookup 20 pref 20
sudo ip -6 route add default dev tun0 table 20
sudo ip -6 rule add lookup 20 pref 20
```
#### FreeBSD/macOS
```zsh
# Bypass upstream socks5 server
# 10.0.0.1: socks5 server
# 10.0.2.2: default gateway
sudo route add -net 10.0.0.1/32 10.0.2.2
# Route others
sudo route change -inet default -interface tun0
sudo route change -inet6 default -interface tun0
```
#### Windows
```zsh
# Bypass upstream socks5 server
# 10.0.0.1: socks5 server
# 10.0.2.2: default gateway
route add 10.0.0.1/32 10.0.2.2
# Route others
route change 0.0.0.0/0 0.0.0.0 if tun-index
route change ::/0 :: if tun-index
```
#### OpenWrt 24.10+
Repo: https://github.com/openwrt/packages/tree/master/net/hev-socks5-tunnel
```sh
# Install package
opkg install hev-socks5-tunnel
# Edit /etc/config/hev-socks5-tunnel
# Restart service
/etc/init.d/hev-socks5-tunnel restart
```
#### Low memory usage
On low-memory systems like iOS, reducing the size of the TCP buffer and
task stack, as well as limiting the maximum session count, can help prevent
out-of-memory issues.
```yaml
misc:
# task stack size (bytes)
task-stack-size: 24576 # 20480 + tcp-buffer-size
# tcp buffer size (bytes)
tcp-buffer-size: 4096
# maximum session count
max-session-count: 1200
```
#### Docker Compose
```yaml
version: "3.9"
services:
client:
image: alpine:latest # just for network testing
tty: true # you can test network in terminal
depends_on:
tun:
condition: service_healthy
network_mode: "service:tun"
tun:
image: ghcr.io/heiher/hev-socks5-tunnel:latest # `latest` for the latest published version; `nightly` for the latest source build; `vX.Y.Z` for the specific version
cap_add:
- NET_ADMIN # needed
devices:
- /dev/net/tun:/dev/net/tun # needed
environment:
TUN: tun0 # optional, tun interface name, default `tun0`
MTU: 8500 # optional, MTU is MTU, default `8500`
IPV4: 198.18.0.1 # optional, tun interface ip, default `198.18.0.1`
IPV6: fc00::1 # optional, tun interface ip
ICMP: off # optional, ICMP Echo mode, default `off`, other option `reply`
TABLE: 20 # optional, ip route table id, default `20`
MARK: 438 # optional, ip route rule mark, dec or hex format, default `438`
SOCKS5_ADDR: a.b.c.d # socks5 proxy server address
SOCKS5_PORT: 1080 # socks5 proxy server port
SOCKS5_USERNAME: user # optional, socks5 proxy username, only set when need to auth
SOCKS5_PASSWORD: pass # optional, socks5 proxy password, only set when need to auth
SOCKS5_UDP_MODE: udp # optional, UDP relay mode, default `udp`, other option `tcp`
SOCKS5_UDP_ADDR: a.b.c.d # optional, override the UDP address provided by the Socks5 server
CONFIG_ROUTES: 1 # optional, set 0 to ignore TABLE, IPV4_INCLUDED_ROUTES and IPV4_EXCLUDED_ROUTES, with MARK defaults to 0
IPV4_INCLUDED_ROUTES: 0.0.0.0/0 # optional, demo means proxy all traffic. for multiple network segments, join with `,` or `\n`
IPV4_EXCLUDED_ROUTES: a.b.c.d # optional, demo means exclude traffic from the proxy itself. for multiple network segments, join with `,` or `\n`
DNS_CACHE: 1 # optional, enable the lightweight caching resolver (dnsmasq) for use with mapdns disabled, default `0`
DNS_CACHE_SERVERS: 8.8.8.8,1.1.1.1 # optional, upstream resolvers of the cache, they are queried via the tun device, default `8.8.8.8,1.1.1.1`
DNS_CACHE_SIZE: 10000 # optional, number of cached DNS records, default `10000`
LOG_LEVEL: warn # optional, default `warn`, other option `debug`/`info`/`error`
dns:
- 127.0.0.1 # point clients at the caching resolver when DNS_CACHE=1, or a remote resolver like 8.8.8.8 otherwise
```
#### DNS caching
The tunnel has no built-in DNS cache when mapdns is disabled, but the Docker
image ships an optional lightweight caching resolver (dnsmasq). Enable it with
`DNS_CACHE=1`, no entrypoint override needed. It listens on `127.0.0.1` and the
tun interface addresses, so clients sharing the network namespace
(`network_mode: "service:tun"`) use it with `dns: 127.0.0.1` (or the tun IPv4,
e.g. `dns: 198.18.0.1`). Upstream servers (`DNS_CACHE_SERVERS`) are queried
through the tun device, i.e. resolved remotely via the Socks5 server, and
successful answers are cached locally (`DNS_CACHE_SIZE` records).
You can also set the route rules with multiple network segments like:
```yaml
environment:
IPV4_INCLUDED_ROUTES: 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
IPV4_EXCLUDED_ROUTES: |-
a.b.c.d/24
a.b.c.f/24
```
## API
### C
```c
/**
* hev_socks5_tunnel_main:
* @config_path: config file path
* @tun_fd: tunnel file descriptor
*
* Start and run the socks5 tunnel, this function will blocks until the
* hev_socks5_tunnel_quit is called or an error occurs.
*
* Alias of hev_socks5_tunnel_main_from_file
*
* Returns: returns zero on successful, otherwise returns -1.
*
* Since: 2.4.6
*/
int hev_socks5_tunnel_main (const char *config_path, int tun_fd);
/**
* hev_socks5_tunnel_main_from_file:
* @config_path: config file path
* @tun_fd: tunnel file descriptor
*
* Start and run the socks5 tunnel, this function will blocks until the
* hev_socks5_tunnel_quit is called or an error occurs.
*
* Returns: returns zero on successful, otherwise returns -1.
*
* Since: 2.6.7
*/
int hev_socks5_tunnel_main_from_file (const char *config_path, int tun_fd);
/**
* hev_socks5_tunnel_main_from_str:
* @config_str: string config
* @config_len: the byte length of string config
* @tun_fd: tunnel file descriptor
*
* Start and run the socks5 tunnel, this function will blocks until the
* hev_socks5_tunnel_quit is called or an error occurs.
*
* Returns: returns zero on successful, otherwise returns -1.
*
* Since: 2.6.7
*/
int hev_socks5_tunnel_main_from_str (const unsigned char *config_str,
unsigned int config_len, int tun_fd);
/**
* hev_socks5_tunnel_quit:
*
* Stop the socks5 tunnel.
*
* Since: 2.4.6
*/
void hev_socks5_tunnel_quit (void);
/**
* hev_socks5_tunnel_stats:
* @tx_packets (out): transmitted packets
* @tx_bytes (out): transmitted bytes
* @rx_packets (out): received packets
* @rx_bytes (out): received bytes
*
* Retrieve tunnel interface traffic statistics.
*
* Since: 2.6.5
*/
void hev_socks5_tunnel_stats (size_t *tx_packets, size_t *tx_bytes,
size_t *rx_packets, size_t *rx_bytes);
```
### Java
```java
public class TProxyService {
private static native boolean TProxyStartService(String config_path, int fd);
private static native boolean TProxyStopService();
private static native boolean TProxyIsRunning();
private static native long[] TProxyGetStats();
static {
System.loadLibrary("hev-socks5-tunnel");
}
}
```
### Kotlin
```kt
object TProxyService {
private external fun TProxyStartService(config_path: String, fd: Int): Boolean
private external fun TProxyStopService(): Boolean
private external fun TProxyIsRunning(): Boolean
private external fun TProxyGetStats(): LongArray
init {
System.loadLibrary("hev-socks5-tunnel")
}
}
```
Allow overriding the package and class names in `Application.mk`[^2].
```makefile
APP_CFLAGS := -DPKGNAME=hev/sockstun -DCLSNAME=TProxyService
```
### Prebuilt Android AAR
The Android CI job also produces an AAR (`hev-socks5-tunnel.aar`, containing all four ABIs)
built with the default JNI contract — no `PKGNAME`/`CLSNAME` overrides — so its natives
register to `hev.htproxy.TProxyService`. The AAR is self-contained: the binding class below
is bundled in it (`classes.jar`, plus a `proguard.txt` that keeps it), so it is called
directly and no shim class has to be added to the app:
```java
package hev.htproxy;
public final class TProxyService {
public static native boolean TProxyStartService(String config_path, int fd);
public static native boolean TProxyStopService();
public static native boolean TProxyIsRunning();
public static native long[] TProxyGetStats();
static {
System.loadLibrary("hev-socks5-tunnel");
}
}
```
Then call these methods from your own code; no per-package rebuild is required. The AAR is
also attached to tagged releases. Consumers that need a custom package or class name can
still override `PKGNAME`/`CLSNAME` in `Application.mk` as shown above and build themselves.
## Use Cases
### Android VPN
* [SocksTun](https://github.com/heiher/sockstun)
* [Orbot](https://github.com/guardianproject/orbot-android)
* [EasyssTun](https://github.com/nange/EasyssTun)
### iOS
* [Tun2SocksKit](https://github.com/EbrahimTahernejad/Tun2SocksKit)
## Contributors
* **acidroper** - https://github.com/acidroper
* **arror** - https://github.com/arror
* **bazuchan** - https://github.com/bazuchan
* **bitmold** - https://github.com/bitmold
* **codewithtamim** - https://github.com/codewithtamim
* **daemooon** - https://github.com/daemooon
* **dovecoteescapee** - https://github.com/dovecoteescapee
* **ebrahimtahernejad** - https://github.com/ebrahimtahernejad
* **egavr** - https://github.com/egavr
* **fwx** - https://github.com/fwx
* **heiby** - https://github.com/heiby
* **hev** - https://hev.cc
* **ihipop** - https://ihipop.com
* **katana** - https://github.com/officialkatana
* **mmjvox** - https://github.com/mmjvox
* **nange** - https://github.com/nange
* **plangto** - https://github.com/plangto
* **popsiclelmlm** - https://github.com/popsiclelmlm
* **pronebird** - https://github.com/pronebird
* **saeeddev94** - https://github.com/saeeddev94
* **simplerick-simplefun** - https://github.com/simplerick-simplefun
* **sskaje** - https://github.com/sskaje
* **wankkoree** - https://github.com/wankkoree
* **xiguagua** - https://github.com/xiguagua
* **xz-dev** - https://github.com/xz-dev
* **yiguodev** - https://github.com/yiguodev
* **yujinpan** - https://github.com/yujinpan
* **zheshinicheng** - https://github.com/zheshinicheng
## License
MIT
[^1]: See [protocol specification](https://github.com/heiher/hev-socks5-core/tree/main?tab=readme-ov-file#udp-in-tcp). The [hev-socks5-server](https://github.com/heiher/hev-socks5-server) supports UDP relay over TCP.
[^2]: See [Application.mk](https://github.com/heiher/sockstun/blob/12830d444fe60ad1c5d68ea6e60ec141cd2c6d97/app/src/main/jni/Application.mk#L19)