"[Errno 1]不允许操作"创建套接字时 [英] "[Errno 1] Operation not permitted" when creating socket

查看:519
本文介绍了"[Errno 1]不允许操作"创建套接字时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用DigiKey针对其Amazon Dash Button hack制作的程序来监视按钮被按下的时间,然后将HTTP GET发送到IFTTT.我正在使用Raspberry Pi来运行它.来源:

I am trying to use the program DigiKey have made for their Amazon Dash Button hack to monitor for when the button is pressed and then send a HTTP GET to IFTTT. I am using a Raspberry Pi to run this. Source:

import socket
import struct
import binascii
import time
import json
import urllib2

# Use your own IFTTT key
ifttt_key = 'example_key'
# Set these up at https://ifttt.com/maker
ifttt_url_button = 'https://maker.ifttt.com/trigger/button_pressed/with/key/' + ifttt_key

# Replace this MAC addresses and nickname with your own
macs = {
    'xxxxxxxxxxxx' : 'vanish'
}

# Trigger a IFTTT URL. Body includes JSON with timestamp values.
def trigger_url(url):
    data = '{ "value1" : "' + time.strftime("%Y-%m-%d") + '", "value2" : "' + time.strftime("%H:%M") + '" }'
    req = urllib2.Request(url, data, {'Content-Type': 'application/json'})
    f = urllib2.urlopen(req)
    response = f.read()
    f.close()
    return response

def button_pressed():
    print 'triggering button event, response:' + trigger_url(ifttt_url_button)

rawSocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.htons(0x0003))

while True:
    packet = rawSocket.recvfrom(2048)
    ethernet_header = packet[0][0:14]
    ethernet_detailed = struct.unpack("!6s6s2s", ethernet_header)
    # skip non-ARP packets
    ethertype = ethernet_detailed[2]
    if ethertype != '\x08\x06':
        continue
    # read out data
    arp_header = packet[0][14:42]
    arp_detailed = struct.unpack("2s2s1s1s2s6s4s6s4s", arp_header)
    source_mac = binascii.hexlify(arp_detailed[5])
    source_ip = socket.inet_ntoa(arp_detailed[6])
    dest_ip = socket.inet_ntoa(arp_detailed[8])
    if source_mac in macs:
        #print "ARP from " + macs[source_mac] + " with IP " + source_ip
        if macs[source_mac] == 'vanish':
            button_pressed()
    else:
        print "Unknown MAC " + source_mac + " from IP " + source_ip 

我收到的错误是:

Traceback (most recent call last):
  File "/home/pi/Desktop/dash_btn.py", line 30, in <module>
    rawSocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.htons(0x0003))
  File "/usr/lib/python2.7/socket.py", line 187, in __init__
    _sock = _realsocket(family, type, proto)
error: [Errno 1] Operation not permitted

我尝试使用sudo在终端中运行它,但是它没有任何改变.帮助将不胜感激.

I have tried running it in the terminal with sudo , but it hasn't changed anything. Help would be appreciated.

推荐答案

由于您希望接收和解析 ARP 数据包(位于通过AF_INET接收到的IP级别以下的链路层,OSI层2上),您必须使用低层数据包接口AF_PACKET.

Since you wish to receive and parse ARP packets (which are on a link layer, OSI layer 2, below IP level you receive with AF_INET), you'll have to use the low-level packet interface, AF_PACKET.

man packet(对于AF_PACKET套接字):

对于包含链接级头的原始数据包,套接字类型为 SOCK_RAW ,对于具有以下内容的煮熟数据包,套接字类型为SOCK_DGRAM 链接级标头已删除.链接级头信息以sockaddr_ll结构的通用格式提供. protocol是网络字节顺序的IEEE 802.3协议编号.有关允许的协议列表,请参见<linux/if_ether.h>包含文件. 将协议设置为htons(ETH_P_ALL)时,将接收所有协议.所有传入 该协议类型的数据包在传递到内核中实现的协议之前,将先传递到数据包套接字.

The socket_type is either SOCK_RAW for raw packets including the link-level header or SOCK_DGRAM for cooked packets with the link-level header removed. The link-level header information is available in a common format in a sockaddr_ll structure. protocol is the IEEE 802.3 protocol number in network byte order. See the <linux/if_ether.h> include file for a list of allowed protocols. When protocol is set to htons(ETH_P_ALL), then all protocols are received. All incoming packets of that protocol type will be passed to the packet socket before they are passed to the protocols implemented in the kernel.

因此,要嗅探ARP数据包,必须使用SOCK_RAW套接字类型.但是,要使用它,请使用man 7 raw:

So, for sniffing ARP packets, you must use SOCK_RAW socket type. However, to use it, from man 7 raw:

仅允许有效用户ID为0或CAP_NET_RAW功能的进程打开原始套接字.

Only processes with an effective user ID of 0 or the CAP_NET_RAW capability are allowed to open raw sockets.

因此,您必须使用sudo运行程序.

therefore, you'll have to run your program with sudo.

对于套接字协议(第三个参数),您可以选择现有的0x0003,这表示ETH_P_ALL接收所有软件包,或者可能更好,ETH_P_ARP的值为0x0806(请参阅您的/usr/include/linux/if_ether.h)接收仅ARP 软件包.

For socket protocol (third parameter) you might choose 0x0003 as you already have, which means ETH_P_ALL, receiving all packages, or probably better, ETH_P_ARP which has a value of 0x0806 (see your /usr/include/linux/if_ether.h) to receive only ARP packages.

总的来说,这看起来像这样:

All taken together, this looks like this:

rawSocket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0806))

while True:
    packet = rawSocket.recvfrom(2048)
    # no need to filter-out ARP
    # less load on user program

这篇关于"[Errno 1]不允许操作"创建套接字时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆