auto_redirect: output_udp_icmp routes replies to inbound UDP into the TUN
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 76/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- go, linux
- Domain
- networking, operating-systems
Research direction
Start in redirect_nftables.go at output_prematch around line 434, then inspect output_udp_icmp and nftablesCreateMark around line 101. Reproduce the issue with the stated nftables rules and an internet UDP echo server, watching whether the reply enters the TUN or leaves with a changed source port. Done means inbound-flow replies bypass the TUN mark and preserve their source port.
Written by the indexing model from the issue text.
Description
With auto_redirect on Linux, a local UDP server cannot answer a peer on the internet. The answer goes into the TUN, and sing-box sends it from a new source port. The peer drops it.
Where
output_prematch returns early for reply packets (redirect_nftables.go#L434). output_udp_icmp has no such check. It ends in nftablesCreateMark (redirect_nftables.go#L101), so a reply to an inbound flow gets the TUN mark:
chain output_udp_icmp {
type route hook output priority mangle + 2; policy accept;
meta l4proto != { icmp, udp, ipv6-icmp } return
meta mark 0x00002024 counter return
ct mark 0x00002024 counter return
ip daddr { 10.10.0.0/16, 100.64.0.0/10 } counter return
ip6 daddr { fd7a:115c:a1e0::/48 } counter return
ip daddr @inet4_local_address_set counter return
ip6 daddr @inet6_local_address_set counter return
meta mark set 0x00002023 ct mark set meta mark counter return
}
TCP is not affected: the redirect is in a nat chain, and only the first packet of a connection goes through it.
What I saw
sing-box 1.14.1, Linux, a TUN inbound with auto_route and auto_redirect. Syncthing listens on UDP 22000. A peer on a mobile network connects to it over QUIC (quic-server in Syncthing's log), and the connection drops with reading length: timeout: no recent network activity, again and again; Syncthing falls back to a relay. The chain above is from that host, with the packet counters removed.
I did not isolate this with a minimal server. The steps that should show it with the rule set above: run a UDP echo server on the host, send it a datagram from a host on the internet (not the LAN, which is in inet4_local_address_set), and watch the answer leave the physical interface from another source port, or not at all.
Expected
A reply to a flow that came in on another interface leaves by the host's routes, with its source port, the same as output_prematch already does.
Possible fix
The same check as in output_prematch, before the mark rule:
nft insert rule inet sing-box output_udp_icmp ct direction reply return
Related: #79 is about the same chain.
- Dominant language
- Go
- Stars
- 240
- Forks
- 240
- PR merge metrics
- No merged PRs in 30d
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
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.
More from SagerNet/sing-tun
-
gvisor: LinkEndpointFilter.Attach never forwards nil, so GVisor.Close leaks all inbound dispatcher goroutines and fdsPossibly taken @arpitjain099 claimed this 46 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
Darwin: utun process UUID headers are parsed as IP payloadPossibly taken @d3pre5s claimed this today. Open
Difficulty 4/5 3-5 days Newbie friendliness 25/100
-
Difficulty 3/5 1-2 days Newbie friendliness 68/100
-
TUN `mixed` stack: TCP never re-injected into tun0 on Linux kernel 7.1 (UDP works, `gvisor` works)Open
Difficulty 4/5 1-2 days Newbie friendliness 45/100
-
Difficulty 3/5 1-2 days Newbie friendliness 70/100
All issues in SagerNet/sing-tun
Similar issues
-
validateDeclaredPath lets control characters through into the Gradle init script's Groovy literalOpenagent-butler-finding agent-research bug ready-for-agent
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
jordansmall/spindrift#5821 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
apache/rocketmq-dashboard#7243 ·
Maintainers usually reply within 3 days
-
Missing example coverage: getClockPossibly taken @camunda-sdk-automation claimed this today. Opennew-operations
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
camunda/orchestration-cluster-api-go#75 · 2 comments ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
praetorianer777/Stator#465 ·
Maintainers usually reply within 1 day