背景: 接手别人的项目,添加子网时对子网所有地址进行 ping 测试
构造子网地址和广播地址 socket 连接时,会报PermissionError: [Errno 13] Permission denied的错误.
关于为什么要上子网地址和广播地址我也不清楚(代码专门拼接了这两个地址,这两者和对子网所有地址进行 ping 不是重复了吗)
所有,子网地址和广播地址和应该怎么构造 icmp 的包和建立 socket 连接?

背景: 接手别人的项目,添加子网时对子网所有地址进行 ping 测试
构造子网地址和广播地址 socket 连接时,会报PermissionError: [Errno 13] Permission denied的错误.
关于为什么要上子网地址和广播地址我也不清楚(代码专门拼接了这两个地址,这两者和对子网所有地址进行 ping 不是重复了吗)
所有,子网地址和广播地址和应该怎么构造 icmp 的包和建立 socket 连接?
ping普通地址无权限问题
附一下代码
def init_icmp_packet(sequence): # 把字节打包成二进制数据 data_type = 8 # ICMP Echo Request data_code = 0 # must be zero data_checksum = 0 # "...with value 0 substituted for this field..." data_ID = process_id # Identifier payload = b'abcdefghijklmnopqrstuvwabcdefghi' # data icmp_packet = struct.pack('>BBHHH32s', data_type, data_code, data_checksum, data_ID, sequence, payload) icmp_checksum = check_sum(icmp_packet) # 获取校验和 icmp_packet = struct.pack('>BBHHH32s', data_type, data_code, icmp_checksum, data_ID, sequence, payload) return icmp_packet def init_raw_socket(ip_addr, icmp_packet): raw_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, 1) # 服务端设置非阻塞 # raw_socket.setblocking(False) raw_socket.sendto(icmp_packet, (ip_addr, 1)) # 报错行 return raw_socket 问题已解决.附上解决后的代码:
def init_raw_socket(ip_addr, icmp_packet): raw_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, 1) raw_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) # 解决问题的代码,允许发送广播数据 # 服务端设置非阻塞 # raw_socket.setblocking(False) raw_socket.sendto(icmp_packet, (ip_addr, 1)) return raw_socket 关于setsockopt方法的用法及参数的含义参考这里
1 keakon Apr 17, 2023 socket.SOCK_RAW 需要 root 权限,你加个 sudo 试试 |
2 yougg Apr 17, 2023 |
3 artnowben Apr 17, 2023 构建 icmp 报文请参考一下 测试仪项目 dperf https://github.com/baidu/dperf 具体代码: 1. raw socket 参考 https://github.com/pengjianzhang/tcping/blob/main/tcping.c 2. icmp 封装参考 https://github.com/baidu/dperf/blob/main/src/icmp.c |
4 julyclyde Apr 17, 2023 建议还是先学学网络的基本原理,搞明白掩码到底是做啥用的 再处理权限问题 |
5 shxxy Apr 17, 2023 楼上提到需要 root 权限,其实从内核 2.2 开始就可以单独设置这些权限。你可以用用 sudo setcap cap_net_raw+p PROGRAM 赋予你程序 socket_row 的能力 |
7 shxxy Apr 17, 2023 @julyclyde #6 +是添加,和 chmod 里的+-=有点像 https://man7.org/linux/man-pages/man3/cap_from_text.3.html#TEXTUAL_REPRESENTATION eip 是三个文件属性,有点像 rwx 这种 https://man.archlinux.org/man/capabilities.7#File_capabilities |
8 bulay OP |
9 qbqbqbqb Apr 17, 2023 子网地址是不能用作目标地址的 广播地址可以,但是如果要用广播地址作为目标地址的话,需要用 setsockopt 给 socket 加上 SO_BROADCAST 属性 |
10 bulay OP @qbqbqbqb 感谢大佬!就是这个问题. 另外,子网地址确实可以 ping 通.用 linux 的命令`ping -b`也是可以用子网地址作为目标地址的 |
11 julyclyde Apr 18, 2023 你这个功能是新加的?? 我还以为接手的时候已经有这个了 |