Question

I'm trying to learn a bit of packet generation with scapy. It looks pretty cool. Following some documentation I'm doing this:

l3=IP(dst="192.168.0.1", src="192.168.0.2", tos=(46 << 2))

But only to get the error message of:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/lib/python2.7/dist-packages/scapy/sendrecv.py", line 251, in send
    __gen_send(conf.L3socket(*args, **kargs), x, inter=inter, loop=loop, count=count,verbose=verbose, realtime=realtime)
  File "/usr/lib/python2.7/dist-packages/scapy/arch/linux.py", line 307, in __init__
    self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
  File "/usr/lib/python2.7/socket.py", line 187, in __init__
    _sock = _realsocket(family, type, proto)
error: [Errno 1] Operation not permitted

Running scapy as root solved the problem. But that's not what I wanted. Is it because normal user can't create RAW socket? If so, is there a solution?

Was it helpful?

Solution

Scapy needs root privileges to create raw sockets because it uses the Python socket library. Raw sockets are only allowed to used "with an effective user ID of 0 or the CAP_NET_RAW capability" according to the Linux raw man pages.

I can't find what looks to be reliable documentation on setting the CAP_NET_RAW capability, but if you are looking to a work around to running Scapy scripts that user raw sockets without root, that is what you need to do.

OTHER TIPS

To run Scapy with just cap_net_raw privilege...

The safest and less complicated way I know is, in order:

  1. Make a personal copy of the python binary:

    $ sudo cp /usr/bin/python2.7 ~/python_netraw

  2. Own it:

    $ sudo chown your user name ~/python_netraw

  3. Don't let anybody else run it:

    $ chmod -x,u+x ~/python_netraw

  4. Give it cap_net_raw capability:

    $ sudo setcap cap_net_raw=eip /usr/bin/python_netraw

  5. Run scapy with it:

    $ ~/python_netraw -O /usr/bin/scapy

(Or use sudo each time you need to run Scapy with raw privileges.)

A dirty approach, possibly insecure: Directly give CAP_NET_RAW capability to Python:

sudo setcap cap_net_raw=eip $(readlink -f $(which python))

To run a temporary python environment (like for scapy) with cap_net_raw I found this works:

sudo -E capsh --caps="cap_setpcap,cap_setuid,cap_setgid+ep cap_net_raw+eip" --keep=1 --user="$USER" --addamb="cap_net_raw" -- -c /usr/bin/python3

adapted from the Arch Wiki

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top