服务器安全加固策略.md

Windows

配置日志

应用程序日志、安全日志和系统上传日志审计,日志留存时间需满足6个月。

解决方案:建议更改日志存储路径,自定义存够此类型日志6个月的存储空间,勾选“日志满时将其存档,不要覆盖”;并将服务器日志发送至日志审计,管理员定期查看日志审计记录,确保日志可满足存放6个月以上。

1. 创建日志存储目录

(应用程序日志Application、安全日志Security、系统日志System)

image-20260109145725054

创建指定的 3 个目录

复制默认事件日志目录 %SystemRoot%\System32\winevt\Logs 的 ACL

把目录所有者改成 SYSTEM,并确保 NT SERVICE\EventLog 有完全控制权限

# 以管理员身份运行 PowerShell

$sourceFolder = "$env:SystemRoot\System32\winevt\Logs"
$targetFolders = @(
   "E:\WindowsLogs\Application",
   "E:\WindowsLogs\Security",
   "E:\WindowsLogs\System"
)

# 读取默认事件日志目录 ACL
$sourceAcl = Get-Acl -Path $sourceFolder -Audit -AllCentralAccessPolicies

foreach ($folder in $targetFolders) {
   # 1. 创建目录
   if (-not (Test-Path -LiteralPath $folder)) {
       New-Item -Path $folder -ItemType Directory -Force | Out-Null
       Write-Host "已创建目录: $folder"
   } else {
       Write-Host "目录已存在: $folder"
   }

   # 2. 复制默认 ACL
   Set-Acl -Path $folder -AclObject $sourceAcl -ClearCentralAccessPolicy

   # 3. 设置所有者为 SYSTEM
   $acl = Get-Acl -Path $folder -Audit -AllCentralAccessPolicies
   $acl.SetOwner([System.Security.Principal.NTAccount]::new("SYSTEM"))

   # 4. 确保 NT SERVICE\EventLog 具有完全控制权限
   $eventLogRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
       "NT SERVICE\EventLog",
       "FullControl",
       "ContainerInherit,ObjectInherit",
       "None",
       "Allow"
   )
   $acl.SetAccessRule($eventLogRule)

   # 5. 写回 ACL
   Set-Acl -Path $folder -AclObject $acl -ClearCentralAccessPolicy

   Write-Host "已完成 ACL 配置: $folder"
}

Write-Host "`n全部完成。下一步去事件查看器里修改日志路径"

2.配置事件日志属性

打开事件查看器

方法1:
Win + R → eventvwr.msc → 回车

方法2:
服务器管理器 → 工具 → 事件查看器

方法3:
开始菜单搜索"事件查看器"

配置应用程序日志

1. 事件查看器
  └─ Windows 日志
    └─ 应用程序(右键) → 属性
2. 在"应用程序 属性"窗口中配置:
┌─────────────────────────────────────────┐
│ 应用程序 属性                           │
├─────────────────────────────────────────┤
│                                         │
│ 常规:                                 │
│   日志路径:                             │
│   E:\WindowsLogs\Application\Application.evtx ← 修改这里
│                                         │
│   最大日志大小(KB):                     │
│   [  5000000 ] KB (约 5 GB)         ← 修改这里
│                                         │
│   当达到最大日志大小时:                 │
│   ○ 按需要覆盖事件(最旧的事件优先)     │
│   ○ 存档日志,不覆盖事件               ← 选择这个 ✅
│   ○ 不覆盖事件(手动清除日志)           │
│                                         │
│   [清除日志]   [确定]   [取消]   [应用]       │
└─────────────────────────────────────────┘
3. 点击"确定"

配置安全日志

1. 事件查看器
  └─ Windows 日志
    └─ 安全(右键) → 属性
2. 配置参数:
┌─────────────────────────────────────────┐
│ 安全 属性                               │
├─────────────────────────────────────────┤
│                                         │
│ 日志路径:                               │
│ E:\WindowsLogs\Security\Security.evtx │
│                                         │
│ 最大日志大小(KB):                       │
│ [  10000000 ] KB (约 10 GB)         │ ← 安全日志通常最大
│                                         │
│ 当达到最大日志大小时:                   │
│ ☑ 存档日志,不覆盖事件                 │ ✅
│                                         │
│ [确定]                                 │
└─────────────────────────────────────────┘
3. 点击"确定"

配置系统日志

1. 事件查看器
  └─ Windows 日志
    └─ 系统(右键) → 属性
2. 配置参数:
┌─────────────────────────────────────────┐
│ 系统 属性                               │
├─────────────────────────────────────────┤
│                                         │
│ 日志路径:                               │
│ E:\WindowsLogs\System\System.evtx     │
│                                         │
│ 最大日志大小(KB):                       │
│ [  3000000 ] KB (约 3 GB)           │
│                                         │
│ 当达到最大日志大小时:                   │
│ ☑ 存档日志,不覆盖事件                 │ ✅
│                                         │
│ [确定]                                 │
└─────────────────────────────────────────┘
3. 点击"确定"

重启事件日志服务

#服务管理器重启
services.msc → Windows Event Log → 重新启动

重启后结果:

密码复杂度+有效期

步骤 1:打开本地安全策略
方式一:运行命令
Win + R → 输入:secpol.msc → 回车
方式二:服务器管理器
服务器管理器 → 工具 → 本地安全策略

步骤 2:配置密码策略
2.1 展开策略路径
本地安全策略
└── 账户策略
  └── 密码策略

2.2 配置各项策略

策略项设置值说明
密码必须符合复杂性要求已启用✅ 启用复杂度检查
密码长度最小值8✅ 最少8个字符
密码最长使用期限90✅ 90天后过期
用可还原的加密来存储密码已禁用⚠️ 禁用
2.3 详细配置步骤
① 密码必须符合复杂性要求
1. 双击 "密码必须符合复杂性要求"
2. 选择 "已启用"
3. 点击 "应用" → "确定"
② 密码长度最小值
1. 双击 "密码长度最小值"
2. 设置为:8
3. 点击 "应用" → "确定"
③ 密码最长使用期限
1. 双击 "密码最长使用期限"
2. 设置为:90 天
3. 点击 "应用" → "确定"
步骤 3:应用策略
立即强制更新
Win + R → 输入:cmd → 以管理员身份运行

执行命令:
gpupdate /force

密码复杂度 + 有效期(域控服务器)

步骤 1:打开组策略管理
Win + R → 输入:gpmc.msc → 回车

步骤 2:配置域密码策略
方式一(推荐):
直接编辑 “Default Domain Policy”

方式二:
新建一个域级 GPO(链接到域根),
并确保其优先级高于 Default Domain Policy

2.1 配置路径

计算机配置 └── Windows 设置 └── 安全设置 └── 账户策略 └── 密码策略

2.2 配置各项策略

策略项设置值说明
密码必须符合复杂性要求已启用✅ 启用复杂度检查
密码长度最小值8✅ 最少 8 个字符
密码最长使用期限90✅ 90 天后过期
用可还原的加密来存储密码已禁用⚠️ 禁用
2.3 详细配置步骤

① 密码必须符合复杂性要求
1. 双击 "密码必须符合复杂性要求"
2. 选择 "已启用"
3. 点击 "应用" → "确定"

② 密码长度最小值
1. 双击 "密码长度最小值"
2. 设置为:8
3. 点击 "应用" → "确定"

③ 密码最长使用期限
1. 双击 "密码最长使用期限"
2. 设置为:90 天
3. 点击 "应用" → "确定"

④ 用可还原的加密来存储密码
1. 双击 "用可还原的加密来存储密码"
2. 选择 "已禁用"
3. 点击 "应用" → "确定"
  1. 应用策略
gpupdate /force
  1. 验证结果
PowerShell(管理员)执行:
Get-ADDefaultDomainPasswordPolicy

锁定策略、连接超时

应具有登录失败处理功能,配置并启用结束会话、限制非法登录次数和当登录连接超时自动退出等相关措施;就在密码策略的下面就有锁定策略

远程管理指定安全层

当进行远程管理时,应采取必要措施,防止鉴别信息在网络传输过程中被窃听;

对用户分配账户和权限

应对登录的用户分配账户和权限;(创建系统管理员、安全管理员、审计管理员) 只需要做两件事:重命名admin,三权分立 进入“计算机管理—本地用户和组—用户

安全审计功能

应启用安全审计功能,审计覆盖到每个用户,对重要的用户行为和重要安全事件进行审计;管理工具-账户策略-本地策略-审核策略【配置密码的下面】

审计记录应包括事件的日期和时间、用户、事件类型、事件是否成功及其他与审计相关的信息;右键“计算机”-管理-事件查看器-windows日志-应用程序/安全/系统

及时清理存放在系统中的用户鉴别信息

及时清理存放在系统中的用户鉴别信息,防止信息外泄,被黑客利用 管理工具—本地安全策略—本地策略—安全选项:关机:清除虚拟内存页面文件 【其实就在配置密码策略的下面,所以配置完了话不要关闭,很多配置其实都是在一个页面】

Linux

服务器密码复杂度+有效期

解决方案:Linux服务器在/etc/pam.d/system-auth配置文件中配置密码最小长度为8位,引用pwquality.so模块,配置密码必须由大小写字母、数字、特殊字符中三种或三种以上, 密码有效期为90天。

手动配置步骤:

一、安装必要的软件包
# 检查是否已安装 pwquality
rpm -qa | grep libpwquality

# 如果未安装,执行安装
dnf install -y libpwquality

二、检查 authselect 状态
# 查看当前 authselect 配置
authselect current

# 检查当前配置是否完整
authselect check

1. 如果 authselect check 返回正常,可继续配置。
2. 未启用 authselect,只要 PAM 文件中已经加载了 pam_pwquality.so,就可以继续按照手工方式配置。

#三、确认 pam_pwquality 模块已在 PAM 中启用
grep pam_pwquality.so /etc/pam.d/system-auth /etc/pam.d/password-auth
#如果能看到类似下面的行,说明密码质量模块已经启用,可以继续按照手工方式配置
#password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=
#配置root用户也遵守密码复杂度
sed -i 's/pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=/pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type= enforce_for_root/' /etc/pam.d/system-auth
sed -i 's/pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=/pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type= enforce_for_root/' /etc/pam.d/password-auth

#未找到 pam_pwquality.so,说明模块未启用,需要手工补充 PAM 配置。
#分别编辑两个文件,在 password 段、pam_unix.so 之前加入:
#vim /etc/pam.d/system-auth
#vim /etc/pam.d/password-auth
#password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type= enforce_for_root




四、配置密码复杂度要求
# 备份原文件
cp /etc/security/pwquality.conf /etc/security/pwquality.conf.bak.$(date +%F)

# 编辑文件
vim /etc/security/pwquality.conf
# 密码最小长度 8 位
minlen = 8
# 至少包含 3 种字符类型(大写、小写、数字、特殊字符)
minclass = 3
# 新密码中最多有 3 个字符与旧密码相同
difok = 3
# 禁止使用用户名
usercheck = 1
# 启用字典检查
dictcheck = 1


#1. 这里使用 minclass = 3,表示四类字符中至少满足三类即可。
#2. 不再同时写 dcredit=-1 ucredit=-1 lcredit=-1 ocredit=-1,
否则会变成“每类都至少 1 个”,与“至少 3 类”目标冲突。

五、配置密码有效期 90 天
# 备份
cp /etc/login.defs /etc/login.defs.bak.$(date +%F)

# 编辑
vim /etc/login.defs
PASS_MAX_DAYS 90
PASS_MIN_DAYS 0
PASS_WARN_AGE 7
PASS_MIN_LEN 8


#说明:
#1. /etc/login.defs 主要影响新创建用户的默认密码时效策略。
#2. 已存在用户需要使用 chage 单独调整。

六、对已存在的用户修改密码策略
# 查看当前 root 用户密码策略
chage -l root

# 为 root 设置密码有效期 90 天
chage -M 90 -m 0 -W 7 root

# 批量修改所有普通用户(UID >= 1000,排除 nobody)
for user in $(awk -F: '$3>=1000 && $3!=65534 {print $1}' /etc/passwd); do
chage -M 90 -m 0 -W 7 "$user"
echo "已设置用户 $user 的密码策略"
done

参数说明

pwquality 参数
参数说明推荐值
minlen密码最小长度8
minclass至少满足的字符类型数3
difok与旧密码至少不同的字符数3
usercheck禁止使用用户名相关内容1
dictcheck启用字典检查1
enforce_for_root对 root 生效启用
login.defs 参数
参数说明推荐值
PASS_MAX_DAYS密码最大有效期90
PASS_MIN_DAYS两次修改最小间隔0
PASS_WARN_AGE过期前告警天数7
PASS_MIN_LEN最小长度默认值8

验证配置

1. 检查 PAM 模块是否已加载,并确认是否启用了 root 强制检查
grep pam_pwquality.so /etc/pam.d/system-auth /etc/pam.d/password-auth
2. 检查 pwquality 配置
grep -v '^#' /etc/security/pwquality.conf | grep -v '^$'
3. 检查密码有效期默认配置
grep PASS_ /etc/login.defs | grep -v '^#'
4. 检查 root 用户密码策略
chage -l root

测试密码复杂度

# 创建测试用户
useradd testuser

# 设置密码
passwd testuser

自动化脚本

password_policy_anolis89.sh

#!/bin/bash
#########################################################################
# Script Name: password_policy_anolis89.sh
# Description: Anolis 8.9 密码复杂度和有效期配置脚本
# Author: OpenAI
# Version: 1.0
# Notes:
# 1. 适用于 Anolis 8.9 本地账户场景
# 2. 不依赖 authselect;即使未启用 authselect 也可执行
# 3. 若服务器已接入 AD/IPA/SSSD/realm,请先人工确认后再执行
#########################################################################

set -euo pipefail

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

# 参数定义
MINLEN=8
MINCLASS=3
DIFOK=3
PASS_MAX_DAYS=90
PASS_MIN_DAYS=0
PASS_WARN_AGE=7
PASS_MIN_LEN=8
RETRY=3

BACKUP_DIR="/root/password_policy_backup_$(date +%Y%m%d_%H%M%S)"
PWQUALITY_CONF="/etc/security/pwquality.conf"
LOGIN_DEFS="/etc/login.defs"

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"
}

check_root() {
if [ "$(id -u)" -ne 0 ]; then
log_error "此脚本必须以 root 用户运行。"
exit 1
fi
}

check_os() {
log_step "检查系统版本"
if [ ! -f /etc/os-release ]; then
log_error "无法识别系统版本:/etc/os-release 不存在"
exit 1
fi

. /etc/os-release

if [[ "${VERSION_ID:-}" != 8* ]]; then
log_error "当前系统版本为 ${VERSION_ID:-unknown},此脚本仅适用于 Anolis/RHEL 8 系。"
exit 1
fi

log_info "当前系统:${PRETTY_NAME:-unknown}"
}

check_managed_auth() {
log_step "检查是否接入集中认证(realm/IPA)"

if command -v realm >/dev/null 2>&1; then
if realm list 2>/dev/null | grep -q '^realm-name:'; then
log_error "检测到系统已接入 realm/AD/IPA,请先人工确认认证方案后再修改 PAM。"
exit 1
fi
fi

if [ -f /etc/ipa/default.conf ]; then
log_error "检测到 IPA 客户端配置,请先人工确认认证方案后再修改 PAM。"
exit 1
fi

log_info "未检测到集中认证接入,继续执行。"
}

install_package() {
log_step "检查并安装 libpwquality"
if rpm -q libpwquality >/dev/null 2>&1; then
log_info "libpwquality 已安装"
else
dnf install -y libpwquality
log_info "libpwquality 安装完成"
fi
}

check_authselect() {
log_step "检查 authselect 状态"

if command -v authselect >/dev/null 2>&1; then
log_info "authselect current 输出:"
authselect current || true
echo

log_info "authselect check 输出:"
authselect check || true
echo

log_warn "本脚本不依赖 authselect;只要 PAM 中已加载 pam_pwquality.so,或允许插入该模块,即可继续执行。"
else
log_warn "系统未安装 authselect,继续按手工 PAM 配置方式处理。"
fi
}

backup_files() {
log_step "备份配置文件"
mkdir -p "${BACKUP_DIR}"

for file in \
/etc/pam.d/system-auth \
/etc/pam.d/password-auth \
"${PWQUALITY_CONF}" \
"${LOGIN_DEFS}"
do
if [ -f "$file" ]; then
cp -a "$file" "${BACKUP_DIR}/"
log_info "已备份:$file"
fi
done

log_info "备份目录:${BACKUP_DIR}"
}

ensure_pam_pwquality() {
local file="$1"
local desired="password requisite pam_pwquality.so try_first_pass local_users_only retry=${RETRY} authtok_type= enforce_for_root"

if [ ! -f "$file" ]; then
log_error "PAM 文件不存在:$file"
exit 1
fi

if grep -q 'pam_pwquality\.so' "$file"; then
log_info "$file 已存在 pam_pwquality.so,补齐/规范化参数"
sed -ri '/pam_pwquality\.so/c\'"$desired" "$file"
else
log_warn "$file 未找到 pam_pwquality.so,自动插入到 pam_unix.so 之前"
awk -v desired="$desired" '
BEGIN { inserted=0 }
{
if (!inserted && $0 ~ /^[[:space:]]*password[[:space:]]+.*pam_unix\.so/) {
print desired
inserted=1
}
print
}
END {
if (!inserted) print desired
}
' "$file" > "${file}.tmp"
mv "${file}.tmp" "$file"
fi
}

configure_pam() {
log_step "配置 PAM 中的 pam_pwquality.so"
ensure_pam_pwquality "/etc/pam.d/system-auth"
ensure_pam_pwquality "/etc/pam.d/password-auth"
log_info "PAM 配置完成"
}

set_or_add_eq() {
local file="$1"
local key="$2"
local value="$3"

if grep -Eq "^[[:space:]]*${key}[[:space:]]*=" "$file"; then
sed -ri "s|^[[:space:]]*${key}[[:space:]]*=.*|${key} = ${value}|g" "$file"
else
echo "${key} = ${value}" >> "$file"
fi
}

set_or_add_space() {
local file="$1"
local key="$2"
local value="$3"

if grep -Eq "^[[:space:]]*${key}[[:space:]]+" "$file"; then
sed -ri "s|^[[:space:]]*${key}[[:space:]]+.*|${key} ${value}|g" "$file"
else
echo "${key} ${value}" >> "$file"
fi
}

configure_pwquality() {
log_step "配置 ${PWQUALITY_CONF}"

touch "${PWQUALITY_CONF}"

# 删除可能与 minclass=3 冲突的显式信用配置
sed -ri '/^[[:space:]]*(dcredit|ucredit|lcredit|ocredit)[[:space:]]*=/d' "${PWQUALITY_CONF}"

set_or_add_eq "${PWQUALITY_CONF}" "minlen" "${MINLEN}"
set_or_add_eq "${PWQUALITY_CONF}" "minclass" "${MINCLASS}"
set_or_add_eq "${PWQUALITY_CONF}" "difok" "${DIFOK}"
set_or_add_eq "${PWQUALITY_CONF}" "usercheck" "1"
set_or_add_eq "${PWQUALITY_CONF}" "dictcheck" "1"

log_info "pwquality 配置完成"
}

configure_login_defs() {
log_step "配置 ${LOGIN_DEFS}"

set_or_add_space "${LOGIN_DEFS}" "PASS_MAX_DAYS" "${PASS_MAX_DAYS}"
set_or_add_space "${LOGIN_DEFS}" "PASS_MIN_DAYS" "${PASS_MIN_DAYS}"
set_or_add_space "${LOGIN_DEFS}" "PASS_WARN_AGE" "${PASS_WARN_AGE}"
set_or_add_space "${LOGIN_DEFS}" "PASS_MIN_LEN" "${PASS_MIN_LEN}"

log_info "login.defs 配置完成"
}

apply_password_policy() {
log_step "为现有用户应用密码有效期策略"

log_info "当前 root 用户密码策略:"
chage -l root || true
echo

chage -M "${PASS_MAX_DAYS}" -m "${PASS_MIN_DAYS}" -W "${PASS_WARN_AGE}" root
log_info "已为 root 设置密码有效期"

while IFS=: read -r user _ uid _ _ _ _; do
if [ "$uid" -ge 1000 ] && [ "$uid" -ne 65534 ]; then
chage -M "${PASS_MAX_DAYS}" -m "${PASS_MIN_DAYS}" -W "${PASS_WARN_AGE}" "$user"
log_info "已设置用户 $user 的密码策略"
fi
done < /etc/passwd
}

verify_configuration() {
log_step "验证配置"

echo "===== PAM 配置 ====="
grep pam_pwquality.so /etc/pam.d/system-auth /etc/pam.d/password-auth || true
echo

echo "===== pwquality 配置 ====="
grep -Ev '^[[:space:]]*#|^[[:space:]]*$' "${PWQUALITY_CONF}" || true
echo

echo "===== login.defs 配置 ====="
grep -E '^PASS_(MAX_DAYS|MIN_DAYS|WARN_AGE|MIN_LEN)' "${LOGIN_DEFS}" || true
echo

echo "===== root 用户密码策略 ====="
chage -l root || true
echo
}

show_summary() {
log_step "配置完成摘要"
echo "最小密码长度: ${MINLEN}"
echo "至少字符类型数: ${MINCLASS}"
echo "与旧密码最少不同字符数: ${DIFOK}"
echo "密码最大有效期: ${PASS_MAX_DAYS} 天"
echo "密码最小修改间隔: ${PASS_MIN_DAYS} 天"
echo "密码到期前警告: ${PASS_WARN_AGE} 天"
echo "备份目录: ${BACKUP_DIR}"
echo
log_info "脚本执行完成"
}

main() {
check_root
check_os
check_managed_auth
install_package
check_authselect
backup_files
configure_pam
configure_pwquality
configure_login_defs
apply_password_policy
verify_configuration
show_summary
}

main "$@"

只给 root 应用已有账户时效策略:(配置密码有效期时跳过root用户)

APPLY_TO_USERS=root ./password_policy_anolis89.sh

配置后验证清单

# ✅ 检查 PAM 配置
grep pam_pwquality.so /etc/pam.d/system-auth
# ✅ 检查 pwquality 配置
cat /etc/security/pwquality.conf | grep -v '^#' | grep -v '^$'
# ✅ 检查密码有效期
grep PASS_ /etc/login.defs | grep -v '^#'
# ✅ 检查root用户密码策略
chage -l root

# ✅ 测试密码复杂度(创建测试用户)
useradd testpwd
passwd testpwd # 尝试输入 Test@123
# ✅ 检查用户密码策略
chage -l testpwd
# 为单个用户配置密码有效期
chage -M 90 -m 0 -W 7 username
# 批量配置多个用户
for user in user1 user2 user3; do
chage -M 90 -m 0 -W 7 "$user"
echo "已配置用户: $user"
done
# ✅ 清理测试用户
userdel -r testpwd

Linux日志审计

linux服务器开启日志审计功能,可对audit日志、messages日志、cron日志、secure日志进行记录,服务器本地日志审计时间需满足6个月

解决方案:Linux服务器配置日志轮询,既以周为单位轮询 26 次,即 182天(6个月左右),每周压缩保存日志,日志文件以日期作为扩展名,忽略错误,忽略空文件,延迟压缩,最终达到本地日志保存的目的,保证日志存储时间达到6个月以上。

手动配置方案:

手动配置

配置前检查

# 查看系统版本
cat /etc/os-release
cat /etc/redhat-release
# 一、安装依赖包
dnf install -y rsyslog logrotate audit
# 检查 rsyslog 服务
systemctl status rsyslog
# 检查 auditd 服务
systemctl status auditd
# 测试 rsyslog 配置语法
rsyslogd -N1
# 查看 SELinux 状态
getenforce
# 一、备份原配置
cp /etc/logrotate.d/syslog /etc/logrotate.d/syslog.bak.$(date +%Y%m%d)
# 二、配置 rsyslog 类日志轮转(messages / secure / cron / maillog)
cat > /etc/logrotate.d/syslog << 'EOF'
/var/log/cron
/var/log/maillog
/var/log/messages
/var/log/secure
{
weekly
rotate 26
create 0600 root root
compress
delaycompress
missingok
notifempty
dateext
dateformat -%Y%m%d
sharedscripts
postrotate
/bin/kill -HUP $(cat /run/rsyslogd.pid 2>/dev/null) 2>/dev/null || true
endscript
}
EOF

# 测试 logrotate 配置
logrotate -dv /etc/logrotate.d/syslog

#三、配置 audit 日志保留(audit.log)
# 备份
cp /etc/audit/auditd.conf /etc/audit/auditd.conf.bak.$(date +%F)

# 编辑
vim /etc/audit/auditd.conf

log_file = /var/log/audit/audit.log
log_format = RAW
flush = INCREMENTAL_ASYNC
freq = 100

# 单个 audit 日志文件最大 100 MB,可按实际调整
max_log_file = 100

# 关键:保留旧日志,不覆盖
max_log_file_action = keep_logs

# 建议设置空间预警
space_left = 25%
space_left_action = email

admin_space_left = 10%
admin_space_left_action = single

disk_full_action = single
disk_error_action = syslog



# 重启 rsyslog
systemctl restart rsyslog

systemctl enable auditd
service auditd restart

验证配置

# 检查 rsyslog 配置
rsyslogd -N1

# 检查 logrotate
logrotate -dv /etc/logrotate.d/syslog | head -20

# 查看 auditd 关键配置
grep -E '^(log_file|max_log_file|max_log_file_action|space_left|admin_space_left|disk_full_action|disk_error_action|flush|freq)' /etc/audit/auditd.conf

# 写入测试日志
logger "Final verification - $(date)"
logger -p cron.info "Final verification - cron"
logger -p auth.info "Final verification - auth"

# 查看 syslog 类日志
tail -2 /var/log/messages
tail -2 /var/log/cron
tail -2 /var/log/secure

# 查看 auditd 状态
auditctl -s
ls -lh /var/log/audit/

自动化脚本:

setup_log_rotation_anolis89.sh

#!/bin/bash
# Anolis 8.9 日志留存自动化脚本
# 说明:
# 1. messages / secure / cron / maillog 使用 logrotate,每周轮转,保留 26 周
# 2. audit 日志使用 auditd.conf 的 keep_logs 机制,不并入 syslog 轮转
# 3. 默认只做配置与语法验证,不强制轮转
#
# 可选环境变量:
# ROTATE_WEEKS=26
# AUDIT_MAX_LOG_FILE_MB=100
# AUDIT_SPACE_LEFT=25%
# AUDIT_ADMIN_SPACE_LEFT=10%
# FORCE_ROTATE_TEST=no # yes / no

set -Eeuo pipefail

ROTATE_WEEKS="${ROTATE_WEEKS:-26}"
AUDIT_MAX_LOG_FILE_MB="${AUDIT_MAX_LOG_FILE_MB:-100}"
AUDIT_SPACE_LEFT="${AUDIT_SPACE_LEFT:-25%}"
AUDIT_ADMIN_SPACE_LEFT="${AUDIT_ADMIN_SPACE_LEFT:-10%}"
FORCE_ROTATE_TEST="${FORCE_ROTATE_TEST:-no}"

BACKUP_DIR="/root/log_policy_backup_$(date +%Y%m%d_%H%M%S)"
SYSLOG_ROTATE_CONF="/etc/logrotate.d/syslog"
AUDIT_CONF="/etc/audit/auditd.conf"

GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m'

log_info() { echo -e "${GREEN}[INFO]${NC} $*"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
log_error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
log_step() { echo -e "${BLUE}[STEP]${NC} $*"; }

die() {
log_error "$*"
exit 1
}

require_root() {
[[ "$(id -u)" -eq 0 ]] || die "请以 root 用户运行此脚本。"
}

detect_os() {
log_step "检查操作系统版本"
[[ -f /etc/os-release ]] || die "/etc/os-release 不存在,无法识别系统。"

. /etc/os-release

if [[ "${ID:-}" != "anolis" ]]; then
log_warn "检测到 ID=${ID:-unknown},不是标准 Anolis。将继续按 RHEL 8 兼容方式执行。"
fi

if [[ ! "${VERSION_ID:-}" =~ ^8(\.|$) ]]; then
die "当前系统版本为 ${VERSION_ID:-unknown},此脚本仅适配 Anolis/RHEL 8 系。"
fi

log_info "系统识别通过:${PRETTY_NAME:-Anolis 8}"
}

install_packages() {
log_step "安装依赖包"
dnf -y install rsyslog logrotate audit >/dev/null
log_info "依赖安装完成。"
}

backup_files() {
log_step "备份配置文件"
mkdir -p "${BACKUP_DIR}"
[[ -f "${SYSLOG_ROTATE_CONF}" ]] && cp -a "${SYSLOG_ROTATE_CONF}" "${BACKUP_DIR}/"
[[ -f "${AUDIT_CONF}" ]] && cp -a "${AUDIT_CONF}" "${BACKUP_DIR}/"
log_info "备份完成:${BACKUP_DIR}"
}

enable_services() {
log_step "启用并启动服务"

systemctl enable --now rsyslog >/dev/null
systemctl enable auditd >/dev/null 2>&1 || true
service auditd start >/dev/null 2>&1 || true

systemctl is-active rsyslog >/dev/null || die "rsyslog 启动失败。"
systemctl is-active auditd >/dev/null || log_warn "auditd 当前未处于 active,请检查。"

log_info "服务已处理完成。"
}

create_log_files() {
log_step "创建/校正日志文件"

touch /var/log/messages /var/log/secure /var/log/cron /var/log/maillog
chmod 600 /var/log/messages /var/log/secure /var/log/cron /var/log/maillog
chown root:root /var/log/messages /var/log/secure /var/log/cron /var/log/maillog

mkdir -p /var/log/audit
chmod 700 /var/log/audit
chown root:root /var/log/audit

log_info "日志文件和目录已校正。"
}

write_syslog_rotate_conf() {
log_step "写入 ${SYSLOG_ROTATE_CONF}"

cat > "${SYSLOG_ROTATE_CONF}" <<EOF
/var/log/cron
/var/log/maillog
/var/log/messages
/var/log/secure
{
weekly
rotate ${ROTATE_WEEKS}
create 0600 root root
compress
delaycompress
missingok
notifempty
dateext
dateformat -%Y%m%d
sharedscripts
postrotate
/bin/kill -HUP \$(cat /run/rsyslogd.pid 2>/dev/null) 2>/dev/null || true
endscript
}
EOF

log_info "syslog 轮转配置已写入。"
}

set_kv_eq() {
local file="$1"
local key="$2"
local value="$3"

if grep -Eq "^[[:space:]]*${key}[[:space:]]*=" "$file"; then
sed -ri "s|^[[:space:]]*${key}[[:space:]]*=.*|${key} = ${value}|g" "$file"
else
printf "%s = %s\n" "$key" "$value" >> "$file"
fi
}

configure_auditd() {
log_step "配置 ${AUDIT_CONF}"

touch "${AUDIT_CONF}"

set_kv_eq "${AUDIT_CONF}" "log_file" "/var/log/audit/audit.log"
set_kv_eq "${AUDIT_CONF}" "log_format" "RAW"
set_kv_eq "${AUDIT_CONF}" "flush" "INCREMENTAL_ASYNC"
set_kv_eq "${AUDIT_CONF}" "freq" "100"

set_kv_eq "${AUDIT_CONF}" "max_log_file" "${AUDIT_MAX_LOG_FILE_MB}"
set_kv_eq "${AUDIT_CONF}" "max_log_file_action" "keep_logs"

set_kv_eq "${AUDIT_CONF}" "space_left" "${AUDIT_SPACE_LEFT}"
set_kv_eq "${AUDIT_CONF}" "space_left_action" "email"

set_kv_eq "${AUDIT_CONF}" "admin_space_left" "${AUDIT_ADMIN_SPACE_LEFT}"
set_kv_eq "${AUDIT_CONF}" "admin_space_left_action" "single"

set_kv_eq "${AUDIT_CONF}" "disk_full_action" "single"
set_kv_eq "${AUDIT_CONF}" "disk_error_action" "syslog"

log_info "auditd 配置已完成。"
}

pre_checks() {
log_step "基础检查"

echo "===== 系统版本 ====="
cat /etc/os-release
echo

echo "===== rsyslog 服务状态 ====="
systemctl status rsyslog --no-pager || true
echo

echo "===== auditd 服务状态 ====="
service auditd status || systemctl status auditd --no-pager || true
echo

echo "===== rsyslog 语法检查 ====="
rsyslogd -N1 || die "rsyslog 配置语法检查失败。"
echo

echo "===== 当前 SELinux 状态 ====="
getenforce || true
echo

if findmnt /var/log/audit >/dev/null 2>&1; then
log_info "/var/log/audit 已单独挂载。"
else
log_warn "/var/log/audit 未单独挂载。若 audit 量较大,建议单独分区以便保留 6 个月。"
fi
}

restart_services() {
log_step "重启服务"

systemctl restart rsyslog
service auditd restart >/dev/null 2>&1 || true

systemctl is-active rsyslog >/dev/null || die "rsyslog 重启失败。"
systemctl is-active auditd >/dev/null || log_warn "auditd 重启后未处于 active,请检查。"

log_info "服务重启完成。"
}

test_logging() {
log_step "写入测试日志"

logger "Anolis log policy verification - $(date '+%F %T')"
logger -p auth.info "Anolis secure verification - $(date '+%F %T')"
logger -p cron.info "Anolis cron verification - $(date '+%F %T')"
logger -p mail.info "Anolis mail verification - $(date '+%F %T')"

sleep 2

echo "===== messages ====="
tail -3 /var/log/messages || true
echo

echo "===== secure ====="
tail -3 /var/log/secure || true
echo

echo "===== cron ====="
tail -3 /var/log/cron || true
echo

echo "===== maillog ====="
tail -3 /var/log/maillog || true
echo
}

verify_logrotate() {
log_step "验证 logrotate 配置"
logrotate -dv "${SYSLOG_ROTATE_CONF}" | head -30 || true
echo
}

verify_auditd() {
log_step "验证 auditd 配置"

echo "===== auditd 关键配置 ====="
grep -E '^(log_file|log_format|flush|freq|max_log_file|max_log_file_action|space_left|space_left_action|admin_space_left|admin_space_left_action|disk_full_action|disk_error_action)' "${AUDIT_CONF}" || true
echo

echo "===== auditctl -s ====="
auditctl -s || true
echo

echo "===== /var/log/audit ====="
ls -lh /var/log/audit/ || true
echo
}

force_rotate_if_requested() {
if [[ "${FORCE_ROTATE_TEST}" == "yes" ]]; then
log_step "执行强制轮转测试"
logrotate -fv "${SYSLOG_ROTATE_CONF}" || log_warn "强制轮转返回非 0,请人工检查。"
echo
ls -lht /var/log/messages* /var/log/secure* /var/log/cron* /var/log/maillog* 2>/dev/null | head -20 || true
echo
else
log_info "已跳过强制轮转测试。需要时可使用 FORCE_ROTATE_TEST=yes 再运行一次。"
fi
}

show_summary() {
log_step "配置完成摘要"
echo "syslog 轮转周期: weekly"
echo "syslog 保留轮数: ${ROTATE_WEEKS}"
echo "audit 单文件大小: ${AUDIT_MAX_LOG_FILE_MB} MB"
echo "audit 达到上限动作: keep_logs"
echo "备份目录: ${BACKUP_DIR}"
}

main() {
require_root
detect_os
install_packages
backup_files
enable_services
pre_checks
create_log_files
write_syslog_rotate_conf
configure_auditd
restart_services
test_logging
verify_logrotate
verify_auditd
force_rotate_if_requested
show_summary
log_info "全部完成。"
}

main "$@"

测试验证

ls -lh /var/log/{messages,secure,cron,maillog}* && cat /etc/logrotate.d/syslog && hostname -I 

滚动至顶部