Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

auto_redirect: the mark rule overwrites marks set by other programs, such as Tailscale

Open
#96 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

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

Research direction

Read redirect_nftables_rules.go at nftablesCreateMark and inspect the output_prematch, output, and output_udp_icmp chains, especially where meta mark is written. Reproduce the Linux setup with auto_redirect and Tailscale, then verify that existing policy-routing marks survive sing-box rules. Done means Tailscale peer traffic uses its direct path while sing-box traffic remains redirected.

Written by the indexing model from the issue text.

Description

With auto_redirect on Linux, nftablesCreateMark replaces the whole packet mark. A mark that another program set for its own policy routing is lost. Tailscale is one case: its peer traffic goes into the TUN, and two Tailscale nodes connect through the proxy instead of directly.

Where

nftablesCreateMark (redirect_nftables_rules.go#L729) loads AutoRedirectInputMark with Immediate and writes it to meta mark with no mask. In output_udp_icmp this is the last rule:

meta mark set 0x00002023 ct mark set meta mark counter return

tailscaled marks its sockets with 0x80000 (mask 0xff0000) and adds ip rule entries that send this mark to the main table, before other policy routes. After the rule above, the packet carries 0x2023 only. It does not match the Tailscale rule and goes to the TUN table. TCP to DERP takes the same route through the output chain.

The tailnet ranges are not the problem. route_exclude_address keeps 100.64.0.0/10 out. The traffic that is lost is WireGuard UDP to the peers' public addresses.

Reproduction

sing-box 1.14.1, Linux, a TUN inbound with auto_route, auto_redirect, and route_exclude_address for the tailnet ranges; tailscaled running on the same host and on a second host.

  1. With sing-box running, tailscale ping <peer> answers via <the proxy server's address> with the proxy's round trip: 225 ms in my case
  2. Insert the rules under "Workaround" below. tailscale ping <peer> now answers via <the peer's own address>: 11 ms
Expected

A mark that is already on the packet stays, or the rule returns for it. Two possible forms:

  • return before the mark rule when meta mark & 0xffff0000 != 0, so that the TUN does not take traffic another program routes on its own
  • set only the bits sing-box owns: meta mark set meta mark & 0xffff0000 | 0x2023
Workaround
nft insert rule inet sing-box output_prematch meta mark & 0x00ff0000 == 0x00080000 return
nft insert rule inet sing-box output meta mark & 0x00ff0000 == 0x00080000 return
nft insert rule inet sing-box output_udp_icmp meta mark & 0x00ff0000 == 0x00080000 return

after sing-box creates the table. With these rules, and ct direction reply return from #95, tailscale ping showed the direct path again. I did not test the mark rules without the reply rule.

Dominant language
Go
Stars
241
Forks
243
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

  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.

More from SagerNet/sing-tun

All issues in SagerNet/sing-tun

Similar issues

More Go issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.