python局域网数据包监听_监听UDP数据包的Python原始套接字;仅接收到一半的数据包...

我正试图在Python中创建一个仅侦听UDP数据包的raw套接字:import socket

s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP)

s.bind(('0.0.0.0', 1337))

while True:

print s.recvfrom(65535)

这需要以根用户身份运行,并在端口1337上创建一个原始套接字,该套接字侦听UDP数据包并在接收到它们时打印它们;没有问题。

现在让我们制作一个小客户端来测试这是否有效:import socket

c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

c.connect(('127.0.0.1', 1337))

c.send('message 1')

c.send('message 2')

c.send('message 3')

c.send('message 4')

c.send('message 5')

c.send('message 6')

始终只有第一条、第三条和第五条消息(message 1、message 3和message 5)可以通过并在服务器输出中打印。第二、第四和第六条消息不会显示在服务器输出上,相反,客户端会收到一个异常:>>> c.send('message 2')

Traceback (most recent call last):

File "", line 1, in

socket.error: [Errno 111] Connection refused

在Wireshark中运行此命令表明它正在收到“无法到达目标”的ICMP回复。我已经能够在3台不同的机器上重现这一点(尽管它们都运行Linux)。我遗漏了什么吗?由于使用UDP的协议应该能够容忍数据包丢失,UDP是否会一直丢弃数据包?即便如此,为什么在本地接口上发送数据包时会丢弃?

将服务器绑定到127.0.0.1而不是0.0.0.0具有相同的结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个例子,展示如何使用Python原始套接字构造一个有IP头部、UDP头部、TCP头部、DNS头部和ICMP头部的数据包: ```python import socket import struct # IP头部 ip_version = 4 ip_header_length = 5 ip_tos = 0 ip_total_length = 0 # 后面计算 ip_id = 54321 ip_frag_offset = 0 ip_ttl = 255 ip_protocol = socket.IPPROTO_UDP # 或者socket.IPPROTO_TCP ip_checksum = 0 # 后面计算 ip_src = socket.inet_aton('192.168.0.1') ip_dst = socket.inet_aton('192.168.0.2') ip_header = struct.pack('!BBHHHBBH4s4s', (ip_version << 4) + ip_header_length, ip_tos, ip_total_length, ip_id, (ip_frag_offset << 13), ip_ttl, ip_protocol, ip_checksum, ip_src, ip_dst) # UDP头部 udp_src_port = 1234 udp_dst_port = 5678 udp_length = 0 # 后面计算 udp_checksum = 0 # 后面计算 udp_header = struct.pack('!HHHH', udp_src_port, udp_dst_port, udp_length, udp_checksum) # TCP头部 tcp_src_port = 1234 tcp_dst_port = 5678 tcp_seq_num = 1000 tcp_ack_num = 0 tcp_header_length = 5 tcp_flags = 0x02 # SYN标志 tcp_window_size = socket.htons(5840) tcp_checksum = 0 # 后面计算 tcp_urgent_pointer = 0 tcp_header = struct.pack('!HHLLBBHHH', tcp_src_port, tcp_dst_port, tcp_seq_num, tcp_ack_num, (tcp_header_length << 4), tcp_flags, tcp_window_size, tcp_checksum, tcp_urgent_pointer) # DNS头部 dns_id = 1234 dns_flags = 0 dns_questions = 1 dns_answers = 0 dns_authority_rrs = 0 dns_additional_rrs = 0 dns_header = struct.pack('!HHHHHH', dns_id, dns_flags, dns_questions, dns_answers, dns_authority_rrs, dns_additional_rrs) # ICMP头部 icmp_type = 8 # Echo请求 icmp_code = 0 icmp_checksum = 0 # 后面计算 icmp_id = 1234 icmp_seq_num = 1 icmp_data = b'Hello, World!' icmp_header = struct.pack('!BBHHH', icmp_type, icmp_code, icmp_checksum, icmp_id, icmp_seq_num) # 构造数据包 payload = b'' # 将所有头部和负载拼接在一起 packet = ip_header + udp_header + tcp_header + dns_header + icmp_header + payload # 计算IP头部和UDP头部的长度 ip_length = ip_header_length * 4 + len(packet) udp_length = len(packet) - (ip_header_length * 4) # 重新打包IP头部和UDP头部,更新长度字段 ip_header = struct.pack('!BBHHHBBH4s4s', (ip_version << 4) + ip_header_length, ip_tos, ip_length, ip_id, (ip_frag_offset << 13), ip_ttl, ip_protocol, ip_checksum, ip_src, ip_dst) udp_header = struct.pack('!HHHH', udp_src_port, udp_dst_port, udp_length, udp_checksum) # 计算IP头部和UDP头部的校验和 pseudo_header = struct.pack('!4s4sBBH', ip_src, ip_dst, 0, ip_protocol, udp_length) pseudo_header_checksum = 0 for i in range(0, len(pseudo_header), 2): pseudo_header_checksum += (pseudo_header[i] << 8) + pseudo_header[i + 1] while pseudo_header_checksum > 0xffff: pseudo_header_checksum = (pseudo_header_checksum & 0xffff) + (pseudo_header_checksum >> 16) udp_header_checksum = pseudo_header_checksum for i in range(0, len(udp_header), 2): udp_header_checksum += (udp_header[i] << 8) + udp_header[i + 1] while udp_header_checksum > 0xffff: udp_header_checksum = (udp_header_checksum & 0xffff) + (udp_header_checksum >> 16) udp_header_checksum = ~udp_header_checksum & 0xffff # 更新UDP头部中的校验和字段 udp_header = struct.pack('!HHHH', udp_src_port, udp_dst_port, udp_length, udp_header_checksum) # 计算IP头部的校验和 ip_checksum = 0 for i in range(0, len(ip_header), 2): ip_checksum += (ip_header[i] << 8) + ip_header[i + 1] while ip_checksum > 0xffff: ip_checksum = (ip_checksum & 0xffff) + (ip_checksum >> 16) ip_checksum = ~ip_checksum & 0xffff # 更新IP头部中的校验和字段 ip_header = struct.pack('!BBHHHBBH4s4s', (ip_version << 4) + ip_header_length, ip_tos, ip_length, ip_id, (ip_frag_offset << 13), ip_ttl, ip_protocol, ip_checksum, ip_src, ip_dst) # 发送数据包 s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW) s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) s.sendto(packet, ('192.168.0.2', 0)) ``` 请注意,使用Python原始套接字构造数据包需要管理员权限。此外,构造数据包时需要注意各个头部字段的值和长度,以及各个头部的校验和计算方法。如果头部或校验和计算错误,数据包可能无法成功发送或被接收方丢弃。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值