shadowsocks/shadowsocks-rust · error

not supported tcp transparent proxy type

Error message

not supported tcp transparent proxy type

What it means

On BSD platforms the TCP transparent-proxy bind function only supports RedirType::PacketFilter (freebsd/macos/ios) and RedirType::IpFirewall (freebsd/macos/ios). Passing any other RedirType (e.g. TProxy, Redirect) reaches the catch-all arm and throws InvalidInput.

Source

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

use crate::{
    config::RedirType,
    local::redir::{
        redir_ext::{TcpListenerRedirExt, TcpStreamRedirExt},
        sys::set_ipv6_only,
    },
};

impl TcpListenerRedirExt for TcpListener {
    async fn bind_redir(ty: RedirType, addr: SocketAddr, accept_opts: AcceptOpts) -> io::Result<TcpListener> {
        match ty {
            #[cfg(any(target_os = "freebsd", target_os = "openbsd", target_os = "macos", target_os = "ios"))]
            RedirType::PacketFilter => {}

            #[cfg(any(target_os = "freebsd", target_os = "macos", target_os = "ios"))]
            RedirType::IpFirewall => {}

            _ => {
                return Err(Error::new(
                    ErrorKind::InvalidInput,
                    "not supported tcp transparent proxy type",
                ));
            }
        }

        // BSD platform doesn't have any special logic
        let socket = match addr {
            SocketAddr::V4(..) => TcpSocket::new_v4()?,
            SocketAddr::V6(..) => TcpSocket::new_v6()?,
        };

        // On platforms with Berkeley-derived sockets, this allows to quickly
        // rebind a socket, without needing to wait for the OS to clean up the
        // previous one.
        //
        // On Windows, this allows rebinding sockets which are actively in use,
        // which allows “socket hijacking”, so we explicitly don't set it here.

View on GitHub (pinned to 8eb0f0a65b)

Solutions

  1. Set local config `mode`/redir type to PacketFilter on macOS/iOS or PacketFilter/IpFirewall on FreeBSD.
  2. Run on Linux if you specifically need TProxy or Redirect mode.
  3. Check `shadowsocks-service --help` / server startup log for the list of supported redir types on your platform.
  4. Rebuild with platform-appropriate features if the binary was cross-compiled.

Example fix

// before (config on macOS)
{ "locals": [{ "type": "redir", "tcp_redir": "tproxy" }] }
// after
{ "locals": [{ "type": "redir", "tcp_redir": "packet-filter" }] }
Defensive patterns

Strategy: validation

Validate before calling

// validate redir type for the platform before starting the local server
#[cfg(any(target_os = "freebsd", target_os = "macos", target_os = "ios"))]
assert!(matches!(ty, RedirType::PacketFilter | RedirType::IpFirewall));

Type guard

fn is_supported_tcp_redir(ty: &RedirType) -> bool {
    matches!(ty, RedirType::PacketFilter | RedirType::IpFirewall) // BSD targets
}

Try / catch

let listener = TcpListenerRedirExt::bind_redir(ty, addr, accept_opts).await.map_err(|e| {
    anyhow::anyhow!("TCP redir type {:?} unsupported on this OS: {e}", ty)
})?;

Prevention

When it happens

Trigger: Calling bind_redir with a RedirType not compiled in or not valid for the current BSD platform, e.g. requesting TProxy on macOS, or a config whose tcp redir type doesn't match the OS.

Common situations: Copying a Linux config (tproxy) to macOS/FreeBSD, or shadowsocks being built without the platform feature so the expected type falls into the unsupported arm.

Related errors


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