我正在尝试使用DigiKey针对其Amazon Dash Button hack制作的程序来监视按钮被按下的时间,然后将HTTP GET发送到IFTTT。我正在使用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在终端中运行它,但是它并没有改变任何东西。帮助将不胜感激。
最佳答案
由于您希望接收和解析ARP数据包(位于AF_INET
接收到的IP级别以下的链路层OSI层2上),因此必须使用低级数据包接口(interface)AF_PACKET
。
从man packet
(用于AF_PACKET
套接字):
因此,要嗅探ARP数据包,必须使用SOCK_RAW
套接字类型。但是,要使用它,请从man 7 raw
:
因此,您必须使用sudo
运行程序。
对于套接字协议(protocol)(第三个参数),您可以选择已经拥有的0x0003
,这意味着ETH_P_ALL
,接收所有软件包的,或者可能更好,具有ETH_P_ARP
值的0x0806
(请参阅/usr/include/linux/if_ether.h
),仅接收 ARP 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