Queqiao: a self-hosted SOCKS5 tunnel for long-haul links that erase packets
Self-hosted WAN optimization proxy for difficult long-haul links: authenticated QUIC transport with TLS/TCP fallback, SOCKS5 ingress, and packet loss treated as erasure, not congestion.
At a glance
- What is it?
- Queqiao is a Go proxy that presents a local SOCKS5 endpoint and moves TCP and UDP across one authenticated client-to-gateway session, treating packet loss as erasure rather than congestion. The design is opinionated, the measured wins are workload-dependent, and the README is candid about where it does not brake.
- Who is it for?
- Adopt Queqiao when you control both endpoints and the shared WAN segment is the dominant bottleneck: a local SOCKS5 ingress plus a provider gateway, one authenticated session, QUIC with TLS/TCP fallback. Do not adopt it if the bottleneck sits past the gateway, if a policer drops your traffic without queueing, or if you need a mature multi-user access server with per-user accounting.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 11 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 16, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem Queqiao was built for
Queqiao targets a specific shape of network: a long client-to-gateway segment you own at both ends, where latency is high and loss does not track sending rate. The README traces the project to a China-US route and to a later datacenter case where ASR and TTS models run in the US while clients sit elsewhere. Each request is a single burst that must finish before the next step, which is the pattern a long path handles worst. The README gives one concrete figure: a 355KB audio upload from Guiyang to Irvine takes 1185ms, of which the model spends about 30ms, while the path's bandwidth could move that payload in roughly 9ms.
The intended user is not someone shopping for a general VPN. It is an operator with a provider gateway at one end and a client at the other, willing to run both, and willing to accept that the optimization only helps when the shared WAN segment is the real bottleneck. The README states this boundary plainly: if the bottleneck is somewhere else, measure again before relying on the optimization.
How the shared session model works
The client exposes an ordinary local SOCKS5 proxy, including UDP ASSOCIATE. Applications point at it and do not pick a protocol profile. Behind that, the client and the provider gateway form one authenticated transport session, and every flow inside it shares delivery, loss, RTT, pacing and latency-reserve state. QUIC streams and datagrams are used when available, with authenticated TLS/TCP fallback for networks that block QUIC. HTTPS stays end-to-end: the README says the gateway sees destination and traffic shape but Queqiao does not inspect application content.
The control decision is where the project diverges from a normal transport. Loss is not the congestion signal. The brake is a delay bound: the round trip may not exceed twice the path's own minimum. Measured erasure instead sizes the forward error correction and compensates the window. Recovery strategy is chosen per path, since on a long-RTT link FEC can close a gap sooner than another round trip, while retransmission becomes the more efficient choice as a flow grows. Upstream and downstream are measured and controlled independently because they can differ in capacity and loss.
The README's own path characterization found roughly 42 to 45 percent downstream packet erasure below the capacity knee, then clustered loss once aggregate traffic passed it. Those are two regimes, and the design treats them as two: backing off does not remove independent erasure, and ignoring overload makes it worse. The comparison table in the README reports a bulk median of 143.1 Mbit/s for Queqiao against 76.8 for TUIC v5 and 90.2 for Hysteria 2, but the same table shows SSH p99 under bulk load at 940ms for Queqiao versus 662ms and 526ms. The README says this is why it does not claim a universal win. Take that at face value: the shared model buys throughput here and costs interactive tail latency.
Deploying the client and gateway, and sending first traffic
The repository is a Go module, github.com/bojieli/queqiao, built with Go 1.25.13 per go.mod. Binaries come from the cmd/ tree, and deploy/ holds deployment material; the README links docs/DEPLOYING.md for the deployment steps, so that file, not this article, is the authoritative install path. The README does not document a prebuilt binary download, and it does not print a build command, a default port or a CLI flag, so the repository layout and docs/DEPLOYING.md are what you have to work from.
What the README does define is the shape of the deployment: a provider gateway on the far side, a client on the near side, and one authenticated session between them. The client's job is to look like a local SOCKS5 proxy. The README's own diagram shows applications feeding a local SOCKS5 Queqiao client, which then crosses one coordinated long-haul path to the provider gateway and out to Internet destinations:
flowchart LR
A[Applications<br/>Web · SSH · video · transfers] --> B[Local SOCKS5<br/>Queqiao client]
B ==>|one coordinated long-haul path| C[Provider gateway]
C --> D[Internet destinations]Point an application at that local SOCKS5 endpoint the way you would point at any SOCKS5 proxy, using whatever listen address and port your client configuration sets, since the README does not state a default. What you should see is the request completing through the tunnel rather than directly. If it does not, the first thing to check is whether the client and gateway negotiated QUIC or fell back to authenticated TLS/TCP, since restrictive networks will take the fallback path.
Where Queqiao does not brake, and when it is the wrong tool
The README points at docs/KNOWN-LIMITATIONS.md for the case the delay bound does not cover: a policer, which drops without queueing. That is the honest failure mode. The whole control loop rests on the assumption that queueing delay rises before the path is overwhelmed, so a policer that discards silently gives the sender no delay signal to react to. If your path is shaped by a policer rather than a queue, the mechanism the README describes does not have the input it needs.
The second boundary is placement. Queqiao optimizes the client-to-gateway segment. If the loss and latency that hurt you sit beyond the gateway, on the gateway-to-destination leg, the shared session model has nothing to coordinate. The README says this directly: Queqiao is a good fit when the client and gateway are known, trusted endpoints and their shared WAN segment is the dominant bottleneck.
The third is the interactive tail. The README's own comparison shows SSH p99 under bulk load at 940ms, worse than TUIC v5 and Hysteria 2 on that metric. If your workload is dominated by many small interactive sessions sharing a link with bulk transfers, the shared-path design that helps aggregate throughput is the same design that puts your keystrokes behind a queue. The README frames this as a trade-off rather than a defect, and the comparison table supports that framing.
How it differs from TUIC v5 and Hysteria 2
The README's comparison table puts Queqiao, TUIC v5 and Hysteria 2 side by side on three axes: whether the path model is shared or per-connection, what recovery strategy is used, and two measured outcomes. TUIC v5 and Hysteria 2 are described as usually per-connection, with QUIC recovery and protocol-specific UDP/QUIC recovery respectively. Queqiao is described as sharing one model across an endpoint pair, with erasure-aware FEC plus retransmission.
That is the real difference in approach. A per-connection model makes each flow learn the path on its own, which the README calls a reasonable default for the general Internet but wasteful when many application flows share one difficult segment. Queqiao's bet is that flows to different final destinations still traverse the same client-to-gateway path, so they should share delivery, loss, RTT, pacing and latency-reserve state. The cost of that bet shows up in the same table: 143.1 Mbit/s bulk median versus 76.8 and 90.2, but 940ms SSH p99 versus 662ms and 526ms. Neither approach wins on both rows. The README is explicit that these are representative results from a six-round real-path campaign and that results depend on the path and workload.
Maintenance, licence and upgrade cost
The repository is not archived, and the last push was on 2026-09-07, with v0.6.3 released the same day and v0.6.2 and v0.6.1 landing on 2026-09-05 and 2026-09-04. The release cadence in the days before that push is tight, and the README describes the project as still evolving as more paths are measured. The changelog.d/ directory and CHANGELOG.md are where release notes live, and the README links docs/STATUS.md for project status, which is the file to read if you need to judge stability before depending on it.
The licence is MIT, per the LICENSE file at the repository root. MIT is permissive: it allows use, modification and redistribution with the copyright notice and permission notice retained, and it comes with no warranty. This article is not legal advice, and MIT's interaction with any third-party notices is worth reading in THIRD_PARTY_NOTICES.md, since go.mod pulls in github.com/apernet/quic-go, github.com/refraction-networking/utls, and compression and crypto packages under their own terms.
Upgrade cost is concentrated in the transport. The module depends on a pinned pseudo-version of the quic-go fork, v0.61.1-0.20260806010916-184d081eef3e, so upgrading Queqiao can move the QUIC implementation underneath you. If you run both ends yourself, that is manageable; you control the upgrade window and can roll both sides together. The README does not document rollback, so plan the upgrade as a coordinated change rather than assuming a mixed-version client and gateway will interoperate.
Editorial conclusion
Adopt Queqiao when you control both endpoints and the shared WAN segment is the dominant bottleneck: a local SOCKS5 ingress plus a provider gateway, one authenticated session, QUIC with TLS/TCP fallback. Do not adopt it if the bottleneck sits past the gateway, if a policer drops your traffic without queueing, or if you need a mature multi-user access server with per-user accounting. Before rollout, run a short transfer between your two sites and confirm the bulk median and the SSH p99 under load in docs/COMPARISON.md still describe your path, because the README says results depend on the path and workload.
Frequently asked questions
What problem does Queqiao solve?
It carries TCP and UDP across a long client-to-gateway link you control at both ends, using one authenticated session that shares delivery, loss, RTT and pacing state across flows. The README frames it around paths where packet loss is independent erasure rather than congestion.
How does Queqiao handle packet loss?
Loss is not used as the congestion signal. The README states the brake is a delay bound, where the round trip may not exceed twice the path's own minimum, and measured erasure sizes forward error correction and compensates the window instead.
How do I install Queqiao?
The repository is a Go module, github.com/bojieli/queqiao, built with Go 1.25.13 per go.mod, with binaries under cmd/. The README links docs/DEPLOYING.md for deployment steps; it does not document a prebuilt binary download.
What licence is Queqiao released under?
MIT, per the LICENSE file at the repository root. Third-party dependencies listed in go.mod, including a quic-go fork and utls, carry their own terms documented in THIRD_PARTY_NOTICES.md.
Community notes