page contents

Python端口存活检测:几秒钟扫完全网服务器的隐藏端口

新上线一台服务器,应用方说只开放了必要的端口,结果一扫描发现SSH、RDP、Redis、MongoDB全部对外开放。差点出安全事故。这种事情发生过不止一次,所以我现在对新上线服务器的端口检查是强制流程,不做不交付。

attachments-2026-06-CVCTMvaU6a20d444e7174.png

新上线一台服务器,应用方说只开放了必要的端口,结果一扫描发现SSH、RDP、Redis、MongoDB全部对外开放。差点出安全事故。这种事情发生过不止一次,所以我现在对新上线服务器的端口检查是强制流程,不做不交付。

用Python写一个端口检测脚本,不需要装什么专业扫描工具,标准库就够用。

思路很简单:对目标IP的指定端口做TCP连接探测,能连上说明端口开放,超时说明端口关闭。用多线程并发把速度提上来:

importsocket
fromconcurrent.futuresimportThreadPoolExecutor, as_completed
importdatetime

# 常见高危端口列表
COMMON_PORTS= {
    21: "FTP",
    22: "SSH",
    23: "Telnet",
    25: "SMTP",
    53: "DNS",
    80: "HTTP",
    110: "POP3",
    135: "RPC",
    139: "NetBIOS",
    143: "IMAP",
    443: "HTTPS",
    445: "SMB",
    993: "IMAPS",
    995: "POP3S",
    1433: "MSSQL",
    1521: "Oracle",
    3306: "MySQL",
    3389: "RDP",
    5432: "PostgreSQL",
    6379: "Redis",
    27017: "MongoDB",
    8080: "HTTP-Alt",
    8443: "HTTPS-Alt",
}

defcheck_port(ip, port, timeout=1):
    """检测单个端口,返回True表示开放"""
    sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.settimeout(timeout)
    try:
        result=sock.connect_ex((ip, port))
        sock.close()
        returnresult==0
    exceptException:
        returnFalse

defscan_target(ip, ports=None, timeout=1, max_workers=50):
    """扫描目标IP,返回开放的端口列表"""
    ifportsisNone:
        ports=list(COMMON_PORTS.keys())
    
    open_ports= []
    withThreadPoolExecutor(max_workers=max_workers) aspool:
        future_to_port= {pool.submit(check_port, ip, port, timeout): portforportinports}
        forfutureinas_completed(future_to_port):
            port=future_to_port[future]
            iffuture.result():
                open_ports.append(port)
    
    returnsorted(open_ports)

# 使用示例
if__name__=="__main__":
    target="192.168.1.100"
    print(f"开始扫描 {target} ...")
    open_ports=scan_target(target, timeout=1, max_workers=100)
    
    ifopen_ports:
        print(f"\n发现 {len(open_ports)} 个开放端口:")
        forportinopen_ports:
            service=COMMON_PORTS.get(port, "未知")
            print(f"  [{port:>5}] {service}")
    else:
        print("\n未发现常见高危端口开放")

connect_ex() 返回0表示连接成功,返回其他值表示失败。ThreadPoolExecutor 负责并发,默认50个线程,扫一个C段254个IP大概10来秒。

速度再快一点可以加个参数直接扫整个网段:

defscan_network(network_prefix, ports=None):
    """扫描整个网段"""
    importipaddress
    results= {}
    net=ipaddress.ip_network(network_prefix, strict=False)
    foripinnet:
        ip_str=str(ip)
        open_ports=scan_target(ip_str, ports)
        ifopen_ports:
            results[ip_str] =open_ports
    returnresults

# 扫描192.168.1.0/24
all_results=scan_network("192.168.1.0/24")
forip, portsinsorted(all_results.items()):
    print(f"{ip}: {', '.join(str(p) forpinports)}")

这个脚本拿来做交付前的合规检查很顺手。配合ansible或者paramiko跑一遍资产清单,几分钟就能出报告,比用nmap方便而且结果更可控。

有一点要提醒:大规模扫描内网的时候,频率不要太高,有些安全设备(防火墙、入侵检测系统)会对同一源IP的频繁连接报警,会引来不必要的麻烦。给自己管辖的资产做巡检没问题,拿去扫别人家的网络就是另一回事了。

更多相关技术内容咨询欢迎前往并持续关注好学星城论坛了解详情。

想高效系统的学习Python编程语言,推荐大家关注一个微信公众号:Python编程学习圈。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Python入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。

attachments-2022-05-rLS4AIF8628ee5f3b7e12.jpg

 


你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
Pack
Pack

2115 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 2228 文章
  3. Pack 2115 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章