#!/bin/bash
# 增强型多主机SSH互信配置脚本

# 统一日志输出
LOG_FILE="ssh_cluster_$(date +%Y%m%d%H%M%S).log"
exec > >(tee -a "$LOG_FILE") 2>&1

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m'

# 函数：选择IP获取方式
select_ip_mode() {
    whiptail --title "选择IP获取方式" --menu "请选择IP地址获取方式：" 15 50 4 \
        "1" "手动输入IP地址" \
        "2" "自动扫描同网段IP" \
        3>&1 1>&2 2>&3
}

# 函数：手动输入IP
manual_ip_input() {
    IPLIST=()
    echo -e "${YELLOW}请输入需要连接的IP地址（每行一个，输入空行结束）：${NC}"
    while true; do
        read -p "IP地址: " ip
        [[ -z $ip ]] && break
        if [[ $ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
            IPLIST+=("$ip")
            echo -e "${GREEN}已添加IP: $ip${NC}"
        else
            echo -e "${RED}错误：$ip 不是有效的IP地址${NC}"
        fi
    done
}

# 函数：自动扫描IP（优化版）
auto_scan_ip() {
    echo -e "${YELLOW}正在获取本机IP...${NC}"
    IP=$(ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | head -1)
    [[ -z $IP ]] && IP=$(ip -4 addr show | grep -w inet | awk '{print $2}' | cut -d/ -f1 | grep -v 127.0.0.1 | head -1)
    NET=${IP%.*}.
    
    END=$(whiptail --inputbox "请输入扫描范围上限(1-254)" 10 40 "254" 3>&1 1>&2 2>&3)
    [[ -z $END ]] && END=254

    echo -e "${YELLOW}开始扫描${NET}1-${END}...${NC}"
    rm -f SCANIP.log
    seq 1 $END | xargs -P 50 -I{} timeout 1 ping -c1 -W1 ${NET}{} | grep "bytes from" | awk '{print $4}' | cut -d: -f1 >> SCANIP.log &
    wait

    IPLIST=($(sort -V SCANIP.log 2>/dev/null))
    echo -e "${GREEN}发现 ${#IPLIST[@]} 个存活主机${NC}"
}

# 函数：密码验证
get_password() {
    while :; do
        PASS=$(whiptail --passwordbox "请输入SSH密码（不可为空）" 10 40 3>&1 1>&2 2>&3)
        [[ -n $PASS ]] && break
    done
}

# 函数：安装依赖
install_deps() {
    echo -e "${YELLOW}检查系统依赖...${NC}"
    if command -v yum &>/dev/null; then
        rpm -q sshpass &>/dev/null || yum install -y sshpass
        rpm -q rsync &>/dev/null || yum install -y rsync
    elif command -v apt-get &>/dev/null; then
        dpkg -l | grep -q sshpass || apt-get -y install sshpass
        dpkg -l | grep -q rsync || apt-get -y install rsync
    else
        echo -e "${RED}不支持的包管理器${NC}"
        exit 1
    fi
}

# 函数：初始化密钥
init_ssh_keys() {
    echo -e "${YELLOW}初始化统一密钥...${NC}"
    SSH_DIR="/root/.ssh"
    mkdir -p $SSH_DIR
    chmod 700 $SSH_DIR
    
    # 生成统一密钥对
    if [[ ! -f "$SSH_DIR/id_rsa" ]]; then
        ssh-keygen -q -t rsa -b 4096 -N "" -f "$SSH_DIR/id_rsa"
        echo -e "${GREEN}已生成新密钥对${NC}"
    else
        echo -e "${YELLOW}使用现有密钥对${NC}"
    fi
    
    # 创建增强型authorized_keys
    cat "$SSH_DIR/id_rsa.pub" >> "$SSH_DIR/authorized_keys"
    sort -u "$SSH_DIR/authorized_keys" -o "$SSH_DIR/authorized_keys"
    chmod 600 "$SSH_DIR/authorized_keys"
}

# 主配置函数
configure_host() {
    local ip=$1
    echo -e "\n${YELLOW}开始配置 $ip ...${NC}"
    
    # 跳过本机
    [[ "$ip" == "$IP" ]] && { echo -e "${YELLOW}跳过本机${NC}"; return; }

    # 创建远程目录
    if ! sshpass -p "$PASS" ssh -o StrictHostKeyChecking=no root@$ip \
        "mkdir -p /root/.ssh && chmod 700 /root/.ssh"; then
        echo -e "${RED}$ip 目录创建失败${NC}"
        return 1
    fi

    # 同步SSH配置
    if ! sshpass -p "$PASS" rsync -rzc -e "ssh -o StrictHostKeyChecking=no" \
        --delete --timeout=10 \
        /root/.ssh/ root@$ip:/root/.ssh/; then
        echo -e "${RED}$ip 文件同步失败${NC}"
        return 2
    fi

    # 强制设置权限
    sshpass -p "$PASS" ssh -o StrictHostKeyChecking=no root@$ip \
        "chmod 700 /root/.ssh; \
        chmod 600 /root/.ssh/*; \
        sed -i 's/#*PubkeyAuthentication.*/PubkeyAuthentication yes/g' /etc/ssh/sshd_config; \
        systemctl reload sshd" && \
    echo -e "${GREEN}$ip 配置成功${NC}" || \
    { echo -e "${RED}$ip 权限设置失败${NC}"; return 3; }
}

# 验证函数
verify_connection() {
    echo -e "\n${YELLOW}开始验证互信...${NC}"
    for src_ip in "${IPLIST[@]}"; do
        for dst_ip in "${IPLIST[@]}"; do
            [[ "$src_ip" == "$dst_ip" ]] && continue
            echo -n "测试 $src_ip -> $dst_ip ... "
            if ssh -i /root/.ssh/id_rsa -o BatchMode=yes -o ConnectTimeout=5 root@$dst_ip "echo success" &>/dev/null; then
                echo -e "${GREEN}成功${NC}"
            else
                echo -e "${RED}失败${NC}"
            fi
        done
    done
}

# 主程序
main() {
    # 选择IP获取方式
    case $(select_ip_mode) in
        1) manual_ip_input ;;
        2) auto_scan_ip ;;
        *) exit ;;
    esac

    [[ ${#IPLIST[@]} -eq 0 ]] && { echo -e "${RED}无有效IP地址${NC}"; exit 1; }

    get_password
    install_deps
    init_ssh_keys

    # 显示配置确认
    whiptail --yesno "将配置以下主机：\n$(printf '%s\n' "${IPLIST[@]}")" 20 60 || exit

    # 并行配置
    declare -A pids
    for ip in "${IPLIST[@]}"; do
        configure_host "$ip" &
        pids[$!]="$ip"
    done

    # 等待并处理结果
    for pid in "${!pids[@]}"; do
        wait $pid
        status=$?
        [[ $status -ne 0 ]] && echo -e "${RED}${pids[$pid]} 配置失败 (代码:$status)${NC}"
    done

    verify_connection
    echo -e "${GREEN}所有操作完成！详细日志见 $LOG_FILE${NC}"
}

# 执行主程序
main
