如何获得所需广播地址的发送方IP:端口组合



我在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]))

最新更新