Baike.dev
All toolsOnline toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
T

tun2proxy

> 编程语言
Open source

Tunnel (TUN) interface for SOCKS and HTTP proxies

1.4K stars0 likes2 views
WebsiteGitHub

About

Tunnel (TUN) interface for SOCKS and HTTP proxies

tun2proxy

A tunnel interface for HTTP and SOCKS proxies on Linux, Android, macOS, iOS and Windows.

Additional information can be found in the wiki

Features

  • HTTP proxy support (unauthenticated, basic and digest auth)
  • SOCKS4 and SOCKS5 support (unauthenticated, username/password auth)
  • SOCKS4a and SOCKS5h support (through the virtual DNS feature)
  • Minimal configuration setup for routing all traffic
  • IPv4 and IPv6 support
  • GFW evasion mechanism for certain use cases (see issue #35)
  • SOCKS5 UDP support
  • Native support for proxying DNS over TCP
  • UdpGW (UDP gateway) support for UDP over TCP, see the wiki for more information
  • Session info embedding for per-app routing on Android (see below)

Session Info for Per-App Routing (Android)

To enable per-app traffic routing on Android 10+, you can embed session information (protocol, source IP, source port) in the SOCKS5 username field. This allows your proxy server to call getConnectionOwnerUid() to identify which app initiated the connection.

To enable this feature, append +info to your username:

bash
# Without session info (normal mode)
tun2proxy --proxy "socks5://user:[email protected]:1080"

# With session info
tun2proxy --proxy "socks5://user+info:[email protected]:1080"

The proxy server will receive the username in the format:

original_username|protocol|src_ip|src_port

| is a literal field delimiter in this format. The client does not escape | characters in original_username, so when using +info, the original username must not contain | (including a | introduced via percent-encoding in the proxy URL), otherwise the value becomes ambiguous for server-side parsers.

For example, user+info becomes user|tcp|10.0.0.5|54321.

Servers should parse this as exactly four |-separated fields and reject usernames that do not meet that requirement.

Build

Clone the repository and cd into the project folder. Then run the following:

cargo build --release

Building Framework for Apple Devices

To build an XCFramework for macOS and iOS, run the following:

./build-apple.sh

Installation

Install from binary

Download the binary from releases and put it in your PATH.

Authenticity Verification

Since v0.2.23 build provenance attestations are supported. These allow you to ensure that the builds have been generated from the code on GitHub through the GitHub CI/CD pipeline. To verify the authenticity of the build files, you can use the GitHub CLI:

bash
gh attestation verify <*.zip file> --owner tun2proxy

Install from source

If you have rust toolchain installed, this should work:

bash
cargo install tun2proxy

Note: In Windows, you need to copy wintun DLL to the same directory as the binary. It's %USERPROFILE%\.cargo\bin by default.

Setup

Automated Setup

Using --setup, you can have tun2proxy configure your system to automatically route all traffic through the specified proxy. This requires running the tool as root and will roughly perform the steps outlined in the section describing the manual setup, except that a bind mount is used to overlay the /etc/resolv.conf file.

You would then run the tool as follows:

bash
sudo ./target/release/tun2proxy-bin --setup --proxy "socks5://1.2.3.4:1080"

Apart from SOCKS5, SOCKS4 and HTTP are supported.

Note that if your proxy is a non-global IP address (e.g. because the proxy is provided by some tunneling tool running locally), you will additionally need to provide the public IP address of the server through which the traffic is actually tunneled. In such a case, the tool will tell you to specify the address through --bypass <IP/CIDR> if you wish to make use of the automated setup feature.

Manual Setup

A standard setup, which would route all traffic from your system through the tunnel interface, could look as follows:

…

This tool implements a virtual DNS feature that is used by switch --dns virtual. When a DNS packet to port 53 is detected, an IP address from 198.18.0.0/15 is chosen and mapped to the query name. Connections destined for an IP address from that range will supply the proxy with the mapped query name instead of the IP address. Since many proxies do not support UDP, this enables an out-of-the-box experience in most cases, without relying on third-party resolvers or applications. Depending on your use case, you may want to disable this feature using --dns direct. In that case, you might need an additional tool like dnsproxy that is configured to listen on a local UDP port and communicates with a third-party upstream DNS server via TCP.

When you terminate this program and want to eliminate the impact caused by the above several commands, you can execute the following command. The routes will be automatically deleted with the tunnel device.

bash
sudo ip link del tun0

CLI

…

Currently, tun2proxy supports HTTP, SOCKS4/SOCKS4a and SOCKS5. A proxy is supplied to the --proxy argument in the URL format. For example, an HTTP proxy at 1.2.3.4:3128 with a username of john.doe and a password of secret is supplied as --proxy http://john.doe:[email protected]:3128. This works analogously to curl's --proxy argument.

Container Support

Docker

Tun2proxy can serve as a proxy for other Docker containers. To make use of that feature, first build the image:

bash
docker buildx build -t tun2proxy .

This will build an image containing a statically linked tun2proxy binary (based on musl) without OS.

Alternatively, you can build images based on Ubuntu or Alpine as follows:

bash
docker buildx build -t tun2proxy --target tun2proxy-ubuntu .
docker buildx build -t tun2proxy --target tun2proxy-alpine .

Next, start a container from the tun2proxy image:

bash
docker run -d \
	-v /dev/net/tun:/dev/net/tun \
	--sysctl net.ipv6.conf.default.disable_ipv6=0 \
	--cap-add NET_ADMIN \
	--name tun2proxy \
	tun2proxy --proxy proto://[username[:password]@]host:port

You can then provide the running container's network to another worker container by sharing the network namespace (like kubernetes sidecar):

bash
docker run -it \
	--network "container:tun2proxy" \
	ubuntu:latest

Docker Compose

Create a docker-compose.yaml file with the following content:

yaml
services:
  tun2proxy:
    volumes:
      - /dev/net/tun:/dev/net/tun
    sysctls:
      - net.ipv6.conf.default.disable_ipv6=0
    cap_add:
      - NET_ADMIN
    container_name: tun2proxy
    image: ghcr.io/tun2proxy/tun2proxy-ubuntu:latest
    command: --proxy proto://[username[:password]@]host:port
  alpine:
    stdin_open: true
    tty: true
    network_mode: container:tun2proxy
    image: alpine:latest
    command: apk add curl && curl ifconfig.icu && sleep 10

Then run the compose file

bash
docker compose up -d tun2proxy
docker compose up alpine

Configuration Tips

DNS

When DNS resolution is performed by a service on your machine or through a server in your local network, DNS resolution will not be performed through the tunnel interface, since the routes to localhost or your local network are more specific than 0.0.0.0/1 and 128.0.0.0/1. In this case, it may be advisable to update your /etc/resolv.conf file to use a nameserver address that is routed through the tunnel interface. When virtual DNS is working correctly, you will see log messages like DNS query: example.org for hostnames which your machine is connecting to after having resolved them through DNS.

Note that software like the NetworkManager may change the /etc/resolv.conf file automatically at any time, which will result in DNS leaks. A hacky solution to prevent this consists in making the file immutable as follows: sudo chattr +i "$(realpath /etc/resolv.conf)".

IPv6

Some proxy servers might not support IPv6. When using virtual DNS, this is not a problem as DNS names are resolved by the proxy server. When DNS names are resolved to IPv6 addresses locally, this becomes a problem as the proxy will be asked to open connections to IPv6 destinations. In such a case, you can disable IPv6 on your machine. This can be done either through sysctl -w net.ipv6.conf.all.disable_ipv6=1 and sysctl -w net.ipv6.conf.default.disable_ipv6=1 or through ip -6 route del default, which causes the libc resolver (and other software) to not issue DNS AAAA requests for IPv6 addresses.

Contributors ✨

Thanks goes to these wonderful people:

Issues· 0 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

Rusthttp-proxyproxysockssocks5

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言