#!/bin/bash

# Linux系统安全配置脚本 - 优化版
# 功能：系统检测、防火墙配置、端口管理、fail2ban配置
# 针对代理服务器优化，减少对正常流量的影响

set -e

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

# 日志函数
log_info() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

log_step() {
    echo -e "${BLUE}[STEP]${NC} $1"
}

# 检查是否为root用户
check_root() {
    if [[ $EUID -ne 0 ]]; then
        log_error "此脚本需要root权限运行"
        exit 1
    fi
}

# 检测操作系统
detect_os() {
    log_step "检测操作系统类型..."
    
    if [[ -f /etc/redhat-release ]]; then
        if grep -q "CentOS" /etc/redhat-release; then
            OS="centos"
            PACKAGE_MANAGER="yum"
        elif grep -q "Red Hat" /etc/redhat-release; then
            OS="rhel"
            PACKAGE_MANAGER="yum"
        fi
    elif [[ -f /etc/lsb-release ]] && grep -q "Ubuntu" /etc/lsb-release; then
        OS="ubuntu"
        PACKAGE_MANAGER="apt"
    elif [[ -f /etc/debian_version ]]; then
        OS="debian"
        PACKAGE_MANAGER="apt"
    else
        log_error "不支持的操作系统"
        exit 1
    fi
    
    log_info "检测到操作系统: $OS"
}

# 更新系统包管理器
update_system() {
    log_step "更新系统包管理器..."
    
    case $PACKAGE_MANAGER in
        "yum")
            log_info "正在执行 yum update，可能需要确认..."
            yum update -y
            ;;
        "apt")
            log_info "正在执行 apt update..."
            apt update -y
            ;;
    esac
    
    log_info "系统包管理器更新完成"
}

# 清理已有的iptables配置
clean_existing_iptables() {
    log_step "清理已有的iptables配置..."
    
    # 停止iptables服务（如果正在运行）
    if systemctl is-active --quiet iptables 2>/dev/null; then
        log_info "停止现有iptables服务..."
        systemctl stop iptables 2>/dev/null || true
    fi
    
    # 清空所有规则和链
    log_info "清空所有iptables规则..."
    iptables -F 2>/dev/null || true
    iptables -X 2>/dev/null || true
    iptables -t nat -F 2>/dev/null || true
    iptables -t nat -X 2>/dev/null || true
    iptables -t mangle -F 2>/dev/null || true
    iptables -t mangle -X 2>/dev/null || true
    iptables -t filter -F 2>/dev/null || true
    iptables -t filter -X 2>/dev/null || true
    
    # 重置所有链的默认策略为ACCEPT（避免锁定）
    iptables -P INPUT ACCEPT 2>/dev/null || true
    iptables -P FORWARD ACCEPT 2>/dev/null || true
    iptables -P OUTPUT ACCEPT 2>/dev/null || true
    
    # 删除已保存的iptables规则文件
    case $OS in
        "centos"|"rhel")
            if [[ -f /etc/sysconfig/iptables ]]; then
                log_info "删除旧的iptables配置文件..."
                rm -f /etc/sysconfig/iptables
                rm -f /etc/sysconfig/iptables.save
            fi
            ;;
        "ubuntu"|"debian")
            if [[ -f /etc/iptables/rules.v4 ]]; then
                log_info "删除旧的iptables配置文件..."
                rm -f /etc/iptables/rules.v4
                rm -f /etc/iptables/rules.v6
            fi
            ;;
    esac
    
    log_info "iptables配置清理完成"
}

# 清理已有的fail2ban配置
clean_existing_fail2ban() {
    log_step "清理已有的fail2ban配置..."
    
    # 检查fail2ban是否已安装
    if command -v fail2ban-client &> /dev/null; then
        log_info "检测到已安装的fail2ban，开始清理..."
        
        # 停止fail2ban服务
        if systemctl is-active --quiet fail2ban 2>/dev/null; then
            log_info "停止fail2ban服务..."
            systemctl stop fail2ban 2>/dev/null || true
        fi
        
        # 解封所有被封禁的IP
        log_info "解封所有被封禁的IP..."
        fail2ban-client unban --all 2>/dev/null || true
        
        # 备份原有配置（如果需要）
        if [[ -f /etc/fail2ban/jail.local ]]; then
            log_info "备份原有fail2ban配置..."
            cp /etc/fail2ban/jail.local /etc/fail2ban/jail.local.backup.$(date +%Y%m%d_%H%M%S) 2>/dev/null || true
        fi
        
        # 清理配置文件
        log_info "清理fail2ban配置文件..."
        rm -f /etc/fail2ban/jail.local
        rm -f /etc/fail2ban/jail.d/*.conf 2>/dev/null || true
        
        # 清理自定义过滤器
        rm -f /etc/fail2ban/filter.d/nginx-*.conf 2>/dev/null || true
        
        # 清理日志和数据库
        rm -f /var/lib/fail2ban/fail2ban.sqlite3 2>/dev/null || true
        rm -f /var/log/fail2ban.log* 2>/dev/null || true
        
        log_info "fail2ban配置清理完成"
    else
        log_info "未检测到fail2ban，无需清理"
    fi
}

disable_system_firewalls() {
    log_step "关闭系统自带防火墙..."
    
    case $OS in
        "centos"|"rhel")
            # 停止并禁用firewalld
            if systemctl is-active --quiet firewalld 2>/dev/null; then
                log_info "正在停止firewalld..."
                systemctl stop firewalld
                systemctl disable firewalld
                log_info "已停止并禁用firewalld"
            else
                log_info "firewalld未运行"
            fi
            
            # 停止并禁用ufw (如果存在)
            if command -v ufw &> /dev/null; then
                log_info "正在禁用ufw..."
                ufw --force disable
                log_info "已禁用ufw"
            fi
            ;;
        "ubuntu"|"debian")
            # 停止并禁用ufw
            if command -v ufw &> /dev/null; then
                log_info "正在停止并禁用ufw..."
                ufw --force disable
                systemctl stop ufw 2>/dev/null || true
                systemctl disable ufw 2>/dev/null || true
                log_info "已停止并禁用ufw"
            else
                log_info "ufw未安装"
            fi
            
            # 停止并禁用firewalld (如果存在)
            if systemctl is-active --quiet firewalld 2>/dev/null; then
                log_info "正在停止firewalld..."
                systemctl stop firewalld
                systemctl disable firewalld
                log_info "已停止并禁用firewalld"
            fi
            ;;
    esac
}

# 安装iptables
install_iptables() {
    log_step "安装并配置iptables..."
    
    case $PACKAGE_MANAGER in
        "yum")
            log_info "安装iptables和相关服务..."
            yum install -y iptables iptables-services
            # 确保服务被禁用，我们手动管理
            systemctl disable iptables 2>/dev/null || true
            systemctl stop iptables 2>/dev/null || true
            ;;
        "apt")
            log_info "安装iptables和iptables-persistent..."
            # 预先配置iptables-persistent以避免交互
            echo iptables-persistent iptables-persistent/autosave_v4 boolean true | debconf-set-selections
            echo iptables-persistent iptables-persistent/autosave_v6 boolean true | debconf-set-selections
            apt install -y iptables iptables-persistent
            # 停止自动服务，我们手动管理
            systemctl disable netfilter-persistent 2>/dev/null || true
            systemctl stop netfilter-persistent 2>/dev/null || true
            ;;
    esac
    
    log_info "iptables安装完成"
}

# 配置基础iptables规则 - 针对代理服务器优化
configure_basic_iptables() {
    log_step "配置基础iptables规则（代理服务器优化版）..."
    
    # 再次确保清空现有规则（防止残留）
    log_info "确保清空所有iptables规则..."
    iptables -F 2>/dev/null || true
    iptables -X 2>/dev/null || true
    iptables -t nat -F 2>/dev/null || true
    iptables -t nat -X 2>/dev/null || true
    iptables -t mangle -F 2>/dev/null || true
    iptables -t mangle -X 2>/dev/null || true
    
    # 设置默认策略
    log_info "设置默认策略..."
    iptables -P INPUT DROP
    iptables -P FORWARD DROP
    iptables -P OUTPUT ACCEPT
    
    # 允许本地回环
    log_info "配置本地回环规则..."
    iptables -A INPUT -i lo -j ACCEPT
    iptables -A OUTPUT -o lo -j ACCEPT
    
    # 允许已建立的连接和相关连接（对代理服务器非常重要）
    log_info "配置连接状态规则..."
    iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
    
    # 创建轻量级防护链（针对代理服务器优化）
    log_info "配置轻量级防护规则..."
    iptables -N ddos_protect 2>/dev/null || true
    iptables -F ddos_protect 2>/dev/null || true
    
    # 防护规则更宽松，适合代理服务器
    # 5分钟内超过100个新连接才触发限制（原来是60秒10个）
    iptables -A ddos_protect -m recent --set --name ddos_check
    iptables -A ddos_protect -m recent --update --seconds 300 --hitcount 100 --name ddos_check -j DROP
    iptables -A ddos_protect -j RETURN
    
    # 只对特定端口应用防护（不影响代理端口）
    # 主要保护SSH和管理端口
    iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ddos_protect
    iptables -A INPUT -p tcp --dport 8006 -m state --state NEW -j ddos_protect
    
    # 开放代理相关端口（无限制）
    log_info "开放代理相关端口..."
    iptables -A INPUT -p tcp --dport 12748 -j ACCEPT
    iptables -A INPUT -p tcp --dport 80 -j ACCEPT
    iptables -A INPUT -p tcp --dport 443 -j ACCEPT
    iptables -A INPUT -p tcp --dport 5222 -j ACCEPT
    iptables -A INPUT -p tcp --dport 7777 -j ACCEPT
    iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
    iptables -A INPUT -p tcp --dport 8007 -j ACCEPT
    
    # 开放FTP端口
    log_info "开放FTP端口..."
    iptables -A INPUT -p tcp --dport 21 -j ACCEPT
    iptables -A INPUT -p tcp --dport 20 -j ACCEPT
    # FTP被动模式端口范围
    iptables -A INPUT -p tcp --dport 30000:31000 -j ACCEPT
    
    # 管理端口（应用防护）
    log_info "配置管理端口..."
    iptables -A INPUT -p tcp --dport 8006 -j ACCEPT
    
    # 永久禁用ICMP ping
    log_info "永久禁用ICMP ping..."
    iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
    
    # 开放高端口范围（代理服务器可能需要）
    log_info "开放高端口范围（10000-65535）用于代理服务..."
    iptables -A INPUT -p tcp --dport 10000:65535 -j ACCEPT
    iptables -A INPUT -p udp --dport 10000:65535 -j ACCEPT
    
    log_info "基础iptables规则配置完成（代理服务器优化版）"
    log_info "已开放端口: 12748, 80, 443, 5222, 7777, 8006, 8080, 8007, 21(FTP), 20(FTP), 30000-31000(FTP被动)"
    log_info "已开放高端口范围: 10000-65535（TCP/UDP）"
    log_info "轻量级防护: 5分钟内超过100个新连接才会被限制"
    log_info "永久禁用ICMP ping"
}

# 用户交互：添加自定义端口
add_custom_ports() {
    log_step "配置自定义端口..."
    
    echo -e "${YELLOW}请输入需要开放的额外TCP端口，多个端口用空格分隔（直接回车跳过）:${NC}"
    read -r custom_ports
    
    if [[ -n "$custom_ports" ]]; then
        for port in $custom_ports; do
            # 验证端口号
            if [[ "$port" =~ ^[0-9]+$ ]] && [[ "$port" -ge 1 ]] && [[ "$port" -le 65535 ]]; then
                # 检查端口是否已经在高端口范围内
                if [[ "$port" -ge 10000 ]]; then
                    log_info "端口 $port 已在高端口范围内开放"
                else
                    iptables -A INPUT -p tcp --dport "$port" -j ACCEPT
                    log_info "已开放TCP端口: $port"
                fi
            else
                log_warn "无效端口号: $port，跳过"
            fi
        done
    else
        log_info "未添加额外端口"
    fi
}

# 保存iptables规则
save_iptables() {
    log_step "保存iptables规则..."
    
    case $OS in
        "centos"|"rhel")
            log_info "保存iptables规则到系统配置..."
            service iptables save 2>/dev/null || iptables-save > /etc/sysconfig/iptables
            ;;
        "ubuntu"|"debian")
            log_info "保存iptables规则..."
            iptables-save > /etc/iptables/rules.v4
            # 确保开机自动加载
            if ! grep -q "iptables-restore" /etc/rc.local 2>/dev/null; then
                echo "iptables-restore < /etc/iptables/rules.v4" >> /etc/rc.local
                chmod +x /etc/rc.local
            fi
            ;;
    esac
    
    log_info "iptables规则已保存"
}

# 清理已有的Nginx安全配置
clean_existing_nginx_config() {
    log_step "清理已有的Nginx安全配置..."
    
    if command -v nginx &> /dev/null; then
        log_info "检测到Nginx，清理旧的安全配置..."
        
        # 删除旧的安全配置文件
        rm -f /etc/nginx/conf.d/security.conf
        rm -f /etc/nginx/sites-available/security
        rm -f /etc/nginx/sites-enabled/security
        
        # 测试Nginx配置
        if nginx -t 2>/dev/null; then
            systemctl reload nginx 2>/dev/null || log_warn "无法重载Nginx配置"
            log_info "Nginx配置清理完成"
        else
            log_warn "Nginx配置测试失败，请手动检查"
        fi
    else
        log_info "未检测到Nginx，无需清理"
    fi
}

# 配置Nginx安全规则（代理服务器优化版）
configure_nginx_security() {
    log_step "配置Nginx安全规则（代理服务器优化版）..."
    
    # 检查nginx是否安装
    if ! command -v nginx &> /dev/null; then
        log_warn "Nginx未安装，跳过Nginx安全配置"
        return
    fi
    
    # 创建Nginx安全配置文件（更宽松的配置）
    log_info "创建Nginx安全配置..."
    cat > /etc/nginx/conf.d/security.conf << 'EOF'
# 限制并发连接数和请求速率（代理服务器优化）
# 更宽松的限制，适合代理服务器
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=50r/s;

# 安全配置
server {
    # 提高每个IP的并发连接数限制（原20改为100）
    limit_conn conn_limit_per_ip 100;
    # 提高请求速率限制（原10r/s改为50r/s），增加突发容量
    limit_req zone=req_limit_per_ip burst=20 nodelay;
    
    # 隐藏Nginx版本信息
    server_tokens off;
    
    # 防止目录扫描（保留基本安全）
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }
    
    # 只阻止最危险的文件类型
    location ~* \.(htaccess|htpasswd|ini|log|sh|sql)$ {
        deny all;
        access_log off;
        log_not_found off;
    }
    
    # 只阻止明显的攻击路径
    location ~* /(wp-admin|wp-login|phpmyadmin|setup\.php) {
        deny all;
        access_log off;
        log_not_found off;
    }
    
    # 移除User-Agent检查（可能影响某些代理客户端）
    # 移除爬虫检查（可能误伤正常流量）
    
    # 保留基本的方法限制
    if ($request_method !~ ^(GET|HEAD|POST|PUT|DELETE|OPTIONS)$ ) {
        return 444;
    }
}
EOF
    
    # 检查Nginx配置是否正确
    if nginx -t 2>/dev/null; then
        log_info "Nginx安全配置已应用（代理服务器优化版）"
        systemctl reload nginx 2>/dev/null || log_warn "无法重载Nginx配置，请手动检查"
    else
        log_warn "Nginx配置测试失败，请检查配置文件"
        rm -f /etc/nginx/conf.d/security.conf
    fi
}

# 配置fail2ban（代理服务器优化版）
install_configure_fail2ban() {
    log_step "安装和配置fail2ban（代理服务器优化版）..."
    
    # 根据操作系统确定SSH日志路径
    local ssh_log_path
    case $OS in
        "ubuntu"|"debian")
            ssh_log_path="/var/log/auth.log"
            ;;
        "centos"|"rhel")
            ssh_log_path="/var/log/secure"
            ;;
        *)
            # 默认路径，大多数系统使用auth.log
            ssh_log_path="/var/log/auth.log"
            ;;
    esac
    
    log_info "检测到SSH日志路径: $ssh_log_path"
    
    # 验证日志文件是否存在
    if [[ ! -f "$ssh_log_path" ]]; then
        log_warn "SSH日志文件 $ssh_log_path 不存在，尝试创建..."
        touch "$ssh_log_path"
        chmod 640 "$ssh_log_path"
    fi
    
    # 安装fail2ban
    case $PACKAGE_MANAGER in
        "yum")
            # CentOS需要EPEL源
            log_info "安装EPEL源..."
            yum install -y epel-release
            log_info "安装fail2ban..."
            yum install -y fail2ban
            ;;
        "apt")
            log_info "安装fail2ban..."
            apt install -y fail2ban
            ;;
    esac
    
    # 配置fail2ban（更严格的SSH防护）
    log_info "配置fail2ban规则（严格SSH防护版）..."
    cat > /etc/fail2ban/jail.local << EOF
[DEFAULT]
# 永久封禁（设置为-1表示永久）
bantime = -1
# 查找时间窗口(秒) - 10分钟
findtime = 600
# 最大重试次数 - 5次
maxretry = 5
# 忽略的IP地址（可以添加你的常用IP）
ignoreip = 127.0.0.1/8 ::1

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = $ssh_log_path
maxretry = 5
bantime = -1
findtime = 600

# 禁用其他可能影响代理的jail
[nginx-http-auth]
enabled = false

[nginx-noscript]
enabled = false

[nginx-badbots]
enabled = false

[nginx-noproxy]
enabled = false
EOF
    
    # 启动fail2ban服务
    log_info "启动fail2ban服务..."
    systemctl enable fail2ban
    systemctl restart fail2ban
    
    # 等待一下让服务完全启动
    sleep 2
    
    # 验证fail2ban配置
    log_info "验证fail2ban配置..."
    if fail2ban-client status sshd >/dev/null 2>&1; then
        log_info "fail2ban SSH监控配置成功"
        fail2ban-client status sshd
    else
        log_warn "fail2ban SSH监控可能配置有误，请检查日志: journalctl -u fail2ban"
    fi
    
    log_info "fail2ban安装和配置完成（严格SSH防护版）"
    log_info "SSH防护规则: 连续5次登录失败将永久封禁IP（仅限手动解封）"
    log_info "使用日志文件: $ssh_log_path"
}

# 显示当前状态
show_status() {
    log_step "显示当前配置状态..."
    
    echo -e "\n${GREEN}=== 配置完成总结（代理服务器优化版） ===${NC}"
    echo -e "${BLUE}操作系统:${NC} $OS"
    echo -e "${BLUE}iptables状态:${NC} $(systemctl is-active iptables 2>/dev/null || echo "已配置")"
    echo -e "${BLUE}fail2ban状态:${NC} $(systemctl is-active fail2ban)"
    
    echo -e "\n${BLUE}当前开放的端口:${NC}"
    echo "指定TCP端口: 12748, 80, 443, 5222, 7777, 8006, 8080, 8007, 21(FTP), 20(FTP), 30000-31000(FTP被动)"
    echo "高端口范围: 10000-65535 (TCP/UDP) - 适用于代理服务"
    echo "注意: SSH端口22已开放但有防护"
    
    echo -e "\n${BLUE}iptables防护规则（代理优化）:${NC}"
    echo "✓ 轻量级防护: 5分钟内超过100个新连接才会被限制"
    echo "✓ 仅对SSH和管理端口应用连接限制"
    echo "✓ 永久禁用ICMP ping"
    echo "✓ 代理端口无连接数限制"
    
    echo -e "\n${BLUE}Nginx安全配置（代理优化）:${NC}"
    if [[ -f /etc/nginx/conf.d/security.conf ]]; then
        echo "✓ 并发连接限制: 每IP最多100个连接（提高了限制）"
        echo "✓ 请求速率限制: 每IP每秒50个请求，允许突发20个（更宽松）"
        echo "✓ 基本安全防护（移除了可能影响代理的规则）"
        echo "✓ 支持更多HTTP方法（包括PUT、DELETE、OPTIONS）"
    else
        echo "✗ Nginx安全配置未应用（可能因为Nginx未安装）"
    fi
    
    echo -e "\n${BLUE}fail2ban状态（严格SSH防护）:${NC}"
    if systemctl is-active --quiet fail2ban; then
        echo "fail2ban服务状态: $(systemctl is-active fail2ban)"
        echo "✓ SSH防护: 5次失败尝试永久封禁（仅限手动解封）"
        fail2ban-client status sshd 2>/dev/null || echo "SSH监控可能有问题"
        
        echo ""
        echo "手动解封IP命令:"
        echo "  fail2ban-client set sshd unbanip <IP地址>"
        echo "查看封禁列表:"
        echo "  fail2ban-client status sshd"
        echo "查看被永久封禁的IP:"
        echo "  iptables -L -n | grep DROP"
    else
        echo "fail2ban服务未运行"
    fi
    
    echo -e "\n${YELLOW}代理服务器优化说明:${NC}"
    echo "• 大幅放宽了连接数和频率限制"
    echo "• 开放了高端口范围以支持各种代理协议"
    echo "• 移除了可能误伤代理流量的规则"
    echo "• SSH采用严格防护：5次失败永久封禁"
    echo "• 完全禁用ICMP ping以提高隐蔽性"
    echo "• 被封禁的IP需要手动解封，无法自动恢复"
}

# 运行外部脚本
run_external_script() {
    log_step "准备运行外部脚本..."
    echo -e "${YELLOW}即将运行外部脚本，该脚本包含交互内容${NC}"
    echo -e "${YELLOW}按任意键继续...${NC}"
    read -n 1 -s
    
    log_info "正在下载并运行外部脚本..."
    if wget http://download.azurezoo.cloud//Tools/Linux_tools.sh -O /tmp/Linux_tools.sh; then
        chmod +x /tmp/Linux_tools.sh
        bash /tmp/Linux_tools.sh
        # 清理临时文件
        rm -f /tmp/Linux_tools.sh
        log_info "外部脚本运行完成"
    else
        log_error "下载外部脚本失败"
    fi
}

# 主函数
main() {
    echo -e "${GREEN}========================================${NC}"
    echo -e "${GREEN}   Linux系统安全配置脚本 - 代理优化版${NC}"
    echo -e "${GREEN}========================================${NC}"
    
    check_root
    detect_os
    update_system
    clean_existing_iptables
    clean_existing_fail2ban
    disable_system_firewalls
    install_iptables
    configure_basic_iptables
    add_custom_ports
    save_iptables
    clean_existing_nginx_config
    configure_nginx_security
    install_configure_fail2ban
    show_status
    run_external_script
    
    echo -e "\n${GREEN}========================================${NC}"
    echo -e "${GREEN}      所有配置已完成！${NC}"
    echo -e "${GREEN}========================================${NC}"
    
    log_info "系统安全配置完成，建议重启系统以确保所有配置生效"
    echo -e "\n${YELLOW}重要提示:${NC}"
    echo -e "• 此配置针对代理服务器优化，安全限制较为宽松"
    echo -e "• 如需更严格的安全配置，请手动调整相关参数"
    echo -e "• 建议定期检查fail2ban日志和被封禁的IP列表"
    echo -e "• 可使用以下命令检查连接状态："
    echo -e "  - netstat -tuln  # 查看监听端口"
    echo -e "  - iptables -L -n  # 查看防火墙规则"
    echo -e "  - fail2ban-client status  # 查看fail2ban状态"
}

# 执行主函数
main "$@"
