diff --git a/pkg/synapse.service b/pkg/synapse.service index 1624e92..dc4aa41 100644 --- a/pkg/synapse.service +++ b/pkg/synapse.service @@ -41,16 +41,14 @@ Group=root NoNewPrivileges=false PrivateTmp=false -# File system access - minimal restrictions for XDP/BPF +# File system access - disabled for XDP/BPF compatibility +# ReadWritePaths/ReadOnlyPaths create mount namespaces that fail if /sys/fs/bpf doesn't exist ProtectSystem=false ProtectHome=false -# XDP/BPF requires access to /sys/fs/bpf and network interfaces -ReadWritePaths=/var/log/synapse /var/run /var/lib/synapse /etc/synapse/certs /sys/fs/bpf -ReadOnlyPaths=/sys/class/net /sys/devices /proc/sys/net -# Capabilities (required for XDP/BPF) -AmbientCapabilities=CAP_NET_ADMIN CAP_SYS_ADMIN CAP_BPF CAP_NET_BIND_SERVICE -CapabilityBoundingSet=CAP_NET_ADMIN CAP_SYS_ADMIN CAP_BPF CAP_NET_BIND_SERVICE +# Capabilities (required for XDP/BPF and iptables) +AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW CAP_SYS_ADMIN CAP_BPF CAP_NET_BIND_SERVICE +CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_RAW CAP_SYS_ADMIN CAP_BPF CAP_NET_BIND_SERVICE # Network - must have full network access for XDP PrivateNetwork=false diff --git a/src/firewall/nftables.rs b/src/firewall/nftables.rs index 92794d3..f2473e6 100644 --- a/src/firewall/nftables.rs +++ b/src/firewall/nftables.rs @@ -137,8 +137,19 @@ table inet {table} {{ if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); - log::error!("Failed to initialize nftables: {}", stderr); - return Err(format!("Failed to initialize nftables: {}", stderr).into()); + + // Check for common error patterns and provide user-friendly messages + if stderr.contains("Operation not supported") { + log::debug!("nftables kernel support not available: {}", stderr); + return Err("nftables kernel support not available (Operation not supported) - this is common in containers or systems without nf_tables kernel module".into()); + } else if stderr.contains("Permission denied") { + return Err("nftables permission denied - ensure synapse runs as root with CAP_NET_ADMIN".into()); + } else if stderr.contains("No such file or directory") { + return Err("nftables failed - nft command or required files not found".into()); + } else { + log::debug!("nftables initialization failed: {}", stderr); + return Err(format!("nftables initialization failed: {}", stderr.lines().next().unwrap_or("unknown error")).into()); + } } Ok(()) diff --git a/src/main.rs b/src/main.rs index 8bf3c9e..b4efd98 100644 --- a/src/main.rs +++ b/src/main.rs @@ -261,6 +261,9 @@ async fn async_main(args: Args, config: Config) -> Result<()> { if config.network.disable_xdp { log::warn!("XDP disabled by config, will use nftables fallback"); } else { + // Suppress libbpf output - errors will be handled gracefully with fallback to nftables/iptables + libbpf_rs::set_print(None); + for iface in &iface_names { let boxed_open: Box> = Box::new(MaybeUninit::uninit()); let open_object: &'static mut MaybeUninit = Box::leak(boxed_open);