shadowsocks/shadowsocks-rust · error

not supported tcp transparent proxy type

Error message

not supported tcp transparent proxy type

What it means

On Linux the TCP redir listener supports RedirType::Redirect and RedirType::TProxy only. Any other RedirType value (e.g. PacketFilter) hits the wildcard arm and bind_redir returns InvalidInput "not supported tcp transparent proxy type".

Source

Thrown at crates/shadowsocks-service/src/local/redir/tcprelay/sys/unix/linux.rs:90

                } else {
                    // bind, listen as original
                    socket.bind(addr)?;
                }

                // mio's default backlog is 1024
                let listener = socket.listen(1024)?;

                if accept_opts.tcp.fastopen {
                    set_tcp_fastopen(&listener)?;
                }

                Ok(listener)
            }
            RedirType::TProxy => {
                // TPROXY rule requires IP_TRANSPARENT
                create_redir_listener(addr, accept_opts).await
            }
            _ => Err(Error::new(
                ErrorKind::InvalidInput,
                "not supported tcp transparent proxy type",
            )),
        }
    }
}

impl TcpStreamRedirExt for TcpStream {
    fn destination_addr(&self, ty: RedirType) -> io::Result<SocketAddr> {
        match ty {
            RedirType::Redirect => get_original_destination_addr(self),
            RedirType::TProxy => {
                // For TPROXY, uses getsockname() to retrieve original destination address
                self.local_addr()
            }
            _ => unreachable!("not supported tcp transparent proxy type"),
        }
    }

View on GitHub (pinned to 8eb0f0a65b)

Solutions

  1. Set tcp redir type to `redirect` or `tproxy` in the Linux local config.
  2. If TProxy is desired, ensure the kernel supports TPROXY and the process has CAP_NET_ADMIN (IP_TRANSPARENT).
  3. Use platform-conditional config files per host.
  4. Confirm the redir type string against the supported list in the docs.

Example fix

// before (config.json on Linux)
"tcp_redir": "packet-filter"
// after
"tcp_redir": "tproxy"
Defensive patterns

Strategy: validation

Validate before calling

#[cfg(target_os = "linux")]
assert!(matches!(ty, RedirType::Redirect | RedirType::TProxy));

Type guard

fn is_supported_tcp_redir_linux(ty: &RedirType) -> bool {
    matches!(ty, RedirType::Redirect | RedirType::TProxy)
}

Try / catch

match bind_redir(ty, addr, accept_opts).await {
    Err(e) if e.kind() == std::io::ErrorKind::InvalidInput => {
    eprintln!("unsupported redir type {ty:?} on Linux; use redirect or tproxy");
        std::process::exit(2);
    }
    r => r?,
}

Prevention

When it happens

Trigger: Calling bind_redir on Linux with a RedirType other than Redirect or TProxy — typically a config copied from a BSD/macOS host using PacketFilter or IpFirewall.

Common situations: Sharing one config file across Linux and macOS hosts, typos in the redir type value, or older binaries whose enum decoding accepted a type this platform can't bind.

Related errors


AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09). Data as JSON: /api/errors/ce9a8fed6b19df5e. Report an issue: GitHub.