SagerNet / SagerNet/sing-box

[Windows][TUN] direct outbound loops into its own TUN, self-ignited by system DNS, works on any UDP port

Open
#4,455 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
38.2k
Forks
4.6k
Avg merge
19d 15h
Merged PRs (30d)
1

Description


Reproduction

Environment: sing-box 1.13.19, windows/amd64, official release binary, running elevated,
on Windows 11 21H2.

Config (minimal.json):

{
  "log": { "level": "info", "timestamp": true },
  "inbounds": [
    {
      "type": "tun",
      "tag": "tun",
      "address": ["172.19.0.1/30", "fdfe:dcba:9876::1/126"],
      "auto_route": true,
      "strict_route": true
    }
  ],
  "outbounds": [{ "type": "direct", "tag": "direct" }],
  "route": {
    "rules": [{ "ip_is_private": true, "outbound": "direct" }],
    "final": "direct",
    "auto_detect_interface": true
  }
}

Run (administrator):

sing-box run -c minimal.json

That's all — no packets need to be sent by anyone. sing-box registers the TUN peer
addresses (172.19.0.2, fdfe:dcba:9876::2) as the adapter's DNS servers; within seconds
of startup the Windows resolver starts querying them, those datagrams enter the TUN, and
the loop ignites by itself.

(For a deterministic trigger instead of waiting, send one UDP datagram to any port from
a regular shell — nothing needs to be listening there.)

(New-Object Net.Sockets.UdpClient).Send([Text.Encoding]::ASCII.GetBytes('x'),1,'172.19.0.2',9999)

What happens

An endless packet loop on any destination port, self-ignited here on port 53 with
zero user traffic:

INFO inbound/tun[tun]: inbound packet connection from 172.19.0.1:49960
INFO inbound/tun[tun]: inbound packet connection to 172.19.0.2:53
INFO outbound/direct[direct]: outbound packet connection
INFO inbound/tun[tun]: inbound packet connection from [fdfe:dcba:9876::1]:49961
INFO inbound/tun[tun]: inbound packet connection to [fdfe:dcba:9876::2]:53
...

The source port increments on every pass: each datagram written back by direct enters
the same TUN again and is treated as a brand-new flow, so connection tracking never
terminates it. This causes very high CPU usage, starting immediately at startup and
continuing until the process is killed.

Cause

Under auto_route, the OS resolves the TUN peer 172.19.0.2 as the default gateway.
Any datagram sent to it enters the TUN, matches ip_is_private => direct, and the
direct outbound auto-detects the outgoing interface by destination — which is the TUN
itself — writing the packet back into the same device. System DNS queries to .2:53
provide the self-igniting vector; gateway probes (NAT-PMP 5351, SSDP 1900, ...) or a
single manual datagram work on any other port.

Verified with an isolated test: rejecting every port (1–65535) on 172.19.0.2 except
a single unused one (23292) — DNS 53, NAT-PMP 5351, SSDP 1900 all dropped — three manual
datagrams to that sole surviving port still ignited the identical loop. The loop does not
care about ports at all; only the destination address matters.

Workaround that fully stops it

{
  "ip_cidr": ["172.19.0.0/30", "fdfe:dcba:9876::/126"],
  "action": "reject",
  "method": "drop"
}

Placed after DNS-hijack rules and before ip_is_private. Verified: identical ignition
attempt after this rule → +0.06 s CPU / +5 KB logs (fully suppressed). Blocking only ports
5351/1900 does NOT stop the loop — it works on any port.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the loop with the provided minimal.json configuration and sing-box run -c minimal.json on Windows. Trace the Windows TUN auto_route and direct outbound handling for packets sent to the TUN peer addresses, then verify that DNS and arbitrary-port datagrams no longer re-enter the same TUN while normal routing remains functional.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
networking
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.