#!/bin/bash # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' NC='\033[0m' # No Color # 显示标题 echo -e "${CYAN}" echo "================================================" echo " 全端口扫描诊断工具 v3.0" echo "================================================" echo -e "${NC}" # 变量定义 SCAN_RESULTS=() OPEN_PORTS=() TOTAL_PORTS_SCANNED=0 START_TIME=0 END_TIME=0 # 函数:检查命令是否存在 check_command() { if command -v "$1" &> /dev/null; then return 0 else return 1 fi } # 函数:显示帮助信息 show_help() { echo -e "${YELLOW}使用说明:${NC}" echo "1. 本工具用于全面扫描目标的所有端口" echo "2. 支持IP地址和域名测试" echo "3. 提供多种扫描模式和速度选项" echo "4. 生成详细的扫描报告" echo "" echo -e "${YELLOW}扫描模式:${NC}" echo " - 快速扫描: 常用端口 (1-1000)" echo " - 标准扫描: 常见服务端口 (1-10000)" echo " - 全面扫描: 所有端口 (1-65535)" echo " - 自定义扫描: 指定端口范围" echo "" } # 函数:输入IP/域名 input_target() { while true; do echo -e "${BLUE}请输入要扫描的目标IP地址或域名:${NC}" read -p "目标地址: " TARGET if [ -z "$TARGET" ]; then echo -e "${RED}错误:目标地址不能为空!${NC}" continue fi # 简单验证格式 if [[ "$TARGET" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] || [[ "$TARGET" =~ ^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then break else echo -e "${RED}错误:请输入有效的IP地址或域名!${NC}" fi done } # 函数:选择扫描模式 select_scan_mode() { echo -e "${BLUE}请选择扫描模式:${NC}" echo "1) 快速扫描 (1-1000端口)" echo "2) 标准扫描 (1-10000端口)" echo "3) 全面扫描 (1-65535端口)" echo "4) 自定义端口范围" echo "5) 常用服务端口扫描" while true; do read -p "请选择 [1-5]: " MODE case $MODE in 1) START_PORT=1 END_PORT=1000 MODE_NAME="快速扫描" break ;; 2) START_PORT=1 END_PORT=10000 MODE_NAME="标准扫描" break ;; 3) START_PORT=1 END_PORT=65535 MODE_NAME="全面扫描" break ;; 4) input_custom_range MODE_NAME="自定义扫描" break ;; 5) scan_common_services MODE_NAME="常用服务扫描" break ;; *) echo -e "${RED}错误:请输入1-5之间的数字!${NC}" ;; esac done } # 函数:输入自定义端口范围 input_custom_range() { while true; do echo -e "${BLUE}请输入自定义端口范围:${NC}" read -p "起始端口: " START_PORT read -p "结束端口: " END_PORT if [[ ! "$START_PORT" =~ ^[0-9]+$ ]] || [[ ! "$END_PORT" =~ ^[0-9]+$ ]]; then echo -e "${RED}错误:端口必须是数字!${NC}" continue fi if [ "$START_PORT" -lt 1 ] || [ "$END_PORT" -gt 65535 ]; then echo -e "${RED}错误:端口范围必须在 1-65535 之间!${NC}" continue fi if [ "$START_PORT" -gt "$END_PORT" ]; then echo -e "${RED}错误:起始端口不能大于结束端口!${NC}" continue fi break done } # 函数:常用服务端口扫描 scan_common_services() { # 常见服务端口列表 COMMON_PORTS=(21 22 23 25 53 80 110 111 135 139 143 443 445 993 995 1723 3306 3389 5432 5900 6379 27017 25565) echo -e "${CYAN}开始扫描常用服务端口...${NC}" echo -e "扫描端口: ${YELLOW}${COMMON_PORTS[*]}${NC}" START_TIME=$(date +%s) for port in "${COMMON_PORTS[@]}"; do scan_single_port "$port" done END_TIME=$(date +%s) return 0 } # 函数:扫描单个端口 scan_single_port() { local port=$1 local result="" # 使用TCP连接测试 if timeout 1 bash -c "echo > /dev/tcp/$TARGET/$port" 2>/dev/null; then result="${GREEN}开放${NC}" OPEN_PORTS+=("$port") # 尝试识别服务 local service=$(identify_service "$port") result="$result - $service" else result="${RED}关闭${NC}" fi SCAN_RESULTS+=("端口 $port: $result") TOTAL_PORTS_SCANNED=$((TOTAL_PORTS_SCANNED + 1)) # 显示实时进度 if [ $TOTAL_PORTS_SCANNED -eq 1 ] || [ $((TOTAL_PORTS_SCANNED % 100)) -eq 0 ] || [ $TOTAL_PORTS_SCANNED -le 50 ]; then echo -e "扫描进度: $TOTAL_PORTS_SCANNED 端口 - 端口 $port: $result" fi } # 函数:识别服务 identify_service() { local port=$1 case $port in 21) echo "FTP" ;; 22) echo "SSH" ;; 23) echo "Telnet" ;; 25) echo "SMTP" ;; 53) echo "DNS" ;; 80) echo "HTTP" ;; 110) echo "POP3" ;; 111) echo "RPC" ;; 135) echo "RPC" ;; 139) echo "NetBIOS" ;; 143) echo "IMAP" ;; 443) echo "HTTPS" ;; 445) echo "SMB" ;; 993) echo "IMAPS" ;; 995) echo "POP3S" ;; 1723) echo "PPTP" ;; 3306) echo "MySQL" ;; 3389) echo "RDP" ;; 5432) echo "PostgreSQL" ;; 5900) echo "VNC" ;; 6379) echo "Redis" ;; 27017) echo "MongoDB" ;; 25565) echo "Minecraft" ;; *) echo "未知服务" ;; esac } # 函数:端口范围扫描 scan_port_range() { local start=$1 local end=$2 echo -e "${CYAN}开始扫描端口范围: $start - $end${NC}" echo -e "目标: ${YELLOW}$TARGET${NC}" echo -e "预计端口数量: $((end - start + 1))" echo "" START_TIME=$(date +%s) for ((port=start; port<=end; port++)); do scan_single_port "$port" done END_TIME=$(date +%s) } # 函数:并行扫描(加速) parallel_scan() { local start=$1 local end=$2 local batch_size=1000 local max_parallel=50 echo -e "${CYAN}开始并行扫描端口范围: $start - $end${NC}" echo -e "目标: ${YELLOW}$TARGET${NC}" echo -e "并行度: $max_parallel" echo "" START_TIME=$(date +%s) for ((batch_start=start; batch_start<=end; batch_start+=batch_size)); do local batch_end=$((batch_start + batch_size - 1)) if [ $batch_end -gt $end ]; then batch_end=$end fi echo -e "${YELLOW}扫描批次: $batch_start - $batch_end${NC}" for ((port=batch_start; port<=batch_end; port++)); do # 控制并行数量 ( if timeout 1 bash -c "echo > /dev/tcp/$TARGET/$port" 2>/dev/null; then echo -e "${GREEN}发现开放端口: $port${NC} - $(identify_service $port)" OPEN_PORTS+=("$port") fi ) & # 控制并发数 if [[ $(jobs -r -p | wc -l) -ge $max_parallel ]]; then wait -n fi done wait TOTAL_PORTS_SCANNED=$((TOTAL_PORTS_SCANNED + batch_size)) echo -e "已完成: $TOTAL_PORTS_SCANNED/$((end - start + 1)) 端口" done END_TIME=$(date +%s) } # 函数:Ping测试 ping_test() { echo -e "\n${PURPLE}=== 网络连通性测试 ===${NC}" echo -e "目标: ${YELLOW}$TARGET${NC}" if ping -c 3 -W 2 "$TARGET" &> /dev/null; then echo -e "${GREEN}✓ 网络连通正常${NC}" return 0 else echo -e "${RED}✗ 网络不通${NC}" return 1 fi } # 函数:DNS解析测试 dns_test() { echo -e "\n${PURPLE}=== DNS 解析测试 ===${NC}" if [[ "$TARGET" =~ ^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then echo -e "${CYAN}检测到域名,进行DNS解析...${NC}" if check_command nslookup; then if nslookup "$TARGET" &> /dev/null; then echo -e "${GREEN}✓ DNS 解析成功${NC}" nslookup "$TARGET" | grep -A 5 "Name:" else echo -e "${RED}✗ DNS 解析失败${NC}" fi else echo -e "${YELLOW}⚠ DNS 查询工具未安装${NC}" fi else echo -e "${CYAN}检测到IP地址,跳过DNS解析${NC}" fi } # 函数:生成扫描报告 generate_scan_report() { local duration=$((END_TIME - START_TIME)) echo -e "\n${PURPLE}=== 扫描报告 ===${NC}" echo -e "扫描时间: $(date)" echo -e "目标地址: ${YELLOW}$TARGET${NC}" echo -e "扫描模式: ${YELLOW}$MODE_NAME${NC}" if [ "$MODE_NAME" != "常用服务扫描" ]; then echo -e "端口范围: ${YELLOW}$START_PORT - $END_PORT${NC}" fi echo -e "扫描时长: ${YELLOW}${duration} 秒${NC}" echo -e "扫描端口总数: ${YELLOW}$TOTAL_PORTS_SCANNED${NC}" echo -e "开放端口数量: ${YELLOW}${#OPEN_PORTS[@]}${NC}" if [ ${#OPEN_PORTS[@]} -gt 0 ]; then echo -e "\n${GREEN}=== 开放的端口 ===${NC}" printf "端口\t状态\t服务\n" printf "====\t====\t====\n" # 对端口进行排序 IFS=$'\n' sorted_ports=($(sort -n <<<"${OPEN_PORTS[*]}")) unset IFS for port in "${sorted_ports[@]}"; do local service=$(identify_service "$port") printf "%-6d\t${GREEN}%-6s${NC}\t%-15s\n" "$port" "开放" "$service" done # 显示端口统计 echo -e "\n${CYAN}端口统计:${NC}" echo -e "标准服务端口 (1-1024): $(echo "${OPEN_PORTS[@]}" | tr ' ' '\n' | awk '$1 <= 1024' | wc -l)" echo -e "注册端口 (1025-49151): $(echo "${OPEN_PORTS[@]}" | tr ' ' '\n' | awk '$1 > 1024 && $1 <= 49151' | wc -l)" echo -e "动态端口 (49152-65535): $(echo "${OPEN_PORTS[@]}" | tr ' ' '\n' | awk '$1 > 49151' | wc -l)" else echo -e "\n${RED}未发现任何开放端口${NC}" fi # 安全建议 echo -e "\n${YELLOW}=== 安全建议 ===${NC}" if [ ${#OPEN_PORTS[@]} -eq 0 ]; then echo -e "${GREEN}● 所有扫描端口均关闭,安全性良好${NC}" elif [ ${#OPEN_PORTS[@]} -le 5 ]; then echo -e "${YELLOW}● 开放端口数量较少,建议检查服务配置${NC}" else echo -e "${RED}● 开放端口较多,建议进行安全审计${NC}" fi } # 函数:选择扫描速度 select_scan_speed() { echo -e "${BLUE}请选择扫描速度:${NC}" echo "1) 慢速扫描 (准确率高)" echo "2) 中速扫描 (平衡模式)" echo "3) 快速扫描 (可能漏扫)" echo "4) 并行扫描 (最快速度)" while true; do read -p "请选择 [1-4]: " SPEED case $SPEED in 1) TIMEOUT=2 SPEED_NAME="慢速扫描" break ;; 2) TIMEOUT=1 SPEED_NAME="中速扫描" break ;; 3) TIMEOUT=0.5 SPEED_NAME="快速扫描" break ;; 4) TIMEOUT=1 SPEED_NAME="并行扫描" break ;; *) echo -e "${RED}错误:请输入1-4之间的数字!${NC}" ;; esac done } # 主函数 main() { # 显示帮助信息 show_help # 获取用户输入 input_target # 网络基础测试 dns_test if ! ping_test; then echo -e "${YELLOW}网络不通,是否继续扫描?(y/n)${NC}" read -p "选择: " CONTINUE if [[ "$CONTINUE" != "y" && "$CONTINUE" != "Y" ]]; then echo -e "${RED}扫描终止${NC}" exit 1 fi fi # 选择扫描模式和速度 select_scan_mode select_scan_speed echo -e "\n${GREEN}开始端口扫描...${NC}" echo -e "目标: ${YELLOW}$TARGET${NC}" echo -e "模式: ${YELLOW}$MODE_NAME${NC}" echo -e "速度: ${YELLOW}$SPEED_NAME${NC}" # 执行扫描 case $MODE in 5) # 常用服务扫描已在 select_scan_mode 中处理 ;; *) if [ "$SPEED_NAME" = "并行扫描" ]; then parallel_scan "$START_PORT" "$END_PORT" else scan_port_range "$START_PORT" "$END_PORT" fi ;; esac # 生成报告 generate_scan_report echo -e "\n${GREEN}端口扫描完成!${NC}" } # 检查系统要求 check_requirements() { local missing=() for cmd in ping timeout; do if ! command -v "$cmd" &> /dev/null; then missing+=("$cmd") fi done if [ ${#missing[@]} -gt 0 ]; then echo -e "${RED}错误: 缺少必要的命令: ${missing[*]}${NC}" echo -e "${YELLOW}请安装缺少的命令后重新运行脚本${NC}" exit 1 fi } # 脚本入口 if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then show_help exit 0 fi # 检查系统要求 check_requirements # 运行主程序 main