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

auto_redirect: output_udp_icmp routes replies to inbound UDP into the TUN

Open Beginner friendly
#95 0 comments 0 reactions 0 assignees View on GitHub

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

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

  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.