# wireproxy: a userspace WireGuard client that speaks SOCKS5 and HTTP

> wireproxy runs a WireGuard peer entirely in userspace and exposes it as a SOCKS5 or HTTP proxy, a TCP tunnel, or an SNI-based TLS proxy, with no kernel interface and no root. It is a small, ISC-licensed Go binary that fits selective routing on a laptop or a container.

**windtf/wireproxy** — Wireguard client that exposes itself as a socks5 proxy

- Repository: https://github.com/windtf/wireproxy
- Stars: 5,816 · Forks: 408
- Language: Go
- License: ISC
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/windtf-wireproxy

## The problem wireproxy solves: WireGuard without a network interface

A normal WireGuard setup creates a network interface and routes traffic for the whole machine. That requires elevated privileges, it changes global routing, and it is awkward when you only want one application to leave through a particular peer. wireproxy takes the opposite approach. According to the README, it is "a completely userspace application that connects to a wireguard peer, and exposes a socks5/http proxy or tunnels on the machine." The WireGuard protocol stack lives inside the process, so the host sees a local listening socket, not a tunnel device.

The README states the motivation directly: you might want this if you "simply want to use wireguard as a way to proxy some traffic" or "don't want root permission just to change wireguard settings." The author describes running it connected to a peer in another country and pointing a browser at it for selected sites. That is the target user: someone who wants per-application routing and is willing to configure a proxy in the client rather than a route in the kernel. The repository also ships a Dockerfile and systemd and rc.d directories, which suggests the same binary is expected to run as a service on a server or in a container.

## How the userspace data path works

The configuration file uses the same [Interface] and [Peer] semantics as wg-quick, which the README points to for field meanings. Address, PrivateKey, DNS, PublicKey, PresharedKey, Endpoint and PersistentKeepalive all appear in the sample. The PrivateKey field can also reference an environment variable, as the sample shows with $MY_WIREGUARD_PRIVATE_KEY.

On top of that peer definition, wireproxy attaches listeners. [Socks5] and [http] bind a local address and route connections through WireGuard. [TCPClientTunnel] listens locally and forwards to a fixed target over the tunnel, while [TCPServerTunnel] listens on the WireGuard side and forwards to a target on the local network. [STDIOTunnel] wires the process's standard input and output to a TCP target, which the README suggests using as an ssh ProxyCommand. [SNI] is a transparent TLS proxy that picks its destination from the TLS Server Name Indication.

Routing is where the design gets interesting. TunnelDomains takes Go regular expressions (RE2). When it is set, only destinations matching a pattern go through WireGuard; everything else is dialed directly over the normal network. The README is explicit that each TunnelDomains line is one full expression, that the key must be repeated for multiple patterns instead of comma-separated, and that matching is case-insensitive with a trailing dot ignored. LogDomains, off by default, logs each destination host and whether it went to TUNNEL or DIRECT. That pairing is the practical part: you discover what your applications contact, then write patterns. The go.mod file shows gvisor and the wireguard-go package, consistent with a userspace stack, plus go-socks5 for the SOCKS5 side.

## Installing wireproxy and running a first SOCKS5 proxy

The README gives two install paths. The Go toolchain route is a single command, and the repository's own module path is used:

```bash
go install github.com/windtf/wireproxy/cmd/wireproxy@v1.1.2 # or @latest
```

Building from source is also documented, and the Makefile sets CGO_ENABLED to 0, so the result is a static binary:

```bash
git clone https://github.com/octeep/wireproxy
cd wireproxy
make
```

There is a Dockerfile as well. It builds with golang:1.26, copies the binary into gcr.io/distroless/static-debian11:nonroot, declares a volume at /etc/wireproxy and defaults to --config /etc/wireproxy/config.

For a first real run, start from the sample configuration: fill in your own PrivateKey, the peer PublicKey and the Endpoint, then add a SOCKS5 listener. The README's sample uses these values:

```ini
[Interface]
Address = 10.200.200.2/32
PrivateKey = $MY_WIREGUARD_PRIVATE_KEY
DNS = 10.200.200.1

[Peer]
PublicKey = QP+A67Z2UBrMgvNIdHv8gPel5URWNLS4B3ZQ2hQIZlg=
Endpoint = my.ddns.example.com:51820

[Socks5]
BindAddress = 127.0.0.1:25344
```

Run the binary with an explicit config path, which is the documented invocation:

```bash
./wireproxy -c myconfig.conf
```

With no -c flag, the README says wireproxy looks in /etc/wireproxy/wireproxy.conf and then $HOME/.config/wireproxy.conf. Point your browser or an application at the SOCKS5 listener on 127.0.0.1:25344 and its traffic should leave through the peer. Before that, validate the file with the configtest flag, which the help text describes as checking the configuration file for validity:

```bash
./wireproxy -n -c myconfig.conf
```

If you want to see which destinations are being tunnelled before committing to TunnelDomains patterns, set LogDomains in the listener section and watch the output.

## Where wireproxy stops: UDP, authentication and scope

The most concrete limitation is in the README's TODO list: UDP support in SOCKS5 and UDP static routing are both listed as not done. The feature list says the SOCKS5 and HTTP proxy currently supports only CONNECT. Anything that depends on UDP through the proxy, DNS over UDP being the obvious case, is outside what this version does. The sample config sets DNS to a WireGuard-side resolver, but that is a tunnel-side setting, not a proxy feature.

Scope is the second constraint. wireproxy is a proxy, not a VPN. Applications that do not speak SOCKS5 or HTTP, or that cannot be pointed at a proxy, will not use it. The README's own framing supports this: it is for people who want to proxy some traffic. If you need every process on the host behind a peer, a kernel WireGuard interface is the simpler answer.

Configuration has sharp edges too. TunnelDomains entries must be single RE2 expressions with the key repeated per pattern; comma-separating them will break quantifiers such as {2,4}, and the README warns about this explicitly. The Socks5 and http sections note that specifying a username and password enables proxy authentication, and that passwords should avoid spaces. There is no documented credential store or rotation mechanism. The README also does not document rollback behaviour or what happens to established connections when the peer configuration changes, so that has to be tested rather than assumed.

## Alternatives and how they differ in approach

The closest conceptual alternative is a kernel WireGuard interface managed by wg-quick. The difference is architectural rather than cosmetic: wg-quick creates a real interface and installs routes, so all traffic matching those routes is affected and root is required. wireproxy keeps the stack in userspace and exposes a local proxy, so only applications configured to use it are affected and no root is needed. The trade-off is that you must configure each client, and you lose UDP through the proxy.

Among proxy front ends, the README itself points to a fork by @artem-russkikh for users who want the same idea with Amnezia VPN instead of plain WireGuard. That is a different upstream protocol, not a different proxy design. For container users, the Dockerfile shows wireproxy running as a nonroot distroless image with the config mounted at /etc/wireproxy, which is a narrower footprint than a container that needs NET_ADMIN to bring up an interface.

If your requirement is transparent interception of all traffic on a host, none of the proxy-based designs fit. If your requirement is a single application or a browser profile leaving through a peer, wireproxy's per-listener config is more direct than building routes and firewall rules by hand.

## Maintenance, licence and upgrade cost

The repository is not archived, and the last push was on 2026-09-17, five days before this writing, so the project is being touched. The most recent release listed is v1.1.3 from 2026-07-16, preceded by v1.1.2 and v1.1.1 in March 2026. Releases are not frequent, which matters if you are tracking upstream WireGuard changes: go.mod pins golang.zx2c4.com/wireguard to a 2025-05-21 pseudo-version and gvisor to a 2025-05-03 pseudo-version, so the userspace stack advances when someone bumps those lines.

Upgrading is cheap in operational terms. It is a single static binary, the Makefile strips symbols with -trimpath -ldflags "-s -w", and the Docker image is distroless. There is no database, no migration step and no daemon protocol to keep in sync. The real upgrade cost is configuration compatibility: your config file follows wg-quick semantics, and new keys such as TunnelDomains and LogDomains have been added to listener sections, so a config written for an older release may not exercise the newer routing behaviour. Running the binary with -n before swapping it in is the low-cost check.

The licence is ISC, a permissive licence, and the README badge and the Dockerfile label both state it. That is compatible with embedding the binary in a larger product, but the README carries no warranty or support statement, and the project has a sponsor whose banner appears in the README. If your organisation requires a support contract or a formal security review process, this repository does not provide one. Nothing here is legal advice; read the LICENSE file yourself.

## Conclusion

wireproxy suits developers and operators who want to route a browser, a CLI tool or a single TCP stream through a WireGuard peer without touching the host's network interfaces or asking for root. It is a poor fit if you need UDP through the proxy, a full VPN for every process on the machine, or an Android client: the README lists UDP support in SOCKS5 and UDP static routing as open TODO items, and no Android build is described. Before adopting it, run the binary with -n against your config file to confirm it parses, and check whether your TunnelDomains patterns match the hosts your applications actually contact by enabling LogDomains.

## FAQ

### Can I use wireproxy as a VPN?

Not in the usual sense. wireproxy is a userspace WireGuard client that exposes SOCKS5, HTTP, TCP tunnels or an SNI proxy on the machine, so only applications pointed at those listeners use the tunnel. It does not create a network interface or route all host traffic.

### Is wireproxy a SOCKS5 proxy or a VPN?

Both descriptions touch part of it. The README describes it as a WireGuard client that exposes itself as a SOCKS5 or HTTP proxy, so the proxy is the interface and WireGuard is the transport underneath.

### Can wireproxy's SOCKS5 proxy be detected?

The README does not discuss detection or fingerprinting of the proxy, so there is nothing in the documentation to confirm either way. What is documented is that the SOCKS5 and HTTP proxy currently supports only CONNECT.

### Which proxy is better with wireproxy, HTTP or SOCKS5?

The README documents both listeners with the same routing behaviour and the same TunnelDomains and LogDomains semantics, and states that both currently support only CONNECT. It does not rank one above the other, so the choice depends on what your client speaks.

## Sources

- [Issues](https://github.com/windtf/wireproxy/issues)
- [License: ISC](https://github.com/windtf/wireproxy/blob/master/LICENSE)
- [README](https://github.com/windtf/wireproxy/blob/master/README.md)
- [Releases](https://github.com/windtf/wireproxy/releases)
- [windtf/wireproxy on GitHub](https://github.com/windtf/wireproxy)

---

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