Repository navigation
UDP relay fails with "Operation not permitted (os error 1)" when sending response back to client #2139
Description
Activity
The error was reported from these lines of codes:
.shadowsocks-rust/crates/shadowsocks-service/src/server/udprelay.rs
Lines 749 to 762 in 8a57e09
match self.inbound.send_to(self.peer_addr, &addr, data).await { Err(err) => { warn!( "udp failed to send back {} bytes to client {}, from target {}, error: {}", data.len(), self.peer_addr, addr, err ); } _ => { trace!("udp relay {} <- {} with {} bytes", self.peer_addr, addr, data.len()); } } sendmsgreturnsEPERM? WHY?In Linux, a UDP socket sendmsg (or sendto) returning EPERM (Operation not permitted) means that the local kernel or network subsystem explicitly blocked the packet from leaving the machine.
Here are the most common causes and how to troubleshoot them:1. Firewall (iptables / nftables) Rules
This is the most frequent cause. If a local firewall rule in the OUTPUT chain is set to DROP or REJECT a packet matching your target IP, port, or protocol, the Linux kernel immediately reports EPERM to the application instead of dropping it silently.
- How to check:
Inspect your active firewall rules for any blocks on your target destination or UDP traffic:
sudo iptables -L OUTPUT -n -v# or for nftables
sudo nftables list ruleset2. Connection Tracking (conntrack) Failures
The Netfilter connection tracking module (nf_conntrack) manages states for network traffic. Under high UDP loads, if the conntrack table becomes full, or if certain application layer gateways (ALGs, like SIP or DNS helpers) encounter out-of-order packets, the kernel might drop the packet internally and throw an EPERM error.
- How to check:
Look through your system kernel logs for conntrack drop messages:
dmesg | grep -i conntrack# or check /var/log/syslog
- Workaround:
If high load on a specific port is causing the issue, you can bypass connection tracking for that traffic:
sudo iptables -t raw -I OUTPUT -p udp --dport -j NOTRACK
3. SELinux or AppArmor Policy Denials
Mandatory Access Control (MAC) systems like SELinux or AppArmor can restrict applications from binding to or sending data out of specific ports, sockets, or network domains. If permission is denied, EPERM is returned.
- How to check:
- SELinux: Check for AVC denied messages in /var/log/audit/audit.log.
- AppArmor: Check /var/log/syslog or /var/log/messages for AppArmor denial events.
4. IP Spoofing and Source Address Validation
If your code uses ancillary data (like IP_PKTINFO) to manually set a source IP address, and that IP does not belong to any local network interface, the kernel's routing security mechanisms may intercept the packet as spoofed and return EPERM.
To narrow down the exact root cause, please let me know:
- Is this error happening consistently on every single call, or does it only happen intermittently under high load?
- Are there any matching error logs in dmesg at the exact timestamp the application encounters EPERM?
- How to check:
Had the same issue in Russia. What solved it was tunneling through a protocol that randomises packet sizes. Took some trial and error. There are services that do this out of the box now (ubivpn is one I know).
UDP relay fails with "Operation not permitted (os error 1)" when sending response back to client
Describe the Bug
TCP works normally, but UDP relay does not.
The server successfully receives UDP packets from clients and also receives responses from upstream servers (for example DNS responses from 1.0.0.1:53), but fails when sending the UDP response back to the client.
The log repeatedly shows:
From the log, it appears that:
TCP traffic works normally.
Steps to reproduce
ssserverwith UDP enabled.Expected behavior
UDP relay should work normally.
The server should forward UDP responses back to the client instead of reporting:
Actual behavior
The server receives upstream responses successfully but fails to send them back to the client.
Logs
Environment
Configuration:
{ "server": "::", "server_port": 9999, "mode": "tcp_and_udp", "method": "chacha20-ietf-poly1305" }Also tested with:
{ "server": "0.0.0.0" }but the issue remains.
Additional Information
Verified:
::to0.0.0.0does not help.The issue seems to happen only when ssserver attempts to send the UDP response back to the client.
Is this a known issue with UDP relay on Linux/OpenWrt, or could additional debugging information help identify the cause?