IP段端口扫描遍历时报TypeError:需字符串/缓冲区却传入IPv4Address
解决
TypeError: coercing to Unicode: need string or buffer, IPv4Address found端口扫描问题 这个问题我之前做网段扫描的时候也踩过坑,本质原因很简单:你用ipaddress模块生成的IP对象,没办法直接传给socket的接口——socket.connect_ex()需要的是字符串格式的IP地址,而ipaddress返回的是IPv4Address类的实例,类型不匹配就触发了这个错误。
错误原因拆解
当你遍历ipaddress.IPv4Network生成的网段时,每个元素都是IPv4Address对象,比如:
for ip in ipaddress.IPv4Network('192.168.1.0/24'): print(type(ip)) # 输出 <class 'ipaddress.IPv4Address'>
而socket的connect_ex((host, port))要求host必须是字符串或者字节流,直接传对象自然会报错。
两种解决方案
方案1:调用扫描函数时转成字符串
在遍历网段、调用portscan的时候,用str()把IP对象转成字符串:
# 示例遍历网段的代码 network = ipaddress.IPv4Network('192.168.1.0/24', strict=False) for ip in network.hosts(): portscan(str(ip)) # 这里把IPv4Address转成字符串
方案2:在扫描函数内部统一处理
更稳妥的方式是在portscan函数开头就把传入的host转成字符串,这样不管外部传的是字符串还是IP对象都能兼容:
def portscan(host): # 新增:将host转换为字符串格式 host = str(host) try: for port in range(1,445): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 可选优化:设置超时时间,大幅提升扫描速度 sock.settimeout(0.5) result = sock.connect_ex((host, port)) if result == 0: print "port",port," is open on",host sock.close() except KeyboardInterrupt: print " CTRL+C Interrupt..." sys.exit() # 中断后退出程序,更友好
修改后的完整可运行代码
#!/usr/bin/env python import socket import ipaddress import sys def portscan(host): host = str(host) try: for port in range(1,445): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(0.5) result = sock.connect_ex((host, port)) if result == 0: print "port",port," is open on",host sock.close() except KeyboardInterrupt: print " CTRL+C Interrupt..." sys.exit() if __name__ == "__main__": if len(sys.argv) != 2: print "Usage: python port_scan.py <network_cidr>" print "Example: python port_scan.py 192.168.1.0/24" sys.exit(1) try: network = ipaddress.IPv4Network(sys.argv[1], strict=False) for ip in network.hosts(): portscan(ip) except ValueError: print "Invalid CIDR format, please check your input." sys.exit(1)
额外优化提示
- 加上超时时间:默认
socket连接没有超时,会导致扫描关闭的端口时等待很久,sock.settimeout(0.5)可以让扫描效率提升很多。 - 增加命令行参数支持:上面的完整代码加入了CIDR参数输入,使用更灵活。
- 如果是Python3环境,记得把
print语句改成带括号的函数形式,比如print(f"port {port} is open on {host}")。
内容的提问来源于stack exchange,提问作者Brandon McGrath
相关产品推荐
相关产品推荐

