Python Socket扫描始终返回‘端口关闭’,但实际端口已开放问题排查
解决Python端口扫描程序始终显示“端口关闭”的问题
我帮你排查了代码里的几个关键问题,正是这些问题导致明明开放的端口被误判为关闭:
核心问题1:端口参数是字符串而非整数
你通过argparse获取的端口列表targetPort是字符串类型,但socket.connect()要求端口必须是整数。当你把字符串端口传给socket时,会直接触发连接异常,最终走到except分支输出“端口关闭”。
核心问题2:Socket资源管理有漏洞
在connect_scan.py的finally块中,如果你连接失败(比如因为端口类型错误),sock对象根本没被创建就执行sock.close(),这会额外抛出NameError,影响程序稳定性。
核心问题3:参数校验逻辑有隐患
在get_target.py中,当用户未指定-p参数时,target_ports是None,此时访问target_ports[0]会直接报错,而不是友好提示用户补全参数。
修正后的完整代码
1. get_target.py(修复参数类型与校验)
import argparse def get_target(): parser = argparse.ArgumentParser(description='Usage of program: ' + '-H <target host> -p <target port>') parser.add_argument('-H', dest='targetHost', required=True, help='specify target host') parser.add_argument('-p', dest='targetPort', nargs='*', type=int, help='specify target ports separated by space') args = parser.parse_args() target_host = args.targetHost target_ports = args.targetPort # 改进参数校验:直接检查target_ports是否为空 if not target_ports: print("Error: Please specify at least one target port with -p") print(parser.usage) exit(0) return target_host, target_ports
- 新增
type=int让argparse自动把端口转为整数 - 替换原有的
target_ports[0]判断,直接检查列表是否为空,避免None索引错误
2. connect_scan.py(修复Socket资源管理)
import socket def connect_scan(target_host, target_port): sock = None try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 添加超时,避免程序卡住(比如目标主机无响应) sock.settimeout(1) sock.connect((target_host, target_port)) print('[+] {}/tcp open'.format(target_port)) except socket.timeout: print('[-] {}/tcp timed out'.format(target_port)) except ConnectionRefusedError: print('[-] {}/tcp closed'.format(target_port)) except Exception as e: print('[-] {}/tcp error: {}'.format(target_port, str(e))) finally: if sock: sock.close()
- 初始化
sock为None,避免finally块中访问未定义的变量 - 添加超时设置,防止线程长时间阻塞
- 拆分异常类型,区分超时、连接拒绝和其他错误,输出更精准的信息
3. port_scan.py(优化流程逻辑)
from socket import * from threading import * from .get_target import * from .connect_scan import * def port_scan(): target_host, target_ports = get_target() try: target_ip = gethostbyname(target_host) except: print('Unknown host {}'.format(target_host)) return # 提前退出,避免后续错误 try: target_name = gethostbyaddr(target_ip) print('[+] Scan results for: ' + target_name[0]) except: print('[+] Scan results for: ' + target_ip) for target_port in target_ports: t = Thread(target=connect_scan, args=(target_ip, target_port)) t.start()
- 解构
get_target()的返回值,代码更清晰 - 在
Unknown host后添加return,避免后续代码继续执行
测试运行
现在你可以用以下命令测试(替换为你的Metasploitable主机IP):
python main.py -H 192.168.1.100 -p 21 22 80 443
这时候应该能正确显示开放的端口了,和Nmap的结果一致。
内容的提问来源于stack exchange,提问作者Jimin Byun
相关产品推荐
相关产品推荐

