2014-03-24 21 views
0

我在Wireshark上看到了一些广播数据包,我希望能够使用希望成为简单的Linux命令行实用程序的东西进行检查。它看起来像这样:如何获取所需广播地址的发件人IP:端口组合?

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的解决方案,微软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])) 
+0

忘了提,我还添加了一个别名接口与广播地址的子网的IP地址。所以,如果我看到数据包发送到192.168.0.155,我会添加一个免费地址范围192.168.0.1到192.168.0.254的别名。 – BobC

+0

你有什么问题? recvfrom()提供发件人地址。其余的只是编程。 – EJP

+0

我的不好:我应该强调我需要一个跨平台的解决方案,至少可以在Windows 7和Linux上运行。问题是绑定会失败,或者即使数据包到达接口也不会收到任何数据。 – BobC

回答

0

下载和测试的许多例子之后,我终于得到了它的工作,然后一分为二并结合代码,直到我在两个平台上都有很小的差别。

它只涉及到一行:Linux必须绑定到特定的广播地址(以root身份),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])) 
+0

这是少数我认为Windows可能比Linux做得更好的案例之一。虽然混杂接口和完全广播绑定(255.255.255.255)可能完全限制为root,但应允许普通用户绑定到受限广播地址(其中至少第一个八位字节不是255)。 – BobC