sing-tun 的 mark 模式 fallback 规则问题
Nobody has claimed this yet.
Assessment
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Newbie friendliness
- 68/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- go, linux, networking
- Domain
- backend, networking
Research direction
Read the mark mode fallback rule in tun_linux.go, especially the section around IPRoute2AutoRedirectFallbackRuleIndex and both address family rules. Check how the rule handles the default route in table 2022, then run the relevant routing tests. Done means the fallback rules suppress prefix length 0 and IPv6 bypass works with source specific main table routes.
Written by the indexing model from the issue text.
Description
IPv4 bypass 正常,v6 bypass 超时, 命中后由内核转发但路径不通、IPv4 正常、direct 正常(OpenWrt 源特定 IPv6 路由 + table 2022 的默认路由被当成直连路径)
根因
auto_redirect 的预匹配 bypass 是在 nftables/NFQUEUE 里给包打 fwmark 0x2024 后交给内核转发(nfqueue_linux.go 里 ActionBypass -> NfRepeat + outputMark)。而 IPv6 包在走到这一步之前,路由其实已经选过一次了:
本机进程 connect()/ping 时的第一次路由查找,sk_mark 还是 0;tun_linux.go 里 mark 模式的 fallback 规则是: 32768: not fwmark 0x2024 lookup 2022(tun_linux.go 中 IPRoute2AutoRedirectFallbackRuleIndex 那段);
这条规则没有 suppress_prefixlength,于是 table 2022 里的 ::/0 -> 默认路由会直接命中,连接被绑到 TUN 的 fdfe:dcba:9876::1 上,甚至先把包送进 TUN。随后预匹配命中 bypass、打上 0x2024,策略路由重查时:9000: fwmark 0x2024 goto 9002(nop)→ 跳过 2022 → 落到 main;
如果 main 里的 IPv6 默认路由是 OpenWrt sourcefilter/DHCPv6-PD 那种 带源前缀的 from 路由,此时源地址已经是 TUN 的 ULA,匹配不上任何 from 路由 → 无路由 → 包被丢弃;
IPv4 因为 main 有普通 default,所以正常;direct 正常是因为 sing-box 的 socket 在 connect() 前就 SO_MARK=0x2024,第一次查找就走 main 并选对了源地址。
修复
在 tun_linux.go 的 mark 模式 fallback 规则(32768,两个地址族)上增加 go it.SuppressPrefixlen = 0
目前解决办法是在op上取消勾选 IPv6 源路由
- 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
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
gvisor: LinkEndpointFilter.Attach never forwards nil, so GVisor.Close leaks all inbound dispatcher goroutines and fdsPossibly taken @arpitjain099 claimed this 47 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 1 day ago. Open
Difficulty 4/5 3-5 days Newbie friendliness 25/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
-
[Bug]: Deleting an MCP proxy leaves its API keys in the gateway's memory and in the policy engineOpenAspect/API Aspect/Other Severity/Minor Type/Bug
Difficulty 2/5 1-3 hours Newbie friendliness 83/100
wso2/api-platform#3852 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Rafaeldelinares/gentle-mesh#125 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Gentleman-Programming/gentle-ai#5643 ·
Maintainers usually reply within 1 day
-
security
Difficulty 2/5 1-3 hours Newbie friendliness 80/100
FootprintAI/Containarium#2869 ·
Maintainers usually reply within 1 day
-
kind/bug
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
kubevirt/kubevirt#19559 · 1 reaction ·
Maintainers usually reply within 1 day