【问题标题】:"[Errno 1] Operation not permitted" when creating socket创建套接字时出现“[Errno 1] Operation not allowed”
【发布时间】:2017-07-16 10:45:26
【问题描述】:

我正在尝试使用 DigiKey 为他们的 Amazon Dash Button hack 制作的程序来监控按钮何时被按下,然后向 IFTTT 发送 HTTP GET。我正在使用 Raspberry Pi 来运行它。来源:

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 在终端中运行它,但它没有改变任何东西。帮助将不胜感激。

【问题讨论】:

    标签: python python-2.7 sockets network-programming arp


    【解决方案1】:

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

    来自man packet(用于AF_PACKET 套接字):

    socket_type 是 SOCK_RAW 用于包含链路级标头的原始数据包SOCK_DGRAM 用于带有 删除了链接级标头。链接级标头信息以sockaddr_ll 结构中的通用格式提供。协议是网络字节顺序的 IEEE 802.3 协议号。有关允许的协议列表,请参阅 &lt;linux/if_ether.h&gt; 包含文件。 如果协议设置为htons(ETH_P_ALL),则接收所有协议。所有传入 该协议类型的数据包将在传递给内核中实现的协议之前传递给数据包套接字。

    所以,要嗅探 ARP 数据包,您必须使用SOCK_RAW 套接字类型。但是,要使用它,来自man 7 raw

    只有有效用户 ID 为 0 或具有 CAP_NET_RAW 能力的进程才能打开原始套接字。

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

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

    综合来看,是这样的:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-23
      • 1970-01-01
      • 2014-07-18
      • 2021-03-08
      • 1970-01-01
      • 2018-05-29
      • 2016-01-05
      相关资源
      最近更新 更多