# tun2socks: routing a TUN device through a proxy with the gVisor network stack

> xjasonlyu/tun2socks is an MIT-licensed Go program that takes packets from a TUN interface and hands them to an HTTP, SOCKS, Shadowsocks, SSH or relay proxy. It is a building block for gateway and transparent-proxy setups, not a packaged consumer VPN app.

**xjasonlyu/tun2socks** — tun2socks - powered by gVisor TCP/IP stack

- Repository: https://github.com/xjasonlyu/tun2socks
- Website: https://github.com/xjasonlyu/tun2socks
- Stars: 5,513 · Forks: 646
- Language: Go
- License: MIT
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/xjasonlyu-tun2socks

## The gap tun2socks fills between a proxy and the operating system

A SOCKS5 or HTTP proxy only accepts connections from programs that know how to speak that protocol. Browsers do; a game, an SSH client, a container runtime or an arbitrary daemon usually does not. tun2socks closes that gap. It creates a TUN device, which is a virtual network interface that the kernel hands IP packets to instead of a physical NIC, and it terminates those packets in user space. Every TCP connection and UDP flow that arrives on the interface is turned into a connection to the configured proxy.

The audience is therefore narrower than the search traffic suggests. The README lists Linux, macOS, Windows, FreeBSD and OpenBSD, and the Makefile builds for those plus a long list of architectures including linux-mips64le, linux-s390x and linux-loong64. That is a tool aimed at people who run routers, home servers or lab machines and want a whole host or a whole subnet to egress through one proxy. It is not aimed at someone who wants a phone app. The repository contains no Android or iOS project, and the topics list mentions shadowsocks, tor, wireguard and ssh-tunnel as things it can front, not as things it bundles.

## How the gVisor TCP/IP stack turns packets into proxy connections

The architecture is visible in the top-level directories. A TUN device is created and handed to the engine, which is the code in engine/. The engine passes the raw IP packets into the gVisor network stack rather than into the host kernel's own TCP/IP implementation. gVisor is a user-space application kernel, and here it does the work of terminating TCP and UDP: reassembling streams, tracking connection state, generating acknowledgements. The dialer/ package then takes each accepted connection and opens the matching connection to the proxy, and proxy/ implements the protocol side: HTTP, SOCKS4 and SOCKS5, Shadowsocks, SSH and a relay protocol via github.com/go-gost/relay. The transport/ package carries the proxied bytes.

The practical consequence of doing TCP/IP in user space is that the host kernel never sees the proxied connections as ordinary sockets tied to the original destination. The kernel only sees the TUN device. That is what makes transparent proxying possible without per-application configuration, and it is also why the MTU and buffer environment variables in the Dockerfile (MTU, TCP_SNDBUF, TCP_RCVBUF, TCP_AUTO_TUNING) exist: the user-space stack has its own memory budget. The README links a wiki page on memory optimization, which is a fair signal that this budget is something operators actually tune. The README also claims IPv6 support and tunnelling of IPv4 over IPv6 and the reverse, but the README does not explain the mechanism behind that mapping, so treat it as a stated feature rather than a documented one.

The README's benchmark image and its claim that tun2socks "performs best" in "all scenarios of usage" come from the project itself, with details on a wiki page. There is no third-party measurement in the repository, and the benchmark covers the project's own comparison set, so it should not be read as a general statement about user-space stacks.

## Installing tun2socks from source and running a first SOCKS5 session

The README points at a wiki page titled Install from Source for the canonical instructions, and the repository carries a Makefile that does the work. Building requires Go, matching the go.mod directive of go 1.26.3. The Makefile disables cgo (CGO_ENABLED := 0) and builds with -trimpath, so the result is a static binary in build/.

```bash
make tun2socks
./build/tun2socks -version
```

The first command compiles the current checkout into build/tun2socks. The second prints the version and git commit that the Makefile injected through -ldflags. If you want a cross-compiled artifact, the Makefile has per-platform targets such as linux-amd64, linux-arm64, darwin-arm64 and windows-amd64; the default all target builds linux-amd64, linux-arm64, darwin-amd64, darwin-arm64 and windows-amd64.

For a first run you need a TUN device and a proxy to point at. The README's Examples wiki page is the reference for the full command line; the shape is a device, an address, and a proxy URL. The Dockerfile gives the same parameters as environment variables with defaults, which is the clearest statement of what a working invocation looks like: TUN=tun0, ADDR=198.18.0.1/15, MTU=9000, PROXY=direct://, LOGLEVEL=info. The direct:// default means the container does nothing useful until you set PROXY.

```bash
docker run --rm -it \
  --cap-add NET_ADMIN \
  -e PROXY=socks5://user:pass@10.0.0.1:1080 \
  -e TUN=tun0 \
  -e ADDR=198.18.0.1/15 \
  xjasonlyu/tun2socks
```

This starts the container with the NET_ADMIN capability, which is required to create the interface, and points it at a SOCKS5 endpoint. The entrypoint script installs iptables and iproute2 in the image, which tells you it expects to configure routing itself. Expect the process to log at info level and then sit there; traffic only appears once the host or the container routes something into 198.18.0.1/15. The Dockerfile also exposes TUN_INCLUDED_ROUTES and TUN_EXCLUDED_ROUTES, which is how you keep some destinations off the tunnel, and EXTRA_COMMANDS for anything the entrypoint does not cover.

On a plain Linux host the equivalent work is creating the device, assigning the address, bringing the interface up and adding a route. The README does not spell out those steps, so the wiki Quickstart Examples page is where to check them rather than guessing flags.

## Where tun2socks is the wrong tool

The most common mismatch is expecting an app. Searches for an APK, an iPhone build or a Windows client will not be satisfied by this repository: it produces a command-line binary and a Docker image. On Android and iOS the TUN device is owned by the system VPN framework, and a program that opens /dev/net/tun directly does not fit that model. If you need a phone client, this project is the wrong layer.

The second mismatch is DNS. tun2socks forwards IP packets; it is not a resolver. The dns/ directory exists, but the README does not document a resolver mode or a DNS policy, so a setup that routes only some prefixes into the tunnel can end up with DNS queries going out unproxied while the connections they precede go through the proxy. That is a configuration problem you have to solve outside the tool, and the README is silent on it.

Third, the memory profile is not free. Terminating TCP/IP in user space means buffers live in the process, which is why the Dockerfile carries TCP_SNDBUF, TCP_RCVBUF and TCP_AUTO_TUNING. On a small router with limited RAM, that is the constraint to watch, and the project's own wiki page on memory optimization is the place to look rather than a defaults file.

Finally, the licence permits commercial use, but the project does not supply support, an SLA or a configuration validator. A misconfigured route on a gateway machine takes down connectivity for everything behind it, and nothing in the repository prevents that.

## tun2socks compared with sing-box and other proxy clients

The nearest comparison in the search data is sing-box, and the difference is one of scope. sing-box is a general proxy platform: it defines its own configuration format, ships its own inbound and outbound types, and can act as a client, a server and a router. tun2socks does one thing. It takes a TUN device and a proxy URL and connects the two, with the proxy protocols listed in the README (HTTP, SOCKS4, SOCKS5, Shadowsocks, SSH, relay) as the outbound side. There is no server mode and no routing rule language in the README.

That narrowness cuts both ways. If your routing policy is complex, you will write it with iproute2 or iptables around tun2socks, and the Dockerfile's TUN_INCLUDED_ROUTES and TUN_EXCLUDED_ROUTES are the only routing knobs it offers. If your policy is simple, a single-purpose binary is easier to reason about than a platform with its own config schema. The restapi/ directory suggests a management surface exists, but the README does not describe its endpoints, and the Dockerfile leaves RESTAPI empty, so it is not something to plan around without reading the source.

Compared with running a SOCKS proxy per application, tun2socks moves the decision from the application to the network layer. That is the whole point, and it is also the whole risk: once the route is in place, every program on the machine is affected, including the ones you forgot about.

## Maintenance, upgrades and what the MIT licence means here

The repository is not archived, and the last push was on 2026-09-13. The release cadence visible in the tags is uneven: v2.6.0 in June 2025, a v2.6.0-beta before it, and v2.7.0 in July 2026. Between releases the main branch moves, so a build from source can be ahead of the newest tag. The Makefile derives BUILD_VERSION from git describe --abbrev-ref=0 --tags HEAD, which means an untagged checkout reports the nearest earlier tag rather than a commit-specific version. If you build from main and later report a bug, that version string will not identify your exact revision.

Upgrade cost is mostly a function of the gVisor dependency. go.mod pins gvisor.dev/gvisor to a pseudo-version dated 2026-09-06, and gVisor is not a stable-API library; it is a large codebase consumed at a specific commit. Bumping it is a real change, not a patch. The same applies to golang.zx2c4.com/wireguard, which is also pinned to a pseudo-version. Expect to rebuild and retest rather than to swap a shared library.

The licence is MIT, per the repository's LICENSE file and the README badge. That is permissive: you can use it in commercial and closed products, and you must keep the copyright and permission notice. It says nothing about the licences of the dependencies you compile in, and gVisor's own terms are a separate matter. That is a question for your own review, not something this article can settle.

## Conclusion

Adopt tun2socks if you already have a proxy endpoint and need a host or a whole LAN segment to send its traffic through it, and you are comfortable creating a TUN device and writing routes yourself. Do not adopt it if you want an app with a toggle: the repository ships a binary, a Docker image and a REST API, not a client for Android, iOS or Windows desktops. Before committing, confirm which proxy protocol your endpoint speaks, check that your platform lets you create the TUN device, and decide whether you need the REST API at all, since the Dockerfile leaves RESTAPI empty by default.

## FAQ

### What is tun2socks used for?

It routes traffic from a TUN device through a proxy, so applications that do not speak SOCKS or HTTP can still be proxied. The README lists HTTP, SOCKS, Shadowsocks, SSH and relay proxies as supported outbound protocols, and it can also act as a Layer 3 gateway for other devices on the same network.

### How do I install tun2socks?

The README links to a wiki page titled Install from Source, and the repository provides a Makefile: running make tun2socks produces build/tun2socks. The go.mod file requires Go 1.26.3, and the Makefile builds with CGO_ENABLED=0.

### How do I set up tun2socks?

You need a TUN device, an address for it, and a proxy URL. The Dockerfile shows the parameters and their defaults as environment variables: TUN=tun0, ADDR=198.18.0.1/15, MTU=9000 and PROXY=direct://, with the direct default meaning no proxying until you set PROXY. The README points to a Quickstart Examples wiki page for the full command line.

### What is tun2socks vs sing-box?

tun2socks is a single-purpose program that connects a TUN device to one proxy URL, with the proxy protocols listed in the README. sing-box is a broader proxy platform with its own configuration format and inbound and outbound types. The README of tun2socks does not document a server mode or a routing rule language.

## Sources

- [License: MIT](https://github.com/xjasonlyu/tun2socks/blob/main/LICENSE)
- [Project website](https://github.com/xjasonlyu/tun2socks)
- [README](https://github.com/xjasonlyu/tun2socks/blob/main/README.md)
- [Releases](https://github.com/xjasonlyu/tun2socks/releases)
- [xjasonlyu/tun2socks on GitHub](https://github.com/xjasonlyu/tun2socks)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/xjasonlyu-tun2socks
