slackhq/nebula · error
SO_REUSEPORT failed: %v
Error message
SO_REUSEPORT failed: %v
What it means
On Android, nebula's UDP listen path sets SO_REUSEPORT on the socket fd via the net.ListenConfig Control hook so multiple sockets can bind the same port. If syscall.SetsockoptInt fails, the error is wrapped as 'SO_REUSEPORT failed'. This typically reflects a kernel or SELinux restriction rather than application misuse.
Source
Thrown at udp/udp_android.go:26
"log/slog"
"net"
"syscall"
"golang.org/x/sys/unix"
)
func NewListener(l *slog.Logger, s Settings) (Conn, error) {
return NewGenericListener(l, s)
}
func NewListenConfig(multi bool) net.ListenConfig {
return net.ListenConfig{
Control: func(network, address string, c syscall.RawConn) error {
if multi {
var controlErr error
err := c.Control(func(fd uintptr) {
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil {
controlErr = fmt.Errorf("SO_REUSEPORT failed: %v", err)
return
}
})
if err != nil {
return err
}
if controlErr != nil {
return controlErr
}
}
return nil
},
}
}
func (u *GenericConn) Rebind() error {
return nil
}View on GitHub (pinned to dd8f660c0a)
Solutions
- Update the device/OS to a kernel >= 3.9 that supports SO_REUSEPORT
- Check SELinux denials (dmesg / adb logcat for avc denied) and adjust the policy or run in permissive mode for testing
- Run with multi=false if lightfire/multiple-socket binding is not needed, so the socket option is skipped
- Verify the error value (permission denied vs invalid argument) to target the actual restriction
Defensive patterns
Strategy: fallback
Validate before calling
// Before relying on multi-socket binding, confirm kernel support: // grep -q SO_REUSEPORT /proc/kallsyms 2>/dev/null || uname -r (require >= 3.9) // On Android also check `adb shell getenforce` for SELinux enforcing mode
Try / catch
ln, err := listenUDP(lc, "0.0.0.0:0")
if err != nil {
if strings.Contains(err.Error(), "SO_REUSEPORT failed") {
// fall back to a single socket (multi=false) or surface a device/kernel requirement
return listenSingle()
}
return err
} Prevention
- Target devices with kernel >= 3.9 where SO_REUSEPORT exists
- Review SELinux policy for socket option denials before shipping to hardened ROMs
- Set multi=false when concurrent UDP listeners on the same port are not required
- Capture the wrapped errno in logs to distinguish permission-denied from invalid-argument
When it happens
Trigger: Creating a UDP listener with multi=true on Android when setsockopt(SOL_SOCKET, SO_REUSEPORT) returns an error — e.g. kernel lacking SO_REUSEPORT support, permission denied from SELinux policy, or fd validity issues.
Common situations: Running nebula on very old Android kernels (<3.9) without SO_REUSEPORT; hardened SELinux policies blocking socket options; custom ROMs with restricted network syscalls.
Related errors
- no outside connection
- ErrInvalidIPv6RemoteForSocket
- could not initialize winrio
- ErrPeerRejected
- ErrHeaderTooShort
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/ace17a8d230fdfee.
Report an issue: GitHub.