我在Wireshark上看到一些广播数据包,我希望能够使用一个简单的Linux命令行实用程序来检查。它看起来像这样:
getsenders bcast_IP port timeout
,它将简单地打印在超时期间遇到的每个新发送方IP。
例如:getsenders 192.168.0.255 12345 0.150
和(或者)
getsenders 192.168.0.0/8 12345 0.150
将监听发送到192.168.0.255:12345的广播数据包,然后打印遇到的每个唯一发送者。另一种方法是列出指定接口上的所有广播发送者。
不幸的是,我的socket-fu很弱。我所知道的是,程序必须以root权限(suid)运行才能监听广播套接字。
我已经花了很多时间(天)尝试从Python中完成此操作,但看起来该路由将需要使用原始套接字并解析数据包(数据包嗅探器,呸!)。我也考虑过使用socat/netcat(通过一个只能执行的suid bash脚本),但也一无所获。
是否有一些简单的Linux代码可以为我做这件事?我不关心工具或源语言是什么,只要它可以设置为suid-root并从命令行运行即可。
顺便说一句,我有一个简单的Python解决方案,在MS Windows下工作,但在Linux下死亡:
myip = <IP address of local interface to listen on>
p = <broadcast port>
timeout = 0.150 # 150 ms
addresses = {}
if "windows" in sys.platform.tolower():
# Create the broadcast reception socket
bsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
bsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
bsock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
bsock.settimeout(timeout)
bsock.bind((myip, p))
while True: # Look for all senders
try:
__, address = bsock.recvfrom(1024) # Don't care about payload
except BaseException, e:
break # Nothing found
else: # A desired broadcast packet was detected
if address[0] not in addresses:
addresses[address[0]] = 1
else:
addresses[address[0]] += 1
if addresses[address[0]] >= 3:
break # Go until timeout or any sender is seen 3 times
finally:
bsock.close()
bsock = None
print(', '.join([k for k in addresses]))
在下载并测试了许多示例之后,我终于使其工作,然后将代码对分并组合,直到我在两个平台上都能工作的最小差异。
它归结为只有一行:Linux必须绑定到特定的广播地址(作为根用户),Windows可以绑定到本地接口地址(作为普通用户),广播数据包预计将到达。
下面是修改后的代码片段:
bcast_addr = <IP addr of broadcast: Must end with at least one '.255'>
myip = <IP addr of local interface receiving from bcast_addr>
p = <broadcast port>
timeout = 0.150 # 150 ms
addresses = {}
# Create the broadcast reception socket
bsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
bsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
bsock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
bsock.settimeout(timeout)
if "windows" in sys.platform.tolower():
bsock.bind((myip, p))
elif os.getuid() == 0: # Must be root for Linux!
bsock.bind((bcast_addr, p))
while True: # Look for all senders
try:
__, address = bsock.recvfrom(1024) # Don't care about payload
except BaseException, e:
break # Nothing found
else: # A desired broadcast packet was detected
if address[0] not in addresses:
addresses[address[0]] = 1
else:
addresses[address[0]] += 1
if addresses[address[0]] >= 3:
break # Go until timeout or any sender is seen 3 times
finally:
bsock.close()
bsock = None
print(', '.join([k for k in addresses]))