Why the TUN stack knob is not cosmetic
In Clash Meta profiles, the tun section is often taught as a binary: enable the virtual interface, pick an MTU, maybe tune auto-route, and call it a day. The stack field, when present, is quieter marketing—but it changes which code reassembles segments, tracks congestion cues, and hands datagrams to your proxy outbounds. That matters the moment you care about micro-stalls (“it still buffers”) or protocol families that do not behave like plain TCP through port 443.
This article deliberately avoids declaring a universal winner. Operating systems differ, drivers collide, and your subscription transport (for example Hysteria2 or TUIC, discussed in our QUIC-oriented protocol benchmark) already colors latency. Treat gvisor versus system as a controlled variable: flip it once, reproduce one failure, read logs, then decide.
Two stacks in one sentence each
gVisor-style stack: a userspace network implementation sits between the TUN file descriptor and your proxy engine. Packets are parsed and TCP state machines are executed without handing every decision to the host kernel’s TCP implementation—or, depending on version and fork, with a narrower delegation boundary than full kernel TCP.
System stack: once frames leave the tunnel abstraction, much of the heavy lifting returns to the operating system’s native TCP/IP path. The proxy still owns policy (which outbound, which rule matched), but the shape of retransmits, certain buffer behaviors, and integration with OS fast paths can track what games and browsers already optimize for on that machine.
Exact key names drift. Your GUI may expose “TUN Stack” labels while YAML uses tun.stack. Export the profile you actually run and match it to release notes for the core revision pinned by your client.
Latency, jitter, and CPU: what people actually feel
Users describe gvisor with language that maps to engineering trade-offs: slightly higher CPU on bursty downloads, a sense that “everything is wrapped in another layer.” That is not imaginary—moving TCP into userspace adds scheduling edges. On a modern laptop the cost is often negligible for web browsing; on a thermally throttled ultrabook streaming 4K while compiling containers, it may surface as uneven pacing.
System stack advocates often report cleaner micro-jitter in FPS titles or rhythm-sensitive input paths. The caveat is that “cleaner” is not a guarantee: kernel participation also means you inherit whichever Windows Defender filter driver, VPN leftover, or hypervisor bridge currently meddles with your NIC list. If the OS path is pristine, system stack can feel closer to bare metal. If the OS path is busy arguing with another WFP provider, system stack concentrates the pain where gVisor might have absorbed a fraction of the chaos—emphasis on might.
Throughput ceilings matter less—until they do
Saturating a 1 Gbps LAN download is not the same workload as holding a stable 30 ms round trip for a hundred small UDP voice frames. gVisor historically shines when you need predictable isolation semantics at the cost of peak efficiency. System stack may win on raw bulk throughput when nothing else competes for the kernel datapath. For most readers, the decisive signal will be interactive smoothness, not Speedtest bragging rights.
QUIC, HTTP/3, and connection migration
QUIC rides UDP with user-space timing assumptions. Browsers probe multiple paths, race certificates, and recover from loss differently than TCP-heavy stacks from a decade ago. When TUN captures QUIC, you are asking the proxy ecosystem to classify and forward UDP flows that may span long-lived session IDs—not a single nostalgic “UDP port for DNS” story.
gvisor can normalize some edge behaviors because more of the lifecycle is visible to the same process that applies routing policy. System stack may interact more directly with OS UDP APIs—helpful when the OS already coalesced NIC offloads you rely on, harmful when a security product reorders datagram delivery. If you are debugging odd QUIC failures, pair this section with the Meta DNS hardening guide: a surprising share of “HTTP/3 is broken” reports are still wrong answers or stale caches, not transport religion.
Gaming workloads: anti-cheat, UDP voice, and LAN parties
Competitive games mix reliable-order TCP for patches and naked UDP for world state. Anti-cheat vendors watch for virtual adapters that smell like routing hacks, and some titles stress bind behavior in ways that interact badly with split stacks. Neither gvisor nor system grants a cheat-code bypass; both can still trip heuristics if your profile is overly aggressive.
Practical playbook: use one reproducible session (same map, same server region), switch stack, and compare packet loss statistics in-game—not just average ping. If voice drops correlate with TUN on but disappear on system proxy–only tests, capture whether UDP 3478-class traffic is matched to the intended group. Our Discord UDP and TUN walkthrough offers a template for that triage without rehashing every TUN prerequisite from scratch.
Compatibility: when gVisor is the safer default
Reach for gvisor when the system stack triggers mysteries that smell like kernel integration: sudden drops after sleep/resume, coexistence with corporate VPNs, multiple TUN producers fighting for interface metrics, or hypervisor networking that rewires ARP assumptions. Userspace TCP is not magic, but it shrinks the surface area where a third-party driver injects policy you did not model in YAML.
Prefer experimenting with system when you trust the host networking stack, need the lowest practical userspace overhead, or you observe CPU saturation attributable to packet parsing in logs. Also consider system when another guide—such as the Clash Verge Rev TUN setup tutorial—already validated TUN service prerequisites on your platform and the remaining issue is strictly micro-latency rather than outright breakage.
TUN is not permission to ignore rules. Choosing system because it feels faster, while half your traffic still bypasses policy due to hard-coded IPs in browsers, produces ghost issues harder than either stack alone explains.
Decision guide without tribal myths
- Try system first when latency and jitter dominate, the machine is clean of competing filters, and QUIC/TCP both misbehave equally on gVisor.
- Try gVisor first when coexistence is messy—VPN overlap, exotic NIC drivers—or when system stack coincides with unexplained hangs that vanish if you disable TUN entirely.
- Try neither as a religion: if toggling stack changes symptoms but DNS still returns inconsistent families, fix resolver policy before declaring victory.
Document outcomes like an incident timeline: timestamp, stack value, matched rule, outbound group, and whether the symptom survived a reboot. Future-you will not trust memory after the third energy drink.
After the stack: DNS, rules, and environment variables
Stack selection should sit before deep DNS archaeology, not after. Once capture is trustworthy, validate fake-ip-filter exclusions, sniffer alignment for TLS SNI, and whether nameserver-policy splits still match how GEOSITE buckets behave. Environment variables that force proxies inside terminals (ALL_PROXY, language-specific HTTP libraries) can bypass TUN entirely—no stack option rescues a process that never touched the tunnel.
If you are ready to formalize resolver architecture, the DNS leak prevention article remains the right companion: it explains FakeIP, DoH, and pragmatic hijack without duplicating this TUN transport layer story.
1Fair A/B testing that convinces skeptics
- Freeze variables: same node, same subscription refresh window, same time of day. Note laptop power state (battery vs AC changes scheduler behavior).
- Change only
tun.stack: resist the urge to toggle MTU and auto-route simultaneously. - Use two observables: an in-app metric (game net graph, VoIP MOS if available) plus Mihomo logs filtered to the destination IP or domain.
- Capture QUIC explicitly: reproduce with HTTP/3 enabled and disabled in the browser to separate loss from alt-protocol negotiation.
- Rollback path: export both YAML snapshots so you can diff rather than hand-merge fragments at midnight.
Illustrative YAML sketch
Treat this as a conversation starter; clients may merge defaults you do not see in the UI. On Linux desktops you might combine TUN with cgroup or network namespace experiments; on Windows you might layer WSL2 or hypervisors that install their own virtual switches—each combination shifts whether kernel integration helps or hurts. When in doubt, capture ipconfig / ip route snapshots beside each stack flip so you can correlate interface metric churn with the subjective “lag spike” narrative.
tun:
enable: true
stack: system # or gvisor — flip exactly here for apples-to-apples tests
auto-route: true
strict-route: true # optional; validate against your LAN needs
Installers, docs, and source
Grab stable installers from our official download page; reserve GitHub for reviewing source, filing issues, or validating signatures—not for casual end-user packaging roulette. When vocabulary drifts between GUIs, anchor on the configuration documentation hub so teammates map features consistently across Windows and macOS builds.
Closing
Clash Meta strength is layering: TUN capture, resolver policy, outbound health, and rules all have to agree at runtime. The gvisor versus system fork is a small YAML diff with oversized effects because it decides who owns TCP state and how tightly your virtual NIC hugs the host. Pick based on evidence from your machine, then export the profile so the next debugging session starts from a labeled baseline instead of rumor.
Compared with ad-hoc forks that hide which core revision they ship, distributions that pair a transparent Meta build with sane defaults tend to waste fewer weekends—which is why we still steer ordinary readers toward curated installers while experts chase upstream changelogs.