[Windows][TUN] direct outbound loops into its own TUN, self-ignited by system DNS, works on any UDP port
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
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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