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

时间:2014-03-24 20:15:35

标签: linux udp broadcast

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

1 个答案:

答案 0 :(得分: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]))