shadowsocks/shadowsocks-rust · critical

open /dev/pf permission denied, consider restart with root u

Error message

open /dev/pf permission denied, consider restart with root user

What it means

On BSD systems the redirector's PacketFilter is opened lazily from /dev/pf; the PF static panics with this message when opening it fails with PermissionDenied. /dev/pf is root-only (or requires pf membership), so the redir service on BSD cannot work as an unprivileged user. This is a fail-fast guard rather than a recoverable error.

Source

Thrown at crates/shadowsocks-service/src/local/redir/sys/unix/bsd_pf.rs:373

        Err(io::Error::other(format!(
            "natlook UDP binding {}, {} not found",
            bind_addr, peer_addr
        )))
    }
}

impl Drop for PacketFilter {
    fn drop(&mut self) {
        unsafe {
            libc::close(self.fd);
        }
    }
}

pub static PF: LazyLock<PacketFilter> = LazyLock::new(|| match PacketFilter::open() {
    Ok(pf) => pf,
    Err(err) if err.kind() == ErrorKind::PermissionDenied => {
        panic!("open /dev/pf permission denied, consider restart with root user");
    }
    Err(err) => {
        panic!("open /dev/pf {err}");
    }
});

View on GitHub (pinned to 8eb0f0a65b)

Solutions

  1. Restart the redir service as root (e.g. sudo or root-owned systemd unit)
  2. Grant the binary the needed capability/membership (add user to pf group or set uid bits)
  3. Run in a pf-enabled environment (host or jail with /dev/pf allowed)
  4. Verify /dev/pf exists (kldload pf / enable pf ruleset) if the device is absent
Defensive patterns

Strategy: validation

Validate before calling

# ensure /dev/pf is openable before launching the redir service:
test -w /dev/pf || echo 'need root or pf group membership'

Prevention

When it happens

Trigger: Lazily initializing `static PF: LazyLock<PacketFilter>` in bsd_pf.rs when a redir server on FreeBSD/OpenBSD/NetBSD calls into the PF NAT lookup and `PacketFilter::open()` returns an error whose kind is ErrorKind::PermissionDenied.

Common situations: Running shadowsocks-redir as a non-root user on BSD; starting via systemd without sufficient capabilities; /dev/pf restricted to group _pf or root; pf device not mounted in a jail/container.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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