Skip to content

Conversation

@Sharif-bot-cmd
Copy link

Pull Request: Non-Root Fallback Backend for Scapy

Overview

This PR introduces a non-root fallback backend for Scapy, allowing basic send and sniff functionality on systems without root privileges.

Currently, Scapy requires raw sockets for full L3 access, which fails on non-root environments. This PR provides:

  • NonRootL3Socket: a UDP-based emulation of L3 send/receive.
  • sniff_nonroot(): non-root compatible packet capture.
  • Automatic backend hook: Scapy falls back to non-root mode if root is unavailable.
  • Optional sudo usage: full functionality works if root privileges are present.

This enables Scapy to work in restricted environments, such as:

  • Standard user accounts on Linux with or without sudo.
  • Docker containers with limited capabilities.
  • Educational environments or CI systems where root access is not allowed.

Implementation Details

  • File Added: scapy/arch/linux/nonroot_backend.py
  • Hooked in: scapy/all.py
  • Tests: tests/test_nonroot.py

Key Features:

  1. NonRootL3Socket

    • Uses UDP sockets to emulate L3 packet sending/receiving.
    • Provides .send(pkt) and .recv(timeout) methods compatible with Scapy.
    • Threaded listener for asynchronous packet capture.
  2. Non-root Sniffer

    • sniff_nonroot() provides a drop-in alternative for sniff() in non-root mode.
    • Supports count, timeout, and debug logging.
  3. Automatic Hook

    • enable_nonroot_backend() automatically sets Scapy’s conf.L3socket to NonRootL3Socket if root is not detected.
    • Uses os.geteuid() when available to detect root privileges.
  4. Graceful Fallback

    • If raw sockets fail, no crash occurs.
    • Logs a clear message when running in non-root mode.

Usage Example

from scapy.all import *

# Root is optional; if not root, non-root backend is used automatically
pkt = IP(dst="127.0.0.1") / UDP(dport=55555) / Raw(load="Hello NonRoot")
s = conf.L3socket(port=55555)
s.send(pkt)

pkts = sniff(count=1, timeout=2)
for p in pkts:
    print(p.summary())

Expected Output (non-root mode):

[*] Non-root fallback active
[IP / UDP 127.0.0.1:55555 > 127.0.0.1:55555 / Raw Hello NonRoot]

Testing Instructions

  1. Clone your fork and checkout the nonroot-backend branch.
  2. Run the included test script:
python3 tests/test_nonroot.py
  1. Verify that packets are sent and received correctly on 127.0.0.1.
  2. Optionally, test with root (sudo) to confirm full Scapy functionality.

Benefits

  • Expands Scapy’s usability to non-root environments.
  • Maintains backward compatibility with root-based L3 sockets.
  • Provides a safe, predictable fallback for CI/CD pipelines, educational setups, and restricted containers.

Notes for Reviewers

  • UDP-based emulation does not provide full raw L3 capabilities; intended as a compatibility fallback.
  • All methods (send, recv, sniff) mimic standard Scapy behavior wherever possible.
  • Additional testing on different Linux distros and Python versions is recommended.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant