端口扫描与服务发现脚本
扫描指定IP/网段的开放端口,识别运行服务,输出扫描报告
详细内容
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ==========================================
# 端口扫描与服务发现脚本
# 用途:扫描指定IP或网段的开放端口,识别常见服务
# 注意:仅限授权范围内使用,未经授权扫描他人网络属于违法行为
# 使用方法:python3 port_scanner.py 192.168.1.1
# python3 port_scanner.py 192.168.1.0/24
# ==========================================
import socket
import sys
import ipaddress
from concurrent.futures import ThreadPoolExecutor, as_completed
from datetime import datetime
# 常见端口对应服务
COMMON_PORTS = {
21: "FTP", 22: "SSH", 23: "Telnet", 25: "SMTP",
53: "DNS", 80: "HTTP", 110: "POP3", 143: "IMAP",
443: "HTTPS", 445: "SMB", 3306: "MySQL", 3389: "RDP",
5432: "PostgreSQL", 6379: "Redis", 8080: "HTTP-Proxy",
8443: "HTTPS-Alt", 9090: "WebAdmin", 27017: "MongoDB",
11211: "Memcached", 2181: "ZooKeeper", 9200: "Elasticsearch",
5601: "Kibana", 15672: "RabbitMQ-Web", 5672: "RabbitMQ",
10050: "Zabbix-Agent", 10051: "Zabbix-Server",
8888: "Jupyter/HTTP", 9000: "PHP-FPM/Portainer",
}
# 默认扫描的常用端口
DEFAULT_PORTS = list(COMMON_PORTS.keys()) + [81, 82, 88, 444, 4443, 5000, 5001, 7001, 7002, 8000, 8001, 8081, 8082, 8088, 8090, 8181, 8888, 9001, 9091, 9999]
def scan_port(ip, port, timeout=1.0):
# 扫描单个端口
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(timeout)
result = sock.connect_ex((ip, port))
sock.close()
if result == 0:
service = COMMON_PORTS.get(port, "Unknown")
# 尝试获取banner
banner = ""
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(1)
s.connect((ip, port))
s.send(b"\r\n")
banner = s.recv(1024).decode('utf-8', errors='ignore').strip()[:100]
s.close()
except:
pass
return {"port": port, "service": service, "banner": banner}
except:
pass
return None
def scan_ip(ip, ports=None, max_workers=100, timeout=1.0):
# 扫描单个IP的多个端口
if ports is None:
ports = DEFAULT_PORTS
open_ports = []
with ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = {executor.submit(scan_port, ip, port, timeout): port for port in ports}
for future in as_completed(futures):
result = future.result()
if result:
open_ports.append(result)
open_ports.sort(key=lambda x: x["port"])
return open_ports
def main():
if len(sys.argv) < 2:
print("用法: python3 port_scanner.py [端口范围]")
print("示例:")
print(" python3 port_scanner.py 192.168.1.1")
print(" python3 port_scanner.py 192.168.1.0/24")
print(" python3 port_scanner.py 192.168.1.1 1-1000")
sys.exit(1)
target = sys.argv[1]
port_range = sys.argv[2] if len(sys.argv) > 2 else None
# 解析端口范围
if port_range:
if "-" in port_range:
start, end = map(int, port_range.split("-"))
ports = list(range(start, end + 1))
else:
ports = [int(port_range)]
else:
ports = DEFAULT_PORTS
print("=" * 60)
print(" 端口扫描工具")
print(f" 目标: {target}")
print(f" 端口数: {len(ports)}")
print(f" 开始时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print("=" * 60)
print()
# 解析目标(单个IP或网段)
try:
network = ipaddress.ip_network(target, strict=False)
ips = [str(ip) for ip in network.hosts()]
if len(ips) == 0:
ips = [target]
except ValueError:
ips = [target]
total_open = 0
for ip in ips:
print(f"扫描: {ip}")
open_ports = scan_ip(ip, ports)
if open_ports:
print(f" 开放端口 ({len(open_ports)}):")
for p in open_ports:
banner_info = f" [{p['banner']}]" if p['banner'] else ""
print(f" {p['port']:>6}/tcp OPEN {p['service']}{banner_info}")
total_open += len(open_ports)
else:
print(" 无开放端口")
print()
print("=" * 60)
print(f" 扫描完成,共发现 {total_open} 个开放端口")
print(f" 结束时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print("=" * 60)
print()
print("⚠️ 免责声明:本工具仅限授权范围内的安全检测使用。")
print(" 未经授权扫描他人网络可能违反法律法规。")
if __name__ == "__main__":
main()
适配环境
适配系统:Windows,Linux,macOS
依赖环境:Python 3.7+
参数说明
[{"name": "target", "label": "\u76ee\u6807IP\u6216\u7f51\u6bb5", "default": "192.168.1.1"}, {"name": "port_range", "label": "\u7aef\u53e3\u8303\u56f4(\u59821-1000\uff0c\u7559\u7a7a\u626b\u5e38\u7528\u7aef\u53e3)", "default": ""}]