Skip to content

Redirect & TProxy — sing-box ​

sing-box has two dedicated inbound types for Linux transparent proxying: redirect (iptables REDIRECT, TCP only) and tproxy (iptables/nftables TPROXY, TCP+UDP).

type: "redirect" ​

json
{
  "inbounds": [{
    "type": "redirect",
    "tag": "redir-in",
    "listen": "127.0.0.1",
    "listen_port": 12345
  }]
}

Only the embedded ListenOptions fields apply (listen, listen_port, tcp_fast_open, netns, …). REDIRECT is TCP only.

Pair with iptables:

sh
iptables -t nat -N SING_BOX
iptables -t nat -A SING_BOX -d 192.168.0.0/16 -j RETURN
iptables -t nat -A SING_BOX -d 10.0.0.0/8 -j RETURN
iptables -t nat -A SING_BOX -p tcp -j REDIRECT --to-ports 12345
iptables -t nat -A OUTPUT -p tcp -j SING_BOX

type: "tproxy" ​

FieldTypeDefaultAllowed valuesDescription
networkNetworkList(tcp+udp)tcp | udp | Restrict to TCP-only or UDP-only. TPROXY supports both; REDIRECT is TCP-only.
udp_mappingUDPNATBehaviorendpoint_independentendpoint_independent | address_dependent | address_and_port_dependentUDP NAT mapping: reuse one mapping per source address and port for all destinations (default), or a separate mapping per destination address / address and port.
udp_filteringUDPNATBehaviorendpoint_independentendpoint_independent | address_dependent | address_and_port_dependentUDP NAT filtering: accept packets from any remote endpoint (default), or only from addresses / address-and-port pairs already sent to.
udp_nat_maxuint320 (auto)<uint32>Maximum number of UDP NAT sessions; the least recently used one is closed when full. 0 means 4096 on iOS, otherwise 4096–16384 based on total memory (16384 if it can't be detected).

Source: option/redir.go:7-13 · pinned at v1.14.2 (af6e64c)

Plus the embedded ListenOptions.

json
{
  "inbounds": [{
    "type": "tproxy",
    "tag": "tproxy-in",
    "listen": "0.0.0.0",
    "listen_port": 12345,
    "network": "tcp,udp"
  }]
}

The matching iptables mangle rules:

sh
iptables -t mangle -N SING_BOX
iptables -t mangle -A SING_BOX -d 192.168.0.0/16 -j RETURN
iptables -t mangle -A SING_BOX -d 10.0.0.0/8 -j RETURN
iptables -t mangle -A SING_BOX -m mark --mark 0x100 -j RETURN
iptables -t mangle -A SING_BOX -p tcp -j TPROXY --on-port 12345 --tproxy-mark 0x1
iptables -t mangle -A SING_BOX -p udp -j TPROXY --on-port 12345 --tproxy-mark 0x1
iptables -t mangle -A PREROUTING -j SING_BOX

ip rule add fwmark 0x1 table 100
ip route add local 0.0.0.0/0 dev lo table 100

The escape mark (0x100 above) should match a corresponding fwmark on sing-box's outbound sockets — set via the outbound's routing_mark field or route.default_mark.

Notes ​

  • Both inbound types need CAP_NET_ADMIN. Run sing-box as root or set the capability on the binary with setcap.
  • tproxy is preferred for new setups because it handles UDP and works without NAT translation (the original destination is read cleanly from the socket).
  • These are Linux-only inbound types. On other platforms, use TUN for transparent proxying.

Cross-core notes ​

Source: option/redir.go:7-13 · v1.14.2 (af6e64c)

Core Tutorial by Argsment