Dernière activité 1 month ago

Révision 0c928dbda658e48bbf0c0f71f095bb79052756da

arch_hardening_script.sh Brut
1#!/bin/bash
2
3################################################################################
4# 服务器自动化加固脚本 - 多发行版增强版
5# 作者: Mercas
6# 日期: 2025-11-09
7# 版本: v4.0 Multi-Distro Enhanced
8#
9# 支持的发行版:
10# - Ubuntu/Debian (apt包管理器)
11# - Arch Linux/Manjaro (pacman + AUR支持)
12#
13# 新增功能:
14# - 防火墙: ufw / iptables / nftables 多选一
15# - 入侵防护: fail2ban / sshguard / crowdsec 多选一
16# - AUR助手: 自动安装yay或paru
17# - SSH密钥: ED25519 (替代RSA 4096)
18################################################################################
19
20# ============================================================================
21# 全局配置
22# ============================================================================
23
24LOG_FILE="/var/log/server_hardening_$(date +%Y%m%d_%H%M%S).log"
25BACKUP_DIR="/root/security_backup_$(date +%Y%m%d_%H%M%S)"
26ROLLBACK_DIR="/root/security_rollback_$(date +%Y%m%d_%H%M%S)"
27REPORT_FILE="/root/security_hardening_report_$(date +%Y%m%d_%H%M%S).txt"
28
29# 错误级别
30ERROR_CRITICAL=1
31ERROR_SEVERE=2
32ERROR_WARNING=3
33ERROR_INFO=4
34
35# ============================================================================
36# 发行版检测
37# ============================================================================
38
39detect_distribution() {
40 if [[ -f /etc/os-release ]]; then
41 . /etc/os-release
42 DISTRO_ID="${ID}"
43 DISTRO_NAME="${NAME}"
44 DISTRO_VERSION="${VERSION_ID}"
45 elif [[ -f /etc/lsb-release ]]; then
46 . /etc/lsb-release
47 DISTRO_ID="${DISTRIB_ID}"
48 DISTRO_NAME="${DISTRIB_DESCRIPTION}"
49 DISTRO_VERSION="${DISTRIB_RELEASE}"
50 else
51 DISTRO_ID="unknown"
52 DISTRO_NAME="Unknown Linux"
53 DISTRO_VERSION="unknown"
54 fi
55
56 case "${DISTRO_ID}" in
57 ubuntu)
58 DISTRO_FAMILY="debian"
59 PACKAGE_MANAGER="apt"
60 ;;
61 debian)
62 DISTRO_FAMILY="debian"
63 PACKAGE_MANAGER="apt"
64 ;;
65 arch|manjaro|antergos)
66 DISTRO_FAMILY="arch"
67 PACKAGE_MANAGER="pacman"
68 ;;
69 *)
70 if command -v pacman &> /dev/null; then
71 DISTRO_FAMILY="arch"
72 PACKAGE_MANAGER="pacman"
73 else
74 DISTRO_FAMILY="debian"
75 PACKAGE_MANAGER="apt"
76 fi
77 ;;
78 esac
79
80 echo "检测到发行版: $DISTRO_NAME ($DISTRO_FAMILY)"
81}
82
83# ============================================================================
84# 颜色定义
85# ============================================================================
86
87setup_colors() {
88 if command -v tput &> /dev/null && [[ -n "$TERM" ]]; then
89 RED=$(tput setaf 1 2>/dev/null || echo '\033[0;31m')
90 GREEN=$(tput setaf 2 2>/dev/null || echo '\033[0;32m')
91 YELLOW=$(tput setaf 3 2>/dev/null || echo '\033[1;33m')
92 BLUE=$(tput setaf 4 2>/dev/null || echo '\033[0;34m')
93 CYAN=$(tput setaf 6 2>/dev/null || echo '\033[0;36m')
94 NC=$(tput sgr0 2>/dev/null || echo '\033[0m')
95 else
96 RED='\033[0;31m'
97 GREEN='\033[0;32m'
98 YELLOW='\033[1;33m'
99 BLUE='\033[0;34m'
100 CYAN='\033[0;36m'
101 NC='\033[0m'
102 fi
103}
104
105# ============================================================================
106# 日志函数
107# ============================================================================
108
109log() {
110 echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1" | tee -a "$LOG_FILE"
111}
112
113log_info() {
114 echo -e "${BLUE}[INFO]${NC} $1" | tee -a "$LOG_FILE"
115}
116
117log_warning() {
118 echo -e "${YELLOW}[WARNING]${NC} $1" | tee -a "$LOG_FILE"
119}
120
121log_error() {
122 echo -e "${RED}[ERROR]${NC} $1" | tee -a "$LOG_FILE"
123}
124
125log_success() {
126 echo -e "${GREEN}[SUCCESS]${NC} $1" | tee -a "$LOG_FILE"
127}
128
129log_section() {
130 echo -e "\n${CYAN}========================================${NC}" | tee -a "$LOG_FILE"
131 echo -e "${CYAN}$1${NC}" | tee -a "$LOG_FILE"
132 echo -e "${CYAN}========================================${NC}\n" | tee -a "$LOG_FILE"
133}
134
135log_rollback() {
136 echo -e "${YELLOW}[ROLLBACK]${NC} $1" | tee -a "$LOG_FILE"
137}
138
139# ============================================================================
140# 核心工具函数
141# ============================================================================
142
143check_root() {
144 if [[ $EUID -ne 0 ]]; then
145 log_error "此脚本必须以root权限运行"
146 exit 1
147 fi
148}
149
150handle_error() {
151 local error_level=$1
152 local message=$2
153 local exit_code=${3:-1}
154 local lineno=${4:-0}
155
156 case $error_level in
157 $ERROR_CRITICAL)
158 log_error "[致命错误] $message (行号: $lineno, 退出码: $exit_code)"
159 exit $exit_code
160 ;;
161 $ERROR_SEVERE)
162 log_error "[严重错误] $message (行号: $lineno, 退出码: $exit_code)"
163 if confirm_action "发生严重错误,是否回滚所有更改并退出?"; then
164 execute_rollback
165 exit $exit_code
166 fi
167 ;;
168 $ERROR_WARNING)
169 log_warning "[警告] $message"
170 ;;
171 $ERROR_INFO)
172 log_info "[信息] $message"
173 ;;
174 esac
175}
176
177backup_file() {
178 local file=$1
179 local description=${2:-"备份"}
180
181 if [[ -f "$file" ]]; then
182 mkdir -p "$BACKUP_DIR"
183 local backup_path="$BACKUP_DIR/$(basename "$file").bak"
184 local checksum_file="$backup_path.sha256"
185
186 cp -p "$file" "$backup_path"
187
188 if command -v sha256sum &> /dev/null; then
189 sha256sum "$backup_path" > "$checksum_file"
190 log_info "已备份: $(basename "$file") (SHA256: $(sha256sum --short "$backup_path"))"
191 else
192 log_info "已备份: $(basename "$file")"
193 fi
194
195 echo "$file:$backup_path:$(date +%s)" >> "$ROLLBACK_DIR/rollback_list.txt"
196 fi
197}
198
199init_rollback() {
200 mkdir -p "$ROLLBACK_DIR"
201 touch "$ROLLBACK_DIR/rollback_list.txt"
202 touch "$ROLLBACK_DIR/actions.log"
203 log_info "回滚机制已初始化: $ROLLBACK_DIR"
204}
205
206execute_rollback() {
207 log_rollback "开始执行回滚操作..."
208
209 if [[ ! -f "$ROLLBACK_DIR/rollback_list.txt" ]]; then
210 log_warning "没有回滚记录可执行"
211 return 0
212 fi
213
214 while IFS=: read -r original backup timestamp; do
215 if [[ -f "$backup" ]] && [[ -f "$original" ]]; then
216 cp "$backup" "$original"
217 log_rollback "已还原: $original"
218 fi
219 done < "$ROLLBACK_DIR/rollback_list.txt"
220
221 log_success "回滚操作完成"
222}
223
224record_rollback_action() {
225 local action_type=$1
226 local target=$2
227 local command=$3
228 local timestamp=$(date +%s)
229 echo "$timestamp:$action_type:$target:$command" >> "$ROLLBACK_DIR/actions.log"
230}
231
232confirm_action() {
233 local message=$1
234 if [[ -t 0 ]]; then
235 echo -e "${YELLOW}${message} [y/N]: ${NC}\c"
236 read -n 1 -r
237 echo
238 if [[ ! $REPLY =~ ^[Yy]$ ]]; then
239 return 1
240 fi
241 return 0
242 else
243 log_info "非交互模式: $message - 跳过"
244 return 1
245 fi
246}
247
248check_port_available() {
249 local port=$1
250 local service_name=$2
251
252 if ss -tunlp 2>/dev/null | grep -q ":$port "; then
253 log_warning "端口 $port 已被占用"
254 if ! confirm_action "是否继续使用端口 $port"; then
255 return 1
256 fi
257 fi
258 return 0
259}
260
261# ============================================================================
262# 包管理器抽象层
263# ============================================================================
264
265update_package_list() {
266 case $PACKAGE_MANAGER in
267 apt)
268 apt update -y 2>&1 | tee -a "$LOG_FILE"
269 ;;
270 pacman)
271 pacman -Sy 2>&1 | tee -a "$LOG_FILE"
272 ;;
273 esac
274}
275
276install_package() {
277 local package=$1
278 local description=${2:-"安装软件包"}
279
280 log_info "安装: $package ($description)"
281
282 case $PACKAGE_MANAGER in
283 apt)
284 if dpkg -l 2>/dev/null | grep -q "^ii $package "; then
285 log_info "$package 已安装"
286 return 0
287 fi
288 apt install -y "$package" 2>&1 | tee -a "$LOG_FILE"
289 return ${PIPESTATUS[0]}
290 ;;
291 pacman)
292 if pacman -Qq "$package" &>/dev/null; then
293 log_info "$package 已安装"
294 return 0
295 fi
296 pacman -S --noconfirm "$package" 2>&1 | tee -a "$LOG_FILE"
297 return ${PIPESTATUS[0]}
298 ;;
299 esac
300}
301
302is_package_installed() {
303 local package=$1
304
305 case $PACKAGE_MANAGER in
306 apt)
307 dpkg -l 2>/dev/null | grep -q "^ii $package"
308 ;;
309 pacman)
310 pacman -Qq "$package" &>/dev/null
311 ;;
312 esac
313}
314
315enable_service() {
316 local service=$1
317
318 if command -v systemctl &> /dev/null; then
319 systemctl enable "$service" 2>&1 | tee -a "$LOG_FILE"
320 systemctl start "$service" 2>&1 | tee -a "$LOG_FILE"
321 fi
322}
323
324disable_service() {
325 local service=$1
326
327 if command -v systemctl &> /dev/null; then
328 systemctl stop "$service" 2>&1 | tee -a "$LOG_FILE" || true
329 systemctl disable "$service" 2>&1 | tee -a "$LOG_FILE" || true
330 fi
331}
332
333# ============================================================================
334# AUR助手安装
335# ============================================================================
336
337install_aur_helper() {
338 log_section "安装AUR助手"
339
340 if ! command -v git &> /dev/null; then
341 log_info "安装git..."
342 pacman -S --noconfirm git 2>&1 | tee -a "$LOG_FILE"
343 fi
344
345 if command -v yay &> /dev/null || command -v paru &> /dev/null; then
346 log_info "AUR助手已安装"
347 return 0
348 fi
349
350 echo -e "${YELLOW}请选择AUR助手:${NC}"
351 echo "1) yay (更流行)"
352 echo "2) paru (功能更丰富)"
353 echo "3) 跳过安装"
354 echo -e "${YELLOW}选择 [1-3]: ${NC}\c"
355 read -p "" aur_choice
356
357 local aur_helper=""
358 local aur_repo=""
359
360 case $aur_choice in
361 1)
362 aur_helper="yay"
363 aur_repo="https://aur.archlinux.org/yay.git"
364 ;;
365 2)
366 aur_helper="paru"
367 aur_repo="https://aur.archlinux.org/paru.git"
368 ;;
369 3)
370 log_info "跳过AUR助手安装"
371 return 0
372 ;;
373 *)
374 log_warning "无效选择"
375 return 1
376 ;;
377 esac
378
379 # 确保base-devel已安装
380 log_info "安装构建依赖..."
381 pacman -S --needed --noconfirm base-devel 2>&1 | tee -a "$LOG_FILE"
382
383 # 克隆并安装AUR助手
384 local temp_dir=$(mktemp -d)
385 cd "$temp_dir"
386
387 log_info "从AUR安装 $aur_helper..."
388 git clone "$aur_repo" 2>&1 | tee -a "$LOG_FILE"
389 cd "$aur_helper"
390
391 if makepkg -si --noconfirm 2>&1 | tee -a "$LOG_FILE"; then
392 log_success "$aur_helper 安装成功"
393
394 # 记录回滚命令
395 record_rollback_action "aur_helper" "$aur_helper" "pacman -Rns $aur_helper"
396 else
397 log_error "$aur_helper 安装失败"
398 rm -rf "$temp_dir"
399 return 1
400 fi
401
402 rm -rf "$temp_dir"
403
404 # 验证安装
405 if command -v $aur_helper &> /dev/null; then
406 log_success "AUR助手 $aur_helper 已就绪"
407 fi
408}
409
410install_aur_package() {
411 local package=$1
412 local description=${2:-"AUR包"}
413
414 # 优先使用pacman
415 if is_package_installed "$package"; then
416 log_info "$package 已安装"
417 return 0
418 fi
419
420 # 尝试pacman
421 if pacman -S --noconfirm "$package" 2>&1 | tee -a "$LOG_FILE"; then
422 return 0
423 fi
424
425 # 使用AUR助手
426 if command -v yay &> /dev/null; then
427 log_info "使用yay安装 $package..."
428 yay -S --noconfirm "$package" 2>&1 | tee -a "$LOG_FILE"
429 elif command -v paru &> /dev/null; then
430 log_info "使用paru安装 $package..."
431 paru -S --noconfirm "$package" 2>&1 | tee -a "$LOG_FILE"
432 else
433 log_warning "无AUR助手可用,跳过 $package 安装"
434 return 1
435 fi
436}
437
438# ============================================================================
439# 密码策略配置
440# ============================================================================
441
442configure_password_policy() {
443 log_info "配置密码策略..."
444
445 case $PACKAGE_MANAGER in
446 apt)
447 if ! is_package_installed "libpam-pwquality"; then
448 install_package "libpam-pwquality" "密码质量检查"
449 fi
450
451 local pwquality_file="/etc/security/pwquality.conf"
452 backup_file "$pwquality_file"
453
454 if ! grep -q "^minlen = 12" "$pwquality_file" 2>/dev/null; then
455 cat >> "$pwquality_file" << 'EOF'
456
457# 密码安全策略
458minlen = 12
459dcredit = -1
460ucredit = -1
461lcredit = -1
462ocredit = -1
463maxrepeat = 3
464EOF
465 fi
466 ;;
467 pacman)
468 if ! is_package_installed "libpwquality"; then
469 install_package "libpwquality" "密码质量检查库"
470 fi
471
472 local login_defs="/etc/login.defs"
473 if [[ -f "$login_defs" ]]; then
474 backup_file "$login_defs"
475 sed -i 's/^PASS_MAX_DAYS.*/PASS_MAX_DAYS 90/' "$login_defs" 2>/dev/null || true
476 sed -i 's/^PASS_MIN_DAYS.*/PASS_MIN_DAYS 1/' "$login_defs" 2>/dev/null || true
477 sed -i 's/^PASS_WARN_AGE.*/PASS_WARN_AGE 14/' "$login_defs" 2>/dev/null || true
478 fi
479 ;;
480 esac
481
482 log_success "密码策略配置完成"
483}
484
485# ============================================================================
486# 防火墙配置 (支持 ufw / iptables / nftables)
487# ============================================================================
488
489configure_firewall() {
490 log_section "配置防火墙"
491
492 local ssh_port=22
493
494 # 检测SSH端口
495 if [[ -f "/etc/ssh/sshd_config" ]]; then
496 ssh_port=$(grep -E "^Port [0-9]+" /etc/ssh/sshd_config 2>/dev/null | awk '{print $2}' | head -1)
497 ssh_port=${ssh_port:-22}
498 fi
499
500 echo -e "${YELLOW}请选择防火墙方案:${NC}"
501 echo "1) UFW (简单防火墙) - 推荐Ubuntu/新手"
502 echo "2) iptables (传统防火墙) - 通用选择"
503 echo "3) nftables (下一代防火墙) - Arch推荐,更高效"
504 echo "4) 跳过防火墙配置"
505 echo -e "${YELLOW}选择 [1-4]: ${NC}\c"
506 read -p "" firewall_choice
507
508 case $firewall_choice in
509 1)
510 configure_ufw "$ssh_port"
511 ;;
512 2)
513 configure_iptables "$ssh_port"
514 ;;
515 3)
516 configure_nftables "$ssh_port"
517 ;;
518 4)
519 log_info "跳过防火墙配置"
520 ;;
521 *)
522 log_warning "无效选择,使用默认iptables"
523 configure_iptables "$ssh_port"
524 ;;
525 esac
526}
527
528configure_ufw() {
529 local ssh_port=$1
530
531 log_info "配置UFW防火墙..."
532
533 if ! is_package_installed "ufw"; then
534 install_package "ufw" "简单防火墙"
535 fi
536
537 ufw default deny incoming 2>&1 | tee -a "$LOG_FILE"
538 ufw default allow outgoing 2>&1 | tee -a "$LOG_FILE"
539
540 if [[ -t 0 ]]; then
541 echo -e "${YELLOW}SSH端口 (默认$ssh_port): ${NC}\c"
542 read -p "" ssh_port_input
543 ssh_port=${ssh_port_input:-$ssh_port}
544 fi
545
546 ufw allow "$ssh_port/tcp" comment 'SSH' 2>&1 | tee -a "$LOG_FILE"
547
548 if confirm_action "是否开放HTTP(80)端口?"; then
549 ufw allow 80/tcp comment 'HTTP' 2>&1 | tee -a "$LOG_FILE"
550 fi
551
552 if confirm_action "是否开放HTTPS(443)端口?"; then
553 ufw allow 443/tcp comment 'HTTPS' 2>&1 | tee -a "$LOG_FILE"
554 fi
555
556 if [[ -t 0 ]]; then
557 echo "y" | ufw enable 2>&1 | tee -a "$LOG_FILE"
558 else
559 ufw --force enable 2>&1 | tee -a "$LOG_FILE"
560 fi
561
562 ufw status numbered 2>/dev/null | tee -a "$LOG_FILE"
563
564 record_rollback_action "firewall" "ufw" "ufw reset"
565 log "UFW防火墙配置完成"
566}
567
568configure_iptables() {
569 local ssh_port=$1
570
571 log_info "配置iptables防火墙..."
572
573 if ! command -v iptables &> /dev/null; then
574 install_package "iptables" "防火墙工具"
575 fi
576
577 if command -v systemctl &> /dev/null; then
578 systemctl enable iptables 2>/dev/null || true
579 systemctl start iptables 2>/dev/null || true
580 fi
581
582 # 刷新现有规则
583 iptables -F 2>&1 | tee -a "$LOG_FILE" || true
584 iptables -X 2>&1 | tee -a "$LOG_FILE" || true
585
586 # 设置默认策略
587 iptables -P INPUT DROP 2>&1 | tee -a "$LOG_FILE"
588 iptables -P FORWARD DROP 2>&1 | tee -a "$LOG_FILE"
589 iptables -P OUTPUT ACCEPT 2>&1 | tee -a "$LOG_FILE"
590
591 if [[ -t 0 ]]; then
592 echo -e "${YELLOW}SSH端口 (默认$ssh_port): ${NC}\c"
593 read -p "" ssh_port_input
594 ssh_port=${ssh_port_input:-$ssh_port}
595 fi
596
597 # 允许SSH
598 iptables -A INPUT -p tcp --dport "$ssh_port" -j ACCEPT 2>&1 | tee -a "$LOG_FILE"
599
600 # 允许回环
601 iptables -A INPUT -i lo -j ACCEPT 2>&1 | tee -a "$LOG_FILE"
602 iptables -A OUTPUT -o lo -j ACCEPT 2>&1 | tee -a "$LOG_FILE"
603
604 # 允许已建立的连接
605 iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT 2>&1 | tee -a "$LOG_FILE"
606
607 if confirm_action "是否开放HTTP(80)端口?"; then
608 iptables -A INPUT -p tcp --dport 80 -j ACCEPT 2>&1 | tee -a "$LOG_FILE"
609 fi
610
611 if confirm_action "是否开放HTTPS(443)端口?"; then
612 iptables -A INPUT -p tcp --dport 443 -j ACCEPT 2>&1 | tee -a "$LOG_FILE"
613 fi
614
615 # 保存规则
616 mkdir -p /etc/iptables
617 iptables-save > /etc/iptables/iptables.rules 2>&1 | tee -a "$LOG_FILE"
618
619 iptables -L -n 2>/dev/null | tee -a "$LOG_FILE"
620
621 record_rollback_action "firewall" "iptables" "iptables -F"
622 log "iptables防火墙配置完成"
623}
624
625configure_nftables() {
626 local ssh_port=$1
627
628 log_info "配置nftables防火墙..."
629
630 if ! command -v nft &> /dev/null; then
631 install_package "nftables" "下一代防火墙"
632 fi
633
634 # 确保服务已启用
635 if command -v systemctl &> /dev/null; then
636 systemctl enable nftables 2>&1 | tee -a "$LOG_FILE"
637 systemctl start nftables 2>&1 | tee -a "$LOG_FILE"
638 fi
639
640 # 备份现有配置
641 if [[ -f /etc/nftables.conf ]]; then
642 backup_file "/etc/nftables.conf"
643 fi
644
645 if [[ -t 0 ]]; then
646 echo -e "${YELLOW}SSH端口 (默认$ssh_port): ${NC}\c"
647 read -p "" ssh_port_input
648 ssh_port=${ssh_port_input:-$ssh_port}
649 fi
650
651 # 创建nftables配置
652 cat > /etc/nftables.conf << EOF
653#!/usr/bin/nft -f
654
655# 刷新所有规则
656flush ruleset
657
658# 定义表
659table inet filter {
660 # 链定义
661 chain input {
662 type filter hook input priority 0; policy drop;
663
664 # 允许回环
665 iif lo accept
666
667 # 允许已建立的连接
668 ct state established,related accept
669
670 # SSH
671 tcp dport $ssh_port accept
672
673 # HTTP/HTTPS (可选)
674 # tcp dport {80, 443} accept
675
676 # 拒绝其他入站
677 reject with icmpx type administratively-prohibited
678 }
679
680 chain forward {
681 type filter hook forward priority 0; policy drop;
682 }
683
684 chain output {
685 type filter hook output priority 0; policy accept;
686 }
687}
688EOF
689
690 log_info "SSH端口: $ssh_port"
691
692 if confirm_action "是否开放HTTP(80)和HTTPS(443)端口?"; then
693 sed -i 's|# tcp dport {80, 443} accept|tcp dport {80, 443} accept|' /etc/nftables.conf
694 log_info "已添加HTTP/HTTPS规则"
695 fi
696
697 # 测试并加载配置
698 nft -f /etc/nftables.conf 2>&1 | tee -a "$LOG_FILE"
699
700 if [[ $? -eq 0 ]]; then
701 log_success "nftables配置已应用"
702 else
703 log_error "nftables配置失败"
704 return 1
705 fi
706
707 # 显示状态
708 nft list ruleset 2>&1 | tee -a "$LOG_FILE"
709
710 record_rollback_action "firewall" "nftables" "nft flush ruleset"
711 log "nftables防火墙配置完成"
712}
713
714# ============================================================================
715# 入侵防御系统 (支持 fail2ban / sshguard / crowdsec)
716# ============================================================================
717
718install_intrusion_prevention() {
719 log_section "配置入侵防御系统"
720
721 echo -e "${YELLOW}请选择入侵防御方案:${NC}"
722 echo "1) Fail2ban (功能丰富,支持多服务)"
723 echo "2) Sshguard (轻量级,专注SSH)"
724 echo "3) Crowdsec (社区驱动,AI增强)"
725 echo "4) 跳过安装"
726 echo -e "${YELLOW}选择 [1-4]: ${NC}\c"
727 read -p "" ips_choice
728
729 case $ips_choice in
730 1)
731 install_fail2ban
732 ;;
733 2)
734 install_sshguard
735 ;;
736 3)
737 install_crowdsec
738 ;;
739 4)
740 log_info "跳过入侵防御系统安装"
741 ;;
742 *)
743 log_warning "无效选择"
744 ;;
745 esac
746}
747
748install_fail2ban() {
749 log_info "安装Fail2ban..."
750
751 case $PACKAGE_MANAGER in
752 apt)
753 install_package "fail2ban" "入侵防御"
754 ;;
755 pacman)
756 install_package "fail2ban" "入侵防御"
757 ;;
758 esac
759
760 if command -v fail2ban-client &> /dev/null; then
761 configure_fail2ban
762 fi
763}
764
765configure_fail2ban() {
766 log_info "配置Fail2ban..."
767
768 local jail_local="/etc/fail2ban/jail.local"
769 backup_file "$jail_local" 2>/dev/null || true
770
771 cat > "$jail_local" << 'EOF'
772[DEFAULT]
773bantime = 3600
774findtime = 600
775maxretry = 5
776
777[sshd]
778enabled = true
779port = ssh
780filter = sshd
781logpath = /var/log/auth.log
782maxretry = 3
783bantime = 7200
784
785[sshd-ddos]
786enabled = true
787port = ssh
788filter = sshd-ddos
789logpath = /var/log/auth.log
790maxretry = 2
791bantime = 7200
792EOF
793
794 enable_service "fail2ban"
795 sleep 2
796
797 if command -v fail2ban-client &> /dev/null; then
798 fail2ban-client status 2>/dev/null | tee -a "$LOG_FILE"
799 fi
800
801 log_success "Fail2ban配置完成"
802}
803
804install_sshguard() {
805 log_info "安装Sshguard..."
806
807 case $PACKAGE_MANAGER in
808 apt)
809 install_package "sshguard" "SSH入侵防御"
810 ;;
811 pacman)
812 install_package "sshguard" "SSH入侵防御"
813 ;;
814 esac
815
816 if command -v sshguard &> /dev/null; then
817 configure_sshguard
818 fi
819}
820
821configure_sshguard() {
822 log_info "配置Sshguard..."
823
824 if command -v systemctl &> /dev/null; then
825 systemctl enable sshguard 2>&1 | tee -a "$LOG_FILE"
826 systemctl start sshguard 2>&1 | tee -a "$LOG_FILE"
827 fi
828
829 log_success "Sshguard已启动"
830}
831
832install_crowdsec() {
833 log_section "安装Crowdsec"
834
835 log_info "Crowdsec - 社区驱动的入侵防御系统"
836 echo -e "${YELLOW}特点:${NC}"
837 echo "• 社区威胁情报共享"
838 echo "• 轻量级,高性能"
839 echo "• 自动学习正常行为"
840 echo "• 支持多种防火墙集成"
841
842 if ! confirm_action "是否安装Crowdsec?"; then
843 log_info "跳过Crowdsec安装"
844 return 0
845 fi
846
847 case $PACKAGE_MANAGER in
848 apt)
849 # 使用官方安装脚本
850 log_info "从官方源安装Crowdsec..."
851 curl -s https://install.crowdsec.net | sh 2>&1 | tee -a "$LOG_FILE"
852 ;;
853 pacman)
854 # 从AUR安装
855 log_info "从AUR安装Crowdsec..."
856 if ! is_package_installed "crowdsec"; then
857 install_aur_package "crowdsec" "Crowdsec核心"
858 fi
859 if ! is_package_installed "crowdsec-firewall-bouncer"; then
860 install_aur_package "crowdsec-firewall-bouncer" "防火墙联动"
861 fi
862 ;;
863 esac
864
865 if command -v cscli &> /dev/null; then
866 configure_crowdsec
867 fi
868}
869
870configure_crowdsec() {
871 log_info "配置Crowdsec..."
872
873 # 初始化
874 cscli console enable 2>&1 | tee -a "$LOG_FILE"
875
876 # 获取推荐场景
877 log_info "安装推荐场景..."
878 cscli scenarios list 2>&1 | tee -a "$LOG_FILE" | head -20
879
880 # 安装SSH防护
881 log_info "启用SSH防护..."
882 cscli scenarios install crowdsecurity/ssh-bf 2>&1 | tee -a "$LOG_FILE"
883
884 # 安装防火墙bouncer
885 log_info "配置防火墙联动..."
886 case $PACKAGE_MANAGER in
887 apt)
888 if is_package_installed "ufw"; then
889 cscli bouncers add crowdsec-ufw-bouncer 2>&1 | tee -a "$LOG_FILE"
890 elif command -v nft &> /dev/null; then
891 cscli bouncers add crowdsec-nft-bouncer 2>&1 | tee -a "$LOG_FILE"
892 fi
893 ;;
894 pacman)
895 if command -v nft &> /dev/null; then
896 cscli bouncers add crowdsec-nft-bouncer 2>&1 | tee -a "$LOG_FILE"
897 fi
898 ;;
899 esac
900
901 # 启动服务
902 enable_service "crowdsec"
903
904 sleep 2
905
906 # 显示状态
907 cscli metrics 2>&1 | tee -a "$LOG_FILE" | head -20
908
909 log_success "Crowdsec配置完成"
910 log_info "运行 'cscli dashboard setup' 可安装可视化面板"
911}
912
913# ============================================================================
914# 自动安全更新
915# ============================================================================
916
917configure_auto_updates() {
918 log_section "配置自动安全更新"
919
920 case $PACKAGE_MANAGER in
921 apt)
922 if confirm_action "是否启用自动安全更新?"; then
923 if ! is_package_installed "unattended-upgrades"; then
924 install_package "unattended-upgrades" "自动更新"
925 fi
926 echo unattended-upgrades unattended-upgrades/enable_auto_updates boolean true | debconf-set-selections 2>&1 | tee -a "$LOG_FILE"
927 log "自动安全更新已启用"
928 fi
929 ;;
930 pacman)
931 log_warning "Arch Linux不推荐完全自动更新"
932 if confirm_action "是否配置pacman更新通知?"; then
933 local cron_file="/etc/cron.daily/check-updates"
934 cat > "$cron_file" << 'EOF'
935#!/bin/bash
936pacman -Sy 2>/dev/null
937echo "系统检查完成"
938EOF
939 chmod +x "$cron_file"
940 log_info "已配置每日更新检查"
941 fi
942 ;;
943 esac
944}
945
946# ============================================================================
947# 安全审计工具
948# ============================================================================
949
950install_security_tools() {
951 log_section "安装额外安全工具"
952
953 if [[ "$PACKAGE_MANAGER" == "pacman" ]]; then
954 # 确保AUR助手已安装
955 if ! command -v yay &> /dev/null && ! command -v paru &> /dev/null; then
956 if confirm_action "是否安装AUR助手以获取更多安全工具?"; then
957 install_aur_helper
958 fi
959 fi
960 fi
961
962 local tools=()
963
964 case $PACKAGE_MANAGER in
965 apt)
966 tools=("auditd")
967 echo -e "${YELLOW}注意: aide和rkhunter可通过apt安装${NC}"
968 ;;
969 pacman)
970 tools=("auditd")
971 echo -e "${YELLOW}提示: aide和rkhunter可从AUR安装${NC}"
972 ;;
973 esac
974
975 for tool in "${tools[@]}"; do
976 if confirm_action "是否安装 $tool"; then
977 if is_package_installed "$tool"; then
978 log_info "$tool 已安装"
979 continue
980 fi
981 install_package "$tool" "安全工具"
982 enable_service "$tool" 2>/dev/null || true
983 fi
984 done
985
986 # 额外的AUR选项
987 if [[ "$PACKAGE_MANAGER" == "pacman" ]]; then
988 if confirm_action "是否从AUR安装 aide (文件完整性)?"; then
989 install_aur_package "aide" "文件完整性检查"
990 fi
991 if confirm_action "是否从AUR安装 rkhunter (Rootkit检测)?"; then
992 install_aur_package "rkhunter" "Rootkit检测"
993 fi
994 fi
995}
996
997# ============================================================================
998# SSH密钥和用户管理 (使用ED25519)
999# ============================================================================
1000
1001verify_ssh_key_exists() {
1002 local username=$1
1003
1004 if [[ -z "$username" ]]; then
1005 return 1
1006 fi
1007
1008 local user_home=$(eval echo "~$username")
1009 local ssh_dir="$user_home/.ssh"
1010 local authorized_keys="$ssh_dir/authorized_keys"
1011
1012 if [[ -f "$authorized_keys" ]] && [[ -s "$authorized_keys" ]]; then
1013 local key_count=$(grep -c "ssh-" "$authorized_keys" 2>/dev/null || echo 0)
1014 if [[ $key_count -gt 0 ]]; then
1015 log_success "用户 $username 已有 $key_count 个SSH公钥"
1016 return 0
1017 fi
1018 fi
1019 return 1
1020}
1021
1022setup_ssh_key() {
1023 local username=$1
1024 local public_key=$2
1025 local user_home=$(eval echo "~$username")
1026 local ssh_dir="$user_home/.ssh"
1027 local authorized_keys="$ssh_dir/authorized_keys"
1028
1029 mkdir -p "$ssh_dir"
1030 echo "$public_key" > "$authorized_keys"
1031 record_rollback_action "ssh_key" "$username" "rm -f $authorized_keys"
1032 log_success "SSH公钥已设置"
1033}
1034
1035# 优化:使用ED25519替代RSA
1036setup_generate_key() {
1037 local username=$1
1038 local user_home=$(eval echo "~$username")
1039 local ssh_dir="$user_home/.ssh"
1040 local key_file="$ssh_dir/id_ed25519"
1041
1042 mkdir -p "$ssh_dir"
1043 chown "$username:$username" "$ssh_dir"
1044
1045 if [[ ! -f "$key_file" ]]; then
1046 log_info "生成ED25519 SSH密钥对..."
1047 log_info "ED25519: 比RSA更安全更快,256位即可达到4096位RSA的安全性"
1048
1049 record_rollback_action "ssh_keygen" "$username" "rm -f $key_file $key_file.pub"
1050
1051 # 使用ED25519生成密钥
1052 su - "$username" -c "ssh-keygen -t ed25519 -f '$key_file' -C '$username@$(hostname)'"
1053
1054 if [[ -f "$key_file" ]]; then
1055 log_success "ED25519密钥对生成成功"
1056 log_info "私钥文件: $key_file"
1057 log_info "公钥文件: $key_file.pub"
1058 log_warning "请妥善保管私钥文件"
1059
1060 echo -e "${YELLOW}公钥内容 (添加到authorized_keys):${NC}"
1061 cat "$key_file.pub"
1062 echo ""
1063 else
1064 log_error "SSH密钥生成失败,回退到RSA..."
1065 # 回退到RSA
1066 local rsa_key_file="$ssh_dir/id_rsa"
1067 su - "$username" -c "ssh-keygen -t rsa -b 4096 -f '$rsa_key_file' -N '' -C '$username@$(hostname)'"
1068 if [[ -f "$rsa_key_file" ]]; then
1069 log_success "RSA密钥对生成成功"
1070 log_info "密钥文件: $rsa_key_file"
1071 fi
1072 return 1
1073 fi
1074 else
1075 log_info "SSH密钥已存在 ($key_file)"
1076 fi
1077}
1078
1079configure_sudo_settings() {
1080 local username=$1
1081
1082 log_info "配置sudo权限..."
1083
1084 echo -e "${YELLOW}请选择sudo权限级别:${NC}"
1085 echo "1) 完全无密码sudo"
1086 echo "2) 需要密码sudo (推荐)"
1087 echo "3) 仅特定命令无密码"
1088 echo "4) 不配置"
1089 echo -e "${YELLOW}选择 [1-4]: ${NC}\c"
1090 read -p "" sudo_option
1091
1092 local sudoers_file="/etc/sudoers.d/$username"
1093
1094 case $sudo_option in
1095 1)
1096 echo "$username ALL=(ALL) NOPASSWD:ALL" > "$sudoers_file"
1097 chmod 440 "$sudoers_file"
1098 record_rollback_action "sudoers" "$username" "rm -f $sudoers_file"
1099 log_warning "已配置无密码sudo (安全性较低)"
1100 ;;
1101 2)
1102 echo "$username ALL=(ALL) ALL" > "$sudoers_file"
1103 chmod 440 "$sudoers_file"
1104 record_rollback_action "sudoers" "$username" "rm -f $sudoers_file"
1105 log_success "已配置需要密码的sudo"
1106 ;;
1107 3)
1108 echo -e "${YELLOW}输入允许无密码执行的命令: ${NC}\c"
1109 read -p "" sudo_commands
1110 if [[ -n "$sudo_commands" ]]; then
1111 echo "$username ALL=(ALL) NOPASSWD: $sudo_commands" > "$sudoers_file"
1112 chmod 440 "$sudoers_file"
1113 record_rollback_action "sudoers" "$username" "rm -f $sudoers_file"
1114 log_success "已配置限制性sudo"
1115 fi
1116 ;;
1117 *)
1118 log_info "跳过sudo配置"
1119 ;;
1120 esac
1121}
1122
1123manage_users() {
1124 log_section "创建管理用户和配置SSH密钥"
1125
1126 if ! confirm_action "是否创建专用管理用户?"; then
1127 log_warning "跳过用户创建"
1128 return 0
1129 fi
1130
1131 local username=""
1132
1133 if [[ -t 0 ]]; then
1134 echo -e "${YELLOW}请输入新用户名: ${NC}\c"
1135 read -p "" username
1136 else
1137 username="admin"
1138 fi
1139
1140 if [[ -z "$username" ]] || [[ ! "$username" =~ ^[a-z_][a-z0-9_-]*$ ]]; then
1141 handle_error $ERROR_SEVERE "无效的用户名: $username"
1142 return 1
1143 fi
1144
1145 # 检查用户是否存在
1146 if id "$username" &>/dev/null 2>&1; then
1147 log_info "用户 $username 已存在"
1148 else
1149 log_info "创建用户: $username"
1150 useradd -m -s /bin/bash "$username" 2>&1 | tee -a "$LOG_FILE"
1151
1152 if [[ -t 0 ]]; then
1153 echo -e "${YELLOW}为用户 $username 设置密码: ${NC}\c"
1154 passwd "$username"
1155 else
1156 local temp_password=$(openssl rand -base64 32)
1157 echo "$username:$temp_password" | chpasswd
1158 record_rollback_action "password" "$username" "passwd -d $username"
1159 log_warning "临时密码: $temp_password"
1160 fi
1161
1162 case $PACKAGE_MANAGER in
1163 apt)
1164 usermod -aG sudo "$username" 2>&1 | tee -a "$LOG_FILE"
1165 record_rollback_action "usermod" "$username" "gpasswd -d $username sudo"
1166 ;;
1167 pacman)
1168 usermod -aG wheel "$username" 2>&1 | tee -a "$LOG_FILE"
1169 record_rollback_action "usermod" "$username" "gpasswd -d $username wheel"
1170 if [[ -f "/etc/sudoers" ]]; then
1171 if ! grep -q "^%wheel ALL=" /etc/sudoers 2>/dev/null; then
1172 backup_file "/etc/sudoers"
1173 echo "%wheel ALL=(ALL) ALL" >> /etc/sudoers
1174 fi
1175 fi
1176 ;;
1177 esac
1178 fi
1179
1180 log_info "配置SSH密钥..."
1181 local key_configured=false
1182
1183 if [[ -t 0 ]]; then
1184 echo -e "${YELLOW}选择密钥配置方式: ${NC}"
1185 echo "1) 现有公钥"
1186 echo "2) 生成ED25519密钥 (推荐)"
1187 echo "3) 跳过"
1188 echo -e "${YELLOW}选择 [1-3]: ${NC}\c"
1189 read -p "" key_option
1190 else
1191 key_option="3"
1192 fi
1193
1194 case $key_option in
1195 1)
1196 echo -e "${YELLOW}输入SSH公钥: ${NC}\c"
1197 read -p "" public_key
1198 if [[ -n "$public_key" ]] && [[ "$public_key" =~ ^ssh- ]]; then
1199 setup_ssh_key "$username" "$public_key"
1200 key_configured=true
1201 fi
1202 ;;
1203 2)
1204 setup_generate_key "$username"
1205 key_configured=true
1206 ;;
1207 *)
1208 log_info "跳过密钥配置"
1209 ;;
1210 esac
1211
1212 configure_sudo_settings "$username"
1213
1214 local user_home=$(eval echo "~$username")
1215 local ssh_dir="$user_home/.ssh"
1216
1217 if [[ -d "$ssh_dir" ]]; then
1218 chown -R "$username:$username" "$ssh_dir" 2>&1 | tee -a "$LOG_FILE"
1219 chmod 700 "$ssh_dir" 2>&1 | tee -a "$LOG_FILE"
1220 chmod 600 "$ssh_dir/authorized_keys" 2>&1 | tee -a "$LOG_FILE" || true
1221 fi
1222
1223 if id "$username" &>/dev/null; then
1224 log_success "用户 $username 配置成功"
1225 fi
1226
1227 if $key_configured; then
1228 return 0
1229 else
1230 return 1
1231 fi
1232}
1233
1234# ============================================================================
1235# SSH安全加固
1236# ============================================================================
1237
1238validate_ssh_config() {
1239 local ssh_config="/etc/ssh/sshd_config"
1240
1241 if [[ ! -f "$ssh_config" ]]; then
1242 log_error "SSH配置文件不存在"
1243 return 1
1244 fi
1245
1246 log_info "验证SSH配置语法..."
1247
1248 if command -v sshd &> /dev/null; then
1249 if sshd -t 2>&1; then
1250 log_success "SSH配置语法验证通过"
1251 return 0
1252 else
1253 log_error "SSH配置语法验证失败"
1254 return 1
1255 fi
1256 fi
1257 return 0
1258}
1259
1260harden_ssh() {
1261 log_section "SSH安全加固"
1262
1263 local ssh_config="/etc/ssh/sshd_config"
1264 local ssh_port=22
1265 local key_configured=false
1266
1267 if [[ ! -f "$ssh_config" ]]; then
1268 handle_error $ERROR_SEVERE "SSH配置文件不存在"
1269 fi
1270
1271 backup_file "$ssh_config"
1272
1273 ssh_port=$(grep -E "^Port [0-9]+" "$ssh_config" 2>/dev/null | awk '{print $2}' | head -1)
1274 ssh_port=${ssh_port:-22}
1275
1276 log_info "步骤1/3: 配置用户和SSH密钥..."
1277 if manage_users; then
1278 key_configured=true
1279 fi
1280
1281 log_info "步骤2/3: 配置安全参数..."
1282
1283 if [[ -t 0 ]]; then
1284 echo -e "${YELLOW}修改SSH端口($ssh_port)? 输入新端口或留空: ${NC}\c"
1285 read -p "" new_port
1286 if [[ -n "$new_port" ]] && [[ "$new_port" =~ ^[0-9]+$ ]] && [[ "$new_port" -gt 1024 ]] && [[ "$new_port" -lt 65536 ]]; then
1287 if ! check_port_available "$new_port" "SSH"; then
1288 log_warning "端口检查未通过"
1289 else
1290 log_warning "请更新防火墙开放端口 $new_port"
1291 ssh_port=$new_port
1292 fi
1293 fi
1294 fi
1295
1296 if confirm_action "是否禁用SSH root登录?"; then
1297 sed -i "s/^#*PermitRootLogin.*/PermitRootLogin no/" "$ssh_config"
1298 record_rollback_action "ssh_config" "PermitRootLogin" "sed -i 's/^PermitRootLogin.*/PermitRootLogin yes/' $ssh_config"
1299 fi
1300
1301 if $key_configured; then
1302 if confirm_action "SSH密钥已配置,是否禁用密码认证?"; then
1303 sed -i "s/^#*PasswordAuthentication.*/PasswordAuthentication no/" "$ssh_config"
1304 record_rollback_action "ssh_config" "PasswordAuthentication" "sed -i 's/^PasswordAuthentication.*/PasswordAuthentication yes/' $ssh_config"
1305 fi
1306 else
1307 log_warning "SSH密钥未配置,跳过密码认证禁用"
1308 fi
1309
1310 # 添加安全配置
1311 cat >> "$ssh_config" << EOF
1312
1313# 安全加固配置
1314Protocol 2
1315MaxAuthTries 3
1316MaxSessions 2
1317LoginGraceTime 60
1318ClientAliveInterval 300
1319ClientAliveCountMax 2
1320PermitEmptyPasswords no
1321X11Forwarding no
1322UseDNS no
1323EOF
1324
1325 log_info "步骤3/3: 验证并应用配置..."
1326
1327 if ! validate_ssh_config; then
1328 handle_error $ERROR_SEVERE "SSH配置验证失败"
1329 execute_rollback
1330 return 1
1331 fi
1332
1333 if systemctl restart sshd 2>&1 | tee -a "$LOG_FILE"; then
1334 log_success "SSH服务已重启 (端口: $ssh_port)"
1335 else
1336 handle_error $ERROR_SEVERE "SSH服务重启失败"
1337 return 1
1338 fi
1339
1340 log "SSH加固完成"
1341}
1342
1343# ============================================================================
1344# 系统加固
1345# ============================================================================
1346
1347harden_users() {
1348 log_section "用户和权限加固"
1349 configure_password_policy
1350
1351 log_info "锁定系统账户..."
1352 local system_users=("bin" "daemon" "adm" "lp" "sync" "shutdown" "halt" "mail" "news" "uucp" "operator" "games" "gopher" "ftp")
1353
1354 for user in "${system_users[@]}"; do
1355 if id "$user" &>/dev/null 2>&1; then
1356 usermod -L -s /usr/sbin/nologin "$user" 2>/dev/null || true
1357 fi
1358 done
1359
1360 log "用户加固完成"
1361}
1362
1363disable_services() {
1364 log_section "禁用不必要的服务"
1365 local services_to_disable=("avahi-daemon" "cups" "bluetooth")
1366
1367 for service in "${services_to_disable[@]}"; do
1368 if command -v systemctl &> /dev/null; then
1369 if systemctl is-enabled "$service" &>/dev/null 2>&1; then
1370 if confirm_action "是否禁用服务: $service"; then
1371 disable_service "$service"
1372 record_rollback_action "service" "$service" "systemctl enable $service; systemctl start $service"
1373 log_info "已禁用: $service"
1374 fi
1375 fi
1376 fi
1377 done
1378}
1379
1380harden_kernel() {
1381 log_section "内核参数安全配置"
1382 local sysctl_conf="/etc/sysctl.d/99-security.conf"
1383 backup_file "$sysctl_conf" 2>/dev/null || true
1384
1385 log_info "配置内核安全参数..."
1386
1387 cat > "$sysctl_conf" << 'EOF'
1388# IP转发禁用
1389net.ipv4.ip_forward = 0
1390net.ipv6.conf.all.forwarding = 0
1391
1392# SYN cookies保护
1393net.ipv4.tcp_syncookies = 1
1394
1395# 忽略ICMP重定向
1396net.ipv4.conf.all.accept_redirects = 0
1397net.ipv6.conf.all.accept_redirects = 0
1398net.ipv4.conf.default.accept_redirects = 0
1399net.ipv6.conf.default.accept_redirects = 0
1400
1401# 禁用源路由
1402net.ipv4.conf.all.accept_source_route = 0
1403net.ipv6.conf.all.accept_source_route = 0
1404
1405# 记录可疑包
1406net.ipv4.conf.all.log_martians = 1
1407net.ipv4.conf.default.log_martians = 1
1408
1409# 忽略ICMP ping请求
1410net.ipv4.icmp_echo_ignore_broadcasts = 1
1411
1412# 反向路径过滤
1413net.ipv4.conf.all.rp_filter = 1
1414net.ipv4.conf.default.rp_filter = 1
1415
1416# SYN flood保护
1417net.ipv4.tcp_max_syn_backlog = 2048
1418net.ipv4.tcp_synack_retries = 2
1419net.ipv4.tcp_syn_retries = 5
1420EOF
1421
1422 if command -v sysctl &> /dev/null; then
1423 sysctl -p "$sysctl_conf" 2>&1 | tee -a "$LOG_FILE" || log_warning "应用内核参数失败"
1424 fi
1425
1426 log "内核参数配置完成"
1427}
1428
1429harden_filesystem() {
1430 log_section "文件系统权限加固"
1431 log_info "设置重要文件权限..."
1432
1433 local files_to_protect=(
1434 "/etc/ssh/sshd_config:600"
1435 "/etc/passwd:644"
1436 "/etc/shadow:640"
1437 "/etc/group:644"
1438 "/etc/gshadow:600"
1439 )
1440
1441 for file_perm in "${files_to_protect[@]}"; do
1442 local file="${file_perm%:*}"
1443 local perm="${file_perm#*:}"
1444 if [[ -f "$file" ]]; then
1445 chmod "$perm" "$file" 2>&1 | tee -a "$LOG_FILE"
1446 record_rollback_action "chmod" "$file" "chmod 644 $file"
1447 fi
1448 done
1449
1450 log_info "SUID/SGID文件检查..."
1451 if command -v find &> /dev/null; then
1452 find / -perm /6000 -type f 2>/dev/null >> "$LOG_FILE" || true
1453 fi
1454}
1455
1456collect_system_info() {
1457 log_section "收集系统信息"
1458 log_info "操作系统: $(cat /etc/os-release 2>/dev/null | grep PRETTY_NAME | cut -d= -f2 || echo "Unknown")"
1459 log_info "内核版本: $(uname -r)"
1460 log_info "主机名: $(hostname)"
1461 log_info "IP地址: $(hostname -I 2>/dev/null | awk '{print $1}' || echo 'N/A')"
1462}
1463
1464update_system() {
1465 log_section "系统更新"
1466
1467 if confirm_action "是否执行系统更新?"; then
1468 case $PACKAGE_MANAGER in
1469 apt)
1470 apt update -y 2>&1 | tee -a "$LOG_FILE"
1471 apt upgrade -y 2>&1 | tee -a "$LOG_FILE"
1472 apt autoremove -y 2>&1 | tee -a "$LOG_FILE"
1473 ;;
1474 pacman)
1475 pacman -Syu --noconfirm 2>&1 | tee -a "$LOG_FILE"
1476 pacman -Rns $(pacman -Qdtq) --noconfirm 2>/dev/null || true
1477 ;;
1478 esac
1479 log "系统更新完成"
1480 else
1481 log_warning "跳过系统更新"
1482 fi
1483}
1484
1485generate_report() {
1486 log_section "生成安全加固报告"
1487
1488 local os_info=$(cat /etc/os-release 2>/dev/null | grep PRETTY_NAME | cut -d= -f2 || echo "Unknown")
1489 local kernel_info=$(uname -r)
1490 local hostname_info=$(hostname)
1491
1492 cat > "$REPORT_FILE" << EOF
1493================================================================================
1494服务器安全加固报告
1495================================================================================
1496生成时间: $(date)
1497主机名: $hostname_info
1498操作系统: $os_info
1499内核版本: $kernel_info
1500包管理器: $PACKAGE_MANAGER
1501
1502备份目录: $BACKUP_DIR
1503回滚目录: $ROLLBACK_DIR
1504日志文件: $LOG_FILE
1505
1506--------------------------------------------------------------------------------
15071. SSH配置
1508--------------------------------------------------------------------------------
1509$(grep -E "^(Port|PermitRootLogin|PasswordAuthentication)" /etc/ssh/sshd_config 2>/dev/null || echo "N/A")
1510
1511--------------------------------------------------------------------------------
15122. 防火墙状态
1513--------------------------------------------------------------------------------
1514$(case $PACKAGE_MANAGER in
1515 apt) ufw status verbose 2>/dev/null ;;
1516 pacman)
1517 if command -v nft &> /dev/null; then nft list ruleset 2>/dev/null;
1518 else iptables -L -n 2>/dev/null; fi
1519 esac || echo "N/A")
1520
1521--------------------------------------------------------------------------------
15223. 入侵防御系统
1523--------------------------------------------------------------------------------
1524$(command -v fail2ban-client &> /dev/null && fail2ban-client status 2>/dev/null || echo "N/A")
1525
1526--------------------------------------------------------------------------------
15274. 已安装安全工具
1528--------------------------------------------------------------------------------
1529$(case $PACKAGE_MANAGER in
1530 apt) dpkg -l 2>/dev/null | grep -E "fail2ban|ufw|auditd" | awk '{print $2 " " $3}' ;;
1531 pacman) pacman -Q 2>/dev/null | grep -E "fail2ban|crowdsec|nftables|auditd" | head -10 ;;
1532 esac || echo "N/A")
1533
1534--------------------------------------------------------------------------------
15355. AUR助手状态
1536--------------------------------------------------------------------------------
1537$(command -v yay &> /dev/null && echo "yay: 已安装" || echo "yay: 未安装")
1538$(command -v paru &> /dev/null && echo "paru: 已安装" || echo "paru: 未安装")
1539
1540================================================================================
1541EOF
1542
1543 if command -v sha256sum &> /dev/null; then
1544 sha256sum "$REPORT_FILE" > "${REPORT_FILE}.sha256"
1545 fi
1546
1547 log_info "报告已生成: $REPORT_FILE"
1548}
1549
1550# ============================================================================
1551# 主程序
1552# ============================================================================
1553
1554main() {
1555 clear
1556
1557 echo -e "${CYAN}"
1558 cat << "EOF"
1559╔══════════════════════════════════════════════════════════════╗
1560║ 服务器安全加固脚本 (多发行版增强版)
1561║ v4.0 - 支持 Ubuntu + Arch Linux ║
1562║ • 多防火墙选择 (UFW/iptables/nftables)
1563║ • 多入侵防护 (Fail2ban/Sshguard/Crowdsec)
1564║ • AUR助手自动安装 (yay/paru)
1565║ • ED25519 SSH密钥 (替代RSA)
1566╚══════════════════════════════════════════════════════════════╝
1567EOF
1568 echo -e "${NC}"
1569
1570 check_root
1571 detect_distribution
1572 setup_colors
1573 init_rollback
1574
1575 log "开始服务器安全加固..."
1576 log_info "日志: $LOG_FILE | 备份: $BACKUP_DIR"
1577
1578 echo -e "${YELLOW}警告: 此脚本将修改系统配置${NC}"
1579
1580 if ! confirm_action "确认继续?"; then
1581 log "用户取消"
1582 exit 0
1583 fi
1584
1585 collect_system_info
1586 update_system
1587 harden_ssh
1588 configure_firewall
1589 install_intrusion_prevention
1590 harden_users
1591 disable_services
1592 harden_kernel
1593 harden_filesystem
1594 configure_auto_updates
1595 install_security_tools
1596 generate_report
1597
1598 log_section "安全加固完成"
1599
1600 echo -e "${GREEN}"
1601 cat << EOF
1602╔══════════════════════════════════════════════════════════════╗
1603║ 安全加固已完成! ║
1604╚══════════════════════════════════════════════════════════════╝
1605
1606重要提醒:
1607• 备份: $BACKUP_DIR
1608• 回滚: $ROLLBACK_DIR
1609• 日志: $LOG_FILE
1610• 报告: $REPORT_FILE
1611• 建议重启服务器
1612
1613下一步:
1614• 测试SSH登录
1615• 检查防火墙规则
1616• 配置入侵防御
1617
1618EOF
1619 echo -e "${NC}"
1620
1621 if confirm_action "是否重启服务器?"; then
1622 log "5秒后重启..."
1623 sleep 5
1624 reboot
1625 fi
1626}
1627
1628main "$@"
1629