
在当今数字化时代,服务器安全已成为企业信息安全体系的核心支柱。随着网络攻击手段的日益复杂和频繁,传统的被动防御策略已不足以应对多变的安全威胁。Ubuntu Server 作为广泛使用的企业级操作系统,其安全性直接关系到企业核心业务的连续性和数据资产的完整性。
1.1 服务器安全面临的挑战
现代服务器环境面临着多重安全挑战:
1.2 主动安全审计的价值
与传统被动防御不同,主动安全审计通过系统性的检查和分析,在安全问题发生前识别和修复潜在风险。Lynis 作为专业的安全审计工具,提供了全面的安全检查框架,帮助企业:
2.1 Lynis 发展历程与设计哲学
Lynis 由 Cisofy 公司开发和维护,是一款开源的企业级安全审计工具。自2007年发布以来,它已成为 Unix-like 系统安全审计的事实标准。Lynis 的设计哲学基于以下几个核心原则:
2.2 Lynis 系统架构深度解析
Lynis 采用模块化架构,主要组件包括:
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ 主控制脚本 │───▶│ 测试模块 │───▶│ 报告生成器 │
│ (lynis) │ │ (include/*) │ │ (lynis-report) │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ 配置管理系统 │ │ 数据收集器 │ │ 输出处理器 │
│ (default.prf) │ │ (helpers/*) │ │ (formats/*) │
└─────────────────┘ └──────────────────┘ └─────────────────┘核心组件详细说明:
include 目录下的独立测试脚本,每个模块专注于特定的安全检查领域default.prf 定义审计行为的默认参数,支持自定义配置覆盖helpers 目录包含专用的数据收集和验证工具2.3 Lynis 与其他安全工具的对比
在企业安全工具生态中,Lynis 占据独特位置:
工具类别 | 代表工具 | 优势 | 局限性 | 适用场景 |
|---|---|---|---|---|
配置审计 | Lynis | 轻量级、全面、易扩展 | 不提供实时防护 | 定期安全评估、合规检查 |
漏洞扫描 | OpenVAS | 漏洞数据库全面 | 资源消耗大、误报率高 | 已知漏洞检测 |
入侵检测 | AIDE | 文件完整性监控 | 配置复杂、维护成本高 | 入侵事后分析 |
合规管理 | OpenSCAP | 标准符合性验证 | 学习曲线陡峭 | 严格合规要求环境 |
Lynis 的独特价值在于其平衡了全面性和易用性,为系统管理员提供了即开即用的安全审计能力。
3.1 系统环境准备与依赖管理
在 Ubuntu Server 上部署 Lynis 前,需要确保系统环境满足基本要求:
# 更新系统包索引
sudo apt update
# 升级现有软件包到最新版本
sudo apt upgrade -y
# 安装 Lynis 运行所需的基础依赖
sudo apt install -y wget gpg apt-transport-https
# 检查系统架构和版本兼容性
echo "系统架构: $(uname -m)"
echo "Ubuntu 版本: $(lsb_release -d | cut -f2)"
echo "内核版本: $(uname -r)"3.2 多种安装方法详解
方法一:官方仓库安装(推荐用于生产环境)
# 导入 Cisofy 官方 GPG 密钥
wget -O - https://packages.cisofy.com/keys/cisofy-software-public.key | sudo apt-key add -
# 添加 Lynis 官方仓库
echo "deb https://packages.cisofy.com/community/lynis/deb/ stable main" | sudo tee /etc/apt/sources.list.d/cisofy-lynis.list
# 更新包列表并安装 Lynis
sudo apt update
sudo apt install lynis -y
# 验证安装完整性
lynis show version
lynis show help方法二:直接下载安装(适用于隔离环境)
# 创建临时工作目录
WORK_DIR=$(mktemp -d)
cd $WORK_DIR
# 下载最新版 Lynis 压缩包
LATEST_VERSION=$(curl -s https://cisofy.com/downloads/lynis/ | grep -oP 'lynis-[0-9]+\.[0-9]+\.[0-9]+\.tar\.gz' | head -1)
wget "https://downloads.cisofy.com/lynis/$LATEST_VERSION"
# 解压并安装
tar xzf lynis-*.tar.gz
cd lynis
# 验证文件完整性
md5sum -c lynis.md5
sha256sum -c lynis.sha256
# 执行安装(不需要 root 权限,但审计时需要)
./lynis show version
# 创建符号链接到系统 PATH(可选)
sudo ln -s $(pwd)/lynis /usr/local/bin/lynis
# 清理临时文件
cd /
rm -rf $WORK_DIR方法三:源码编译安装(用于定制化需求)
# 克隆开发版本(不推荐生产环境使用)
git clone https://github.com/CISOfy/lynis.git
cd lynis
# 检查特定标签(推荐用于生产)
git fetch --tags
LATEST_TAG=$(git describe --tags $(git rev-list --tags --max-count=1))
git checkout $LATEST_TAG
# 验证发布签名(如果可用)
git verify-tag $LATEST_TAG
# 执行安装前测试
./lynis audit system --quick3.3 安装后配置与验证
完成安装后,需要进行基本配置验证:
# 检查 Lynis 文件完整性
sudo lynis update info
# 验证配置文件加载顺序
sudo lynis show settings
# 测试基本功能
sudo lynis audit system --tests-from-group "malware" --quick
# 创建备份配置
sudo cp /etc/lynis/default.prf /etc/lynis/default.prf.backup
# 检查自定义配置目录
sudo mkdir -p /etc/lynis/custom
sudo chmod 755 /etc/lynis/custom3.4 多实例部署策略
对于大规模 Ubuntu Server 环境,可以考虑集中化部署方案:
#!/bin/bash
# centralized-lynis-deployment.sh
# 用于在多台服务器上批量部署 Lynis
set -e
# 配置参数
LYNIS_VERSION="3.0.8"
INSTALL_DIR="/opt/lynis"
LOG_DIR="/var/log/lynis"
# 服务器列表(实际环境中可以从文件或CMDB读取)
SERVERS=("server1.example.com" "server2.example.com" "server3.example.com")
install_lynis_remote() {
local server=$1
echo "在 $server 上安装 Lynis..."
ssh "admin@$server" << EOF
set -e
sudo apt update
sudo apt install -y wget
sudo mkdir -p $INSTALL_DIR $LOG_DIR
cd /tmp
wget "https://downloads.cisofy.com/lynis/lynis-${LYNIS_VERSION}.tar.gz"
tar xzf lynis-${LYNIS_VERSION}.tar.gz
sudo cp -r lynis/* $INSTALL_DIR/
sudo chmod -R 755 $INSTALL_DIR
sudo ln -sf $INSTALL_DIR/lynis /usr/local/bin/lynis
# 验证安装
$INSTALL_DIR/lynis show version
echo "Lynis 在 $server 上安装完成"
EOF
}
# 批量安装
for server in "${SERVERS[@]}"; do
if install_lynis_remote "$server"; then
echo "✓ $server: 安装成功"
else
echo "✗ $server: 安装失败"
fi
done3.5 容器化部署方案
对于容器化环境,可以创建专用的 Lynis 审计容器:
# Dockerfile for Lynis Auditor
FROM ubuntu:20.04
# 安装基础依赖
RUN apt-get update && \
apt-get install -y \
wget \
tar \
apt-transport-https \
gnupg \
&& rm -rf /var/lib/apt/lists/*
# 安装 Lynis
WORKDIR /opt/lynis
RUN wget https://downloads.cisofy.com/lynis/lynis-3.0.8.tar.gz && \
tar xzf lynis-3.0.8.tar.gz --strip-components=1 && \
rm lynis-3.0.8.tar.gz && \
chmod +x lynis
# 创建挂载点
VOLUME ["/lynis-audit"]
WORKDIR /lynis-audit
# 设置入口点
ENTRYPOINT ["/opt/lynis/lynis"]
CMD ["--help"]构建和使用容器:
# 构建镜像
docker build -t lynis-auditor .
# 运行容器审计主机系统
docker run --rm -it \
--privileged \
-v /:/lynis-audit/host-root \
lynis-auditor audit system --quick通过以上多种部署方式,企业可以根据自身基础设施特点选择最适合的 Lynis 部署策略。
4.1 审计过程详细分解
Lynis 的审计过程是一个精心设计的多阶段流程,每个阶段都有特定的目标和输出:
# 完整审计过程分解
sudo lynis audit system --verbose --debug阶段1:初始化与环境准备
阶段2:系统信息收集
# 手动执行信息收集步骤
sudo lynis show system-info此阶段收集的信息包括:
阶段3:测试模块执行
测试模块按照预定义的顺序执行,每个模块包含多个相关的测试用例:
# 查看可用的测试模块
sudo lynis show groups
# 执行特定模块的测试
sudo lynis audit system --tests-from-group "kernel"阶段4:结果分析与评分
Lynis 使用加权算法计算安全评分:
阶段5:报告生成
生成多种格式的报告供不同受众使用:
4.2 测试模块架构详解
Lynis 的测试模块采用统一的架构设计:
# 查看测试模块结构
cat /usr/share/lynis/include/tests_authentication典型测试模块包含以下部分:
# 测试模块模板
# ------------------------------------------------------------------------------
# 测试ID: AUTH-1234
# 测试标题: 检查密码过期策略
# 严重性: 中等
# 测试类型: security_policy
# ------------------------------------------------------------------------------
# 测试前提条件
if [ "${UNAMES}" != "Linux" ]; then
echo "跳过测试:仅适用于 Linux 系统" | logfile
exit
fi
# 测试执行逻辑
if [ -f /etc/login.defs ]; then
PASS_MAX_DAYS=$(grep ^PASS_MAX_DAYS /etc/login.defs | awk '{print $2}')
if [ "${PASS_MAX_DAYS}" -gt 90 ]; then
echo "警告: 密码最大有效期过长: ${PASS_MAX_DAYS} 天" | logfile
Report -w "PASS_MAX_DAYS" "密码策略" "${PASS_MAX_DAYS}" "90"
else
echo "通过: 密码有效期设置正确" | logfile
Report -s "PASS_MAX_DAYS" "密码策略" "${PASS_MAX_DAYS}"
fi
else
echo "警告: 未找到 /etc/login.defs 文件" | logfile
Report -w "PASS_MAX_DAYS" "密码策略" "文件不存在"
fi4.3 自定义测试开发
企业可以根据特定需求开发自定义测试:
# 创建自定义测试目录
sudo mkdir -p /etc/lynis/custom/tests
sudo chmod 755 /etc/lynis/custom/tests
# 创建自定义测试文件
sudo tee /etc/lynis/custom/tests/custom_application_security.sh > /dev/null << 'EOF'
#!/bin/bash
#
# 自定义应用安全测试
#
# 测试ID: CUST-0001
# 测试标题: 检查自定义应用配置文件权限
# 组: custom
CUSTOM_APP_CONFIG="/opt/myapp/config.properties"
if [ -f "${CUSTOM_APP_CONFIG}" ]; then
# 检查文件权限
FILE_PERM=$(stat -c %a "${CUSTOM_APP_CONFIG}")
FILE_OWNER=$(stat -c %U "${CUSTOM_APP_CONFIG}")
if [ "${FILE_PERM}" -gt 600 ]; then
echo "警告: 应用配置文件权限过宽: ${FILE_PERM}" | logfile
Report -w "CUST-0001" "应用配置" "权限 ${FILE_PERM}" "600"
else
echo "通过: 应用配置文件权限正确" | logfile
Report -s "CUST-0001" "应用配置" "权限 ${FILE_PERM}"
fi
if [ "${FILE_OWNER}" != "myapp" ]; then
echo "警告: 配置文件属主不正确: ${FILE_OWNER}" | logfile
Report -w "CUST-0002" "应用配置" "属主 ${FILE_OWNER}" "myapp"
fi
else
echo "信息: 自定义应用配置文件不存在,跳过测试" | logfile
fi
EOF
# 使自定义测试可执行
sudo chmod +x /etc/lynis/custom/tests/custom_application_security.sh5.1 系统安全配置审计
5.1.1 内核安全参数优化
Lynis 对 Linux 内核安全参数进行深度检查:
# 手动检查当前内核参数
sysctl -a | grep -E "(kernel\.|net\.|fs\.)" | grep -i security
# 创建内核安全加固脚本
sudo tee /etc/sysctl.d/99-lynis-hardening.conf > /dev/null << 'EOF'
# Lynis 推荐的内核安全参数
# 网络层安全
net.ipv4.ip_forward = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
# 内核层安全
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
kernel.yama.ptrace_scope = 1
kernel.core_uses_pid = 1
fs.suid_dumpable = 0
# 内存保护
kernel.randomize_va_space = 2
EOF
# 应用配置
sudo sysctl -p /etc/sysctl.d/99-lynis-hardening.conf5.1.2 文件系统安全审计
Lynis 检查文件系统权限和配置:
# 创建文件系统安全检查脚本
sudo tee /usr/local/bin/filesystem-security-audit.sh > /dev/null << 'EOF'
#!/bin/bash
echo "=== 文件系统安全审计报告 ==="
echo "生成时间: $(date)"
echo
# 检查关键目录权限
echo "1. 关键目录权限检查:"
for dir in /bin /boot /etc /home /lib /opt /root /sbin /usr /var; do
if [ -d "$dir" ]; then
perms=$(stat -c "%a %U:%G" "$dir")
echo " $dir: $perms"
fi
done
echo
# 检查SUID/SGID文件
echo "2. SUID/SGID 文件检查:"
find / -type f \( -perm -4000 -o -perm -2000 \) -exec ls -ld {} \; 2>/dev/null | head -20
echo
# 检查世界可写文件
echo "3. 世界可写文件检查:"
find / -type f -perm -0002 ! -path "/proc/*" -exec ls -ld {} \; 2>/dev/null | head -15
echo
# 检查无属主文件
echo "4. 无属主文件检查:"
find / -nouser -o -nogroup 2>/dev/null | head -15
EOF
sudo chmod +x /usr/local/bin/filesystem-security-audit.sh5.2 服务安全配置审计
5.2.1 SSH 服务安全加固
Lynis 对 SSH 配置进行详细检查,以下是最佳实践配置:
# 创建 SSH 安全加固配置
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup.$(date +%Y%m%d)
sudo tee /etc/ssh/sshd_config > /dev/null << 'EOF'
# Lynis 推荐的 SSH 安全配置
Port 22
Protocol 2
SyslogFacility AUTH
LogLevel INFO
# 认证配置
PermitRootLogin no
StrictModes yes
MaxAuthTries 3
MaxSessions 5
# 加密算法配置
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
# 会话配置
ClientAliveInterval 300
ClientAliveCountMax 2
Compression no
# 访问控制
AllowUsers deploy admin
AllowGroups ssh-users
# 其他安全设置
UsePAM yes
PermitEmptyPasswords no
PasswordAuthentication yes
PubkeyAuthentication yes
HostbasedAuthentication no
IgnoreRhosts yes
X11Forwarding no
PrintMotd no
TCPKeepAlive yes
PermitUserEnvironment no
AllowTcpForwarding no
EOF
# 验证配置并重启服务
sudo sshd -t
sudo systemctl restart ssh
sudo systemctl enable ssh5.2.2 网络服务安全审计
检查系统上运行的所有网络服务:
# 网络服务审计脚本
sudo tee /usr/local/bin/network-service-audit.sh > /dev/null << 'EOF'
#!/bin/bash
echo "=== 网络服务安全审计 ==="
echo "审计时间: $(date)"
echo
echo "1. 监听端口和服务:"
ss -tulpn | while read line; do
if [[ $line == LISTEN* ]]; then
echo " $line"
fi
done
echo
echo "2. 检查不必要的服务:"
for service in $(systemctl list-unit-files --type=service --state=enabled | grep enabled | awk '{print $1}'); do
case $service in
ssh|rsyslog|crond|systemd-journald) ;;
*)
echo " 可能不需要的服务: $service"
;;
esac
done
echo
echo "3. 检查防火墙状态:"
if command -v ufw >/dev/null; then
sudo ufw status verbose
elif command -v iptables >/dev/null; then
sudo iptables -L -n
else
echo " 未找到防火墙配置"
fi
EOF
sudo chmod +x /usr/local/bin/network-service-audit.sh5.3 认证与授权安全
5.3.1 PAM 配置加固
Lynis 检查 PAM (Pluggable Authentication Modules) 配置:
# 创建 PAM 安全配置
sudo cp /etc/pam.d/common-password /etc/pam.d/common-password.backup
sudo tee /etc/pam.d/common-password > /dev/null << 'EOF'
# Lynis 推荐的密码策略
password requisite pam_pwquality.so retry=3 minlen=12 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1
password [success=1 default=ignore] pam_unix.so obscure use_authtok try_first_pass sha512 remember=5
password required pam_deny.so
password required pam_permit.so
EOF
# 安装并配置密码质量检查
sudo apt install -y libpam-pwquality
sudo tee /etc/security/pwquality.conf > /dev/null << 'EOF'
# 密码复杂度配置
minlen = 12
minclass = 3
maxrepeat = 2
maxsequence = 3
maxclassrepeat = 2
lcredit = -1
ucredit = -1
dcredit = -1
ocredit = -1
EOF5.3.2 用户账户安全审计
# 用户账户安全检查脚本
sudo tee /usr/local/bin/user-account-audit.sh > /dev/null << 'EOF'
#!/bin/bash
echo "=== 用户账户安全审计 ==="
echo "检查时间: $(date)"
echo
echo "1. 特权账户检查:"
getent passwd | awk -F: '$3 == 0 {print " 特权用户:", $1, "UID:", $3}'
echo
echo "2. 空密码账户检查:"
getent shadow | awk -F: '($2 == "" || $2 == "!") {print " 空密码账户:", $1}'
echo
echo "3. 密码过期策略:"
echo " 当前密码策略:"
chage -l root 2>/dev/null | head -5
echo
echo "4. 最近登录用户:"
last -n 10 | head -10
echo
echo "5. 失败的登录尝试:"
sudo lastb -n 10 2>/dev/null | head -10
EOF
sudo chmod +x /usr/local/bin/user-account-audit.sh6.1 自定义审计策略
创建针对特定合规框架的审计策略:
# 创建 PCI-DSS 合规审计配置文件
sudo tee /etc/lynis/custom/pci-dss.prf > /dev/null << 'EOF'
# PCI-DSS 合规性审计配置
# 基于 Lynis 的定制审计策略
# 跳过与 PCI-DSS 无关的测试
skip-test=LYNIS
skip-test=LYNIS-USER
skip-test=LYNIS-SCHED
# 启用额外的安全测试
enable-test=FILE-7524 # 检查日志文件权限
enable-test=LOGIN-7562 # 检查登录横幅
enable-test=AUTH-9262 # 检查 PAM 配置
# 设置严格的测试参数
test="AUTH-9208|WEAK_HASH=1"
test="FILE-7524|MAX_PERM=640"
# 自定义审计标签
audit-label="PCI-DSS-v3.2.1"
EOF
# 运行 PCI-DSS 专项审计
sudo lynis audit system --profile /etc/lynis/custom/pci-dss.prf6.2 自动化审计与调度
6.2.1 系统d定时任务配置
# 创建自动化审计脚本
sudo tee /usr/local/bin/automated-lynis-audit.sh > /dev/null << 'EOF'
#!/bin/bash
# 自动化 Lynis 审计脚本
set -e
# 配置变量
AUDIT_DIR="/var/log/lynis"
LOG_FILE="${AUDIT_DIR}/audit-$(date +%Y%m%d-%H%M%S).log"
REPORT_DIR="${AUDIT_DIR}/reports"
PROFILE="/etc/lynis/custom/production.prf"
# 创建目录
mkdir -p "${AUDIT_DIR}" "${REPORT_DIR}"
# 执行审计
echo "开始 Lynis 自动化审计: $(date)" | tee -a "${LOG_FILE}"
/usr/local/bin/lynis audit system --profile "${PROFILE}" --cronjob 2>&1 | tee -a "${LOG_FILE}"
# 生成报告
REPORT_FILE="${REPORT_DIR}/report-$(date +%Y%m%d-%H%M%S).txt"
/usr/local/bin/lynis show report >> "${REPORT_FILE}"
# 检查严重问题
if grep -q "Warning" "${LOG_FILE}"; then
echo "发现警告信息,发送通知..." | tee -a "${LOG_FILE}"
# 这里可以添加邮件或通知逻辑
fi
echo "审计完成: $(date)" | tee -a "${LOG_FILE}"
# 清理旧日志(保留30天)
find "${AUDIT_DIR}" -name "audit-*.log" -mtime +30 -delete
find "${REPORT_DIR}" -name "report-*.txt" -mtime +30 -delete
EOF
sudo chmod +x /usr/local/bin/automated-lynis-audit.sh
# 配置每日定时任务
sudo tee /etc/cron.d/lynis-automated-audit > /dev/null << 'EOF'
# 每日凌晨2点执行 Lynis 审计
0 2 * * * root /usr/local/bin/automated-lynis-audit.sh > /dev/null 2>&1
EOF6.2.2 集成到 CI/CD 流水线
# .gitlab-ci.yml 示例
stages:
- security_audit
lynis_audit:
stage: security_audit
image: ubuntu:20.04
before_script:
- apt-get update
- apt-get install -y wget
- wget https://downloads.cisofy.com/lynis/lynis-3.0.8.tar.gz
- tar xzf lynis-3.0.8.tar.gz
- cd lynis
script:
- ./lynis audit system --quick
- ./lynis show report > lynis_report.txt
artifacts:
paths:
- lynis_report.txt
when: always
only:
- master
- develop6.3 高级报告与分析
6.3.1 自定义报告生成器
# 创建高级报告生成脚本
sudo tee /usr/local/bin/lynis-advanced-report.sh > /dev/null << 'EOF'
#!/bin/bash
# Lynis 高级报告生成器
set -e
# 配置
REPORT_DIR="/var/log/lynis/reports"
HTML_DIR="${REPORT_DIR}/html"
DATA_DIR="${REPORT_DIR}/data"
AUDIT_LOG="$1"
if [ -z "$AUDIT_LOG" ]; then
echo "用法: $0 <lynis-audit-log>"
exit 1
fi
# 创建目录
mkdir -p "${HTML_DIR}" "${DATA_DIR}"
# 解析审计日志并生成 JSON 数据
parse_lynis_log() {
local log_file=$1
local output_file=$2
echo "{" > "$output_file"
echo " \"audit_info\": {" >> "$output_file"
echo " \"timestamp\": \"$(grep "Start time" "$log_file" | cut -d: -f2-)\"," >> "$output_file"
echo " \"hostname\": \"$(grep "Hostname" "$log_file" | cut -d: -f2-)\"," >> "$output_file"
echo " \"lynis_version\": \"$(grep "Lynis version" "$log_file" | cut -d: -f2-)\"" >> "$output_file"
echo " }," >> "$output_file"
echo " \"warnings\": [" >> "$output_file"
grep "Warning" "$log_file" | sed 's/^/ "/;s/$/",/' >> "$output_file"
echo " ]," >> "$output_file"
echo " \"suggestions\": [" >> "$output_file"
grep "Suggestion" "$log_file" | sed 's/^/ "/;s/$/",/' >> "$output_file"
echo " ]" >> "$output_file"
echo "}" >> "$output_file"
}
# 生成 HTML 报告
generate_html_report() {
local json_file=$1
local html_file=$2
cat > "$html_file" << 'HTMLHEAD'
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lynis 安全审计报告</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.header { background: #f5f5f5; padding: 20px; border-radius: 5px; }
.warning { background: #fff3cd; border: 1px solid #ffeaa7; padding: 10px; margin: 10px 0; }
.suggestion { background: #d1ecf1; border: 1px solid #bee5eb; padding: 10px; margin: 10px 0; }
.score { font-size: 24px; font-weight: bold; color: #28a745; }
</style>
</head>
<body>
<div class="header">
<h1>Lynis 安全审计报告</h1>
<p>生成时间: <span id="timestamp"></span></p>
<p>主机名: <span id="hostname"></span></p>
<p>Lynis 版本: <span id="version"></span></p>
</div>
<h2>安全警告</h2>
<div id="warnings"></div>
<h2>改进建议</h2>
<div id="suggestions"></div>
<script>
HTMLHEAD
# 嵌入 JSON 数据
echo "var reportData = $(cat "$json_file");" >> "$html_file"
cat >> "$html_file" << 'HTMLTAIL'
// 填充基本信息
document.getElementById('timestamp').textContent = reportData.audit_info.timestamp;
document.getElementById('hostname').textContent = reportData.audit_info.hostname;
document.getElementById('version').textContent = reportData.audit_info.lynis_version;
// 填充警告
var warningsDiv = document.getElementById('warnings');
reportData.warnings.forEach(function(warning) {
var div = document.createElement('div');
div.className = 'warning';
div.textContent = warning;
warningsDiv.appendChild(div);
});
// 填充建议
var suggestionsDiv = document.getElementById('suggestions');
reportData.suggestions.forEach(function(suggestion) {
var div = document.createElement('div');
div.className = 'suggestion';
div.textContent = suggestion;
suggestionsDiv.appendChild(div);
});
</script>
</body>
</html>
HTMLTAIL
}
# 主执行逻辑
JSON_FILE="${DATA_DIR}/$(basename "$AUDIT_LOG").json"
HTML_FILE="${HTML_DIR}/$(basename "$AUDIT_LOG").html"
echo "开始生成报告..."
parse_lynis_log "$AUDIT_LOG" "$JSON_FILE"
generate_html_report "$JSON_FILE" "$HTML_FILE"
echo "报告生成完成:"
echo " JSON 数据: $JSON_FILE"
echo " HTML 报告: $HTML_FILE"
EOF
sudo chmod +x /usr/local/bin/lynis-advanced-report.sh6.3.2 趋势分析与可视化
#!/usr/bin/env python3
# lynis-trend-analysis.py
# Lynis 审计结果趋势分析
import json
import glob
import re
from datetime import datetime
import matplotlib.pyplot as plt
import numpy as np
class LynisTrendAnalyzer:
def __init__(self, log_directory="/var/log/lynis"):
self.log_dir = log_directory
self.data = []
def parse_audit_logs(self):
"""解析审计日志文件"""
log_files = glob.glob(f"{self.log_dir}/audit-*.log")
for log_file in sorted(log_files):
with open(log_file, 'r') as f:
content = f.read()
# 提取关键信息
timestamp_match = re.search(r"Start time\s*:\s*(.+)", content)
score_match = re.search(r"Hardening index\s*:\s*([0-9]+)", content)
warnings_match = re.findall(r"Warning\s*:\s*(.+)", content)
suggestions_match = re.findall(r"Suggestion\s*:\s*(.+)", content)
if timestamp_match and score_match:
self.data.append({
'timestamp': timestamp_match.group(1).strip(),
'score': int(score_match.group(1)),
'warnings': len(warnings_match),
'suggestions': len(suggestions_match),
'file': log_file
})
def generate_trend_chart(self):
"""生成趋势图表"""
if not self.data:
print("没有找到可分析的数据")
return
dates = [datetime.strptime(item['timestamp'], '%Y-%m-%d %H:%M') for item in self.data]
scores = [item['score'] for item in self.data]
warnings = [item['warnings'] for item in self.data]
suggestions = [item['suggestions'] for item in self.data]
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 8))
# 安全分数趋势
ax1.plot(dates, scores, 'o-', linewidth=2, markersize=8, color='#28a745')
ax1.set_title('Lynis 安全分数趋势', fontsize=14, fontweight='bold')
ax1.set_ylabel('安全分数', fontsize=12)
ax1.grid(True, alpha=0.3)
# 警告和建议趋势
ax2.plot(dates, warnings, 'o-', linewidth=2, markersize=8, color='#dc3545', label='警告')
ax2.plot(dates, suggestions, 'o-', linewidth=2, markersize=8, color='#ffc107', label='建议')
ax2.set_title('问题数量趋势', fontsize=14, fontweight='bold')
ax2.set_ylabel('数量', fontsize=12)
ax2.legend()
ax2.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig(f"{self.log_dir}/trend-analysis.png", dpi=300, bbox_inches='tight')
print(f"趋势图表已保存: {self.log_dir}/trend-analysis.png")
if __name__ == "__main__":
analyzer = LynisTrendAnalyzer()
analyzer.parse_audit_logs()
analyzer.generate_trend_chart()7.1 集中式管理架构
对于拥有数百或数千台 Ubuntu Server 的企业环境,需要设计集中式的 Lynis 管理架构:
# 中央管理服务器配置
sudo mkdir -p /opt/lynis-central/{scripts,configs,templates,reports}
# 创建主控脚本
sudo tee /opt/lynis-central/scripts/central-lynis-controller.sh > /dev/null << 'EOF'
#!/bin/bash
# Lynis 中央控制器
set -e
# 配置
BASE_DIR="/opt/lynis-central"
CONFIG_DIR="${BASE_DIR}/configs"
REPORT_DIR="${BASE_DIR}/reports"
LOG_DIR="${BASE_DIR}/logs"
SERVER_LIST="${BASE_DIR}/server-list.txt"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# 日志函数
log() {
echo -e "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "${LOG_DIR}/central-controller.log"
}
# 执行远程审计
run_remote_audit() {
local server=$1
local config=$2
local audit_id=$(date +%Y%m%d-%H%M%S)
log "在服务器 $server 上启动审计..."
# 传输配置文件和脚本
if ! scp "${CONFIG_DIR}/${config}.prf" "admin@${server}:/tmp/lynis-${config}.prf"; then
log "${RED}错误: 无法传输配置文件到 $server${NC}"
return 1
fi
# 执行远程审计
ssh "admin@${server}" << ENDSSH
set -e
AUDIT_DIR="/var/log/lynis"
sudo mkdir -p "\$AUDIT_DIR"
# 执行审计
sudo lynis audit system \
--profile "/tmp/lynis-${config}.prf" \
--cronjob \
--logfile "\$AUDIT_DIR/audit-${audit_id}.log" \
--report-file "\$AUDIT_DIR/report-${audit_id}.txt"
# 收集结果
sudo cat "\$AUDIT_DIR/report-${audit_id}.txt"
ENDSSH
if [ $? -eq 0 ]; then
log "${GREEN}成功: $server 审计完成${NC}"
return 0
else
log "${RED}错误: $server 审计失败${NC}"
return 1
fi
}
# 主控制逻辑
main() {
local config=${1:-"default"}
mkdir -p "${REPORT_DIR}" "${LOG_DIR}"
log "开始批量审计作业,配置: $config"
success_count=0
fail_count=0
failed_servers=()
# 读取服务器列表
if [ ! -f "$SERVER_LIST" ]; then
log "${RED}错误: 服务器列表文件不存在: $SERVER_LIST${NC}"
exit 1
fi
# 并行执行审计(限制并发数)
export -f run_remote_audit log
export RED GREEN YELLOW NC CONFIG_DIR config
while IFS= read -r server; do
if [[ -n "$server" && ! "$server" =~ ^# ]]; then
if run_remote_audit "$server" "$config"; then
((success_count++))
else
((fail_count++))
failed_servers+=("$server")
fi
fi
done < "$SERVER_LIST"
# 生成摘要报告
log "批量审计作业完成"
log "成功: $success_count, 失败: $fail_count"
if [ $fail_count -gt 0 ]; then
log "${YELLOW}失败的服务器:${NC}"
for failed_server in "${failed_servers[@]}"; do
log " - $failed_server"
done
fi
}
main "$@"
EOF
sudo chmod +x /opt/lynis-central/scripts/central-lynis-controller.sh7.2 配置管理集成
将 Lynis 与配置管理工具(如 Ansible)集成:
# ansible/roles/lynis/tasks/main.yml
---
- name: 安装 Lynis
block:
- name: 添加 Lynis 仓库密钥
apt_key:
url: https://packages.cisofy.com/keys/cisofy-software-public.key
state: present
- name: 添加 Lynis 仓库
apt_repository:
repo: "deb https://packages.cisofy.com/community/lynis/deb/ stable main"
state: present
filename: cisofy-lynis
- name: 安装 Lynis
apt:
name: lynis
state: latest
update_cache: yes
- name: 创建自定义配置目录
file:
path: /etc/lynis/custom
state: directory
mode: '0755'
- name: 部署自定义审计配置
template:
src: "templates/{{ item }}.j2"
dest: "/etc/lynis/custom/{{ item }}"
mode: '0644'
loop:
- production.prf
- pci-dss.prf
- custom_tests.sh
- name: 部署审计脚本
template:
src: templates/automated-audit.sh.j2
dest: /usr/local/bin/automated-lynis-audit.sh
mode: '0755'
- name: 配置定时任务
cron:
name: "每日 Lynis 审计"
minute: "0"
hour: "2"
job: "/usr/local/bin/automated-lynis-audit.sh"
user: root
- name: 创建报告目录
file:
path: /var/log/lynis/reports
state: directory
mode: '0755'# ansible/roles/lynis/templates/production.prf.j2
# 生产环境 Lynis 配置
# 审计设置
audit-group="authentication boot-services kernel memory processes storage"
skip-test=LYNIS
skip-test=LYNIS-USER
# 自定义参数
test="AUTH-9208|WEAK_HASH=1"
test="KRNL-6000|ENABLE_SYSCALL_FILTERING=1"
# 报告设置
report-format=plain
report-file=/var/log/lynis/reports/lynis-report-${timestamp}.txt
# 通知设置
{% if lynis_notification_email %}
notification-email={{ lynis_notification_email }}
{% endif %}8.1 CIS Benchmark 合规性检查
Lynis 可以集成 CIS (Center for Internet Security) Benchmark:
# CIS Ubuntu 20.04 LTS Benchmark 检查脚本
sudo tee /usr/local/bin/cis-compliance-check.sh > /dev/null << 'EOF'
#!/bin/bash
# CIS Ubuntu 20.04 LTS 合规性检查
echo "=== CIS Ubuntu 20.04 LTS 合规性检查 ==="
echo "检查时间: $(date)"
echo
# 1. 初始设置检查
echo "1. 初始设置检查"
echo "----------------"
# 1.1 文件系统配置
echo "1.1 文件系统配置"
mount | grep -E "(/tmp|/var|/var/tmp|/var/log|/var/log/audit|/home)" | while read line; do
if echo "$line" | grep -q "nodev\|nosuid\|noexec"; then
echo " ✓ $(echo $line | awk '{print $3}') 配置正确"
else
echo " ✗ $(echo $line | awk '{print $3}') 需要加固"
fi
done
# 1.2 配置软件包更新
echo
echo "1.2 软件包管理"
if [ -f /etc/apt/apt.conf.d/50unattended-upgrades ]; then
if grep -q "Unattended-Upgrade::Allowed-Origins" /etc/apt/apt.conf.d/50unattended-upgrades; then
echo " ✓ 已配置自动更新"
else
echo " ✗ 未配置自动更新"
fi
else
echo " ✗ 自动更新配置不存在"
fi
# 2. 服务检查
echo
echo "2. 服务配置"
echo "-----------"
# 检查不必要的服务
for service in $(systemctl list-unit-files --type=service --state=enabled | grep enabled | awk '{print $1}'); do
case $service in
ssh|rsyslog|cron|systemd-journald)
echo " ✓ $service (必要服务)"
;;
*)
echo " ? $service (需要评估)"
;;
esac
done
# 3. 网络配置
echo
echo "3. 网络配置"
echo "-----------"
# 检查防火墙
if command -v ufw >/dev/null; then
ufw_status=$(sudo ufw status)
if echo "$ufw_status" | grep -q "Status: active"; then
echo " ✓ UFW 防火墙已启用"
else
echo " ✗ UFW 防火墙未启用"
fi
else
echo " ✗ UFW 未安装"
fi
# 4. 日志与审计
echo
echo "4. 日志与审计"
echo "-------------"
# 检查 auditd
if systemctl is-active auditd >/dev/null 2>&1; then
echo " ✓ auditd 服务运行中"
else
echo " ✗ auditd 服务未运行"
fi
# 5. 访问认证与授权
echo
echo "5. 访问控制"
echo "-----------"
# 检查密码策略
if [ -f /etc/login.defs ]; then
pass_max_days=$(grep ^PASS_MAX_DAYS /etc/login.defs | awk '{print $2}')
if [ "$pass_max_days" -le 90 ]; then
echo " ✓ 密码最大有效期: $pass_max_days 天"
else
echo " ✗ 密码最大有效期过长: $pass_max_days 天"
fi
fi
echo
echo "检查完成"
EOF
sudo chmod +x /usr/local/bin/cis-compliance-check.sh8.2 GDPR 合规性检查
# GDPR 数据保护合规性检查
sudo tee /usr/local/bin/gdpr-compliance-check.sh > /dev/null << 'EOF'
#!/bin/bash
# GDPR 合规性检查脚本
echo "=== GDPR 合规性检查 ==="
echo "检查时间: $(date)"
echo
# 1. 数据发现与分类
echo "1. 数据发现与分类"
echo "-----------------"
# 检查可能包含个人数据的目录
POTENTIAL_DATA_DIRS=("/var/www" "/opt" "/home" "/var/lib/mysql")
for dir in "${POTENTIAL_DATA_DIRS[@]}"; do
if [ -d "$dir" ]; then
echo "检查目录: $dir"
# 查找可能包含个人数据的文件
find "$dir" -type f \( -name "*.csv" -o -name "*.sql" -o -name "*.xls" -o -name "*.xlsx" \) -mtime -30 2>/dev/null | head -5 | while read file; do
echo " - $file"
done
fi
done
# 2. 访问控制检查
echo
echo "2. 访问控制"
echo "----------"
# 检查文件权限
echo "敏感文件权限检查:"
for file in /etc/passwd /etc/shadow /etc/my.cnf; do
if [ -f "$file" ]; then
perms=$(stat -c "%a %U:%G" "$file")
echo " $file: $perms"
fi
done
# 3. 加密检查
echo
echo "3. 数据加密"
echo "----------"
# 检查磁盘加密
if command -v lsblk >/dev/null; then
echo "块设备加密状态:"
lsblk -f | grep -v loop | while read line; do
if echo "$line" | grep -q "crypt"; then
echo " ✓ $(echo $line | awk '{print $1}') 已加密"
else
echo " ○ $(echo $line | awk '{print $1}') 未加密"
fi
done
fi
# 4. 日志与监控
echo
echo "4. 日志与监控"
echo "------------"
# 检查审计日志
if [ -f /var/log/auth.log ]; then
auth_log_count=$(sudo grep -c "session opened" /var/log/auth.log 2>/dev/null || echo "0")
echo " 认证事件数量: $auth_log_count"
else
echo " ✗ 认证日志文件不存在"
fi
# 5. 数据保留策略
echo
echo "5. 数据保留"
echo "----------"
# 检查日志轮转配置
if [ -f /etc/logrotate.conf ]; then
echo "日志轮转配置:"
grep -E "(rotate|weekly|monthly)" /etc/logrotate.conf | head -3 | while read line; do
echo " $line"
done
fi
echo
echo "GDPR 合规性检查完成"
echo "注意: 此检查仅覆盖技术层面,完整的 GDPR 合规性需要法律和政策评估"
EOF
sudo chmod +x /usr/local/bin/gdpr-compliance-check.sh9.1 实时安全状态监控
# 实时安全监控脚本
sudo tee /usr/local/bin/security-monitor.sh > /dev/null << 'EOF'
#!/bin/bash
# 实时安全监控脚本
# 配置
CHECK_INTERVAL=300 # 5分钟
LOG_FILE="/var/log/security-monitor.log"
ALERT_EMAIL="security-team@company.com"
# 日志函数
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}
# 发送告警
send_alert() {
local subject=$1
local message=$2
echo "$message" | mail -s "$subject" "$ALERT_EMAIL"
log "告警发送: $subject"
}
# 安全检查函数
check_failed_logins() {
local failed_count=$(sudo lastb -i | head -n -2 | wc -l)
if [ "$failed_count" -gt 10 ]; then
send_alert "高失败登录尝试" "检测到 $failed_count 次失败登录尝试"
fi
}
check_lynis_score() {
local current_score=$(sudo lynis audit system --quick --no-colors 2>/dev/null | grep "Hardening index" | awk '{print $3}')
local baseline_score=70 # 基线分数
if [ -n "$current_score" ] && [ "$current_score" -lt "$baseline_score" ]; then
send_alert "安全分数下降" "当前安全分数: $current_score, 低于基线: $baseline_score"
fi
}
check_critical_files() {
local critical_files=("/etc/passwd" "/etc/shadow" "/etc/sudoers")
for file in "${critical_files[@]}"; do
if [ -f "$file" ]; then
local perms=$(stat -c "%a" "$file")
local expected_perm="644"
if [ "$file" = "/etc/shadow" ]; then
expected_perm="640"
elif [ "$file" = "/etc/sudoers" ]; then
expected_perm="440"
fi
if [ "$perms" != "$expected_perm" ]; then
send_alert "关键文件权限变更" "文件 $file 权限变更为 $perms, 期望: $expected_perm"
fi
fi
done
}
# 主监控循环
main() {
log "安全监控服务启动"
while true; do
log "执行安全检查..."
check_failed_logins
check_lynis_score
check_critical_files
sleep "$CHECK_INTERVAL"
done
}
# 信号处理
trap 'log "安全监控服务停止"; exit 0' SIGTERM SIGINT
main
EOF
sudo chmod +x /usr/local/bin/security-monitor.sh
# 创建 systemd 服务
sudo tee /etc/systemd/system/security-monitor.service > /dev/null << 'EOF'
[Unit]
Description=Security Monitor Service
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/security-monitor.sh
Restart=always
RestartSec=10
User=root
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable security-monitor.service9.2 与 SIEM 系统集成
# Lynis 审计结果转发到 SIEM 系统
sudo tee /usr/local/bin/lynis-siem-integration.sh > /dev/null << 'EOF'
#!/bin/bash
# Lynis 与 SIEM 系统集成脚本
# 配置
SIEM_SERVER="siem.company.com"
SIEM_PORT=514
LYNIS_LOG_DIR="/var/log/lynis"
TEMP_DIR="/tmp/lynis-siem"
# 创建临时目录
mkdir -p "$TEMP_DIR"
# 解析 Lynis 报告并转换为 CEF 格式
parse_lynis_report() {
local report_file=$1
local hostname=$(hostname)
local timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# 读取报告内容
while IFS= read -r line; do
if [[ $line =~ ^\[([A-Z]+)\]\s+(.+) ]]; then
local test_id="${BASH_REMATCH[1]}"
local message="${BASH_REMATCH[2]}"
# 转换为 CEF 格式
local cef_message="CEF:0|CISOfy|Lynis|3.0.8|${test_id}|${message}|5|"
cef_message+="src=${hostname} "
cef_message+="start=${timestamp} "
cef_message+="cat=lynis/security"
# 发送到 SIEM
echo "$cef_message" | nc -w 1 "$SIEM_SERVER" "$SIEM_PORT"
fi
done < "$report_file"
}
# 监控新的审计报告
monitor_lynis_reports() {
inotifywait -m -e create --format '%f' "$LYNIS_LOG_DIR" | while read new_file; do
if [[ $new_file =~ ^report-.*\.txt$ ]]; then
local report_path="${LYNIS_LOG_DIR}/${new_file}"
echo "发现新报告: $report_path"
# 等待文件完全写入
sleep 5
# 解析并发送报告
parse_lynis_report "$report_path"
fi
done
}
# 主函数
main() {
echo "启动 Lynis SIEM 集成服务"
# 发送现有的最新报告
latest_report=$(ls -t "${LYNIS_LOG_DIR}/report-"*.txt 2>/dev/null | head -1)
if [ -n "$latest_report" ]; then
echo "发送现有报告: $latest_report"
parse_lynis_report "$latest_report"
fi
# 开始监控新报告
monitor_lynis_reports
}
main
EOF
sudo chmod +x /usr/local/bin/lynis-siem-integration.sh10.1 性能问题排查
# Lynis 性能优化检查脚本
sudo tee /usr/local/bin/lynis-performance-check.sh > /dev/null << 'EOF'
#!/bin/bash
# Lynis 性能问题排查
echo "=== Lynis 性能诊断 ==="
echo
# 检查系统资源
echo "1. 系统资源状态:"
echo " 内存使用:"
free -h | awk 'NR==2{printf " Used: %s/%s (%.2f%%)\n", $3, $2, $3*100/$2}'
echo " CPU负载:"
uptime | awk -F'load average:' '{print $2}'
echo
# 检查磁盘 I/O
echo "2. 磁盘 I/O 状态:"
iostat -x 1 1 | grep -A1 "Device" | tail -n +2
echo
# 检查 Lynis 执行时间
echo "3. Lynis 基准测试:"
echo " 开始快速审计测试..."
time sudo lynis audit system --quick --no-colors > /dev/null 2>&1
echo
# 检查最耗时的测试
echo "4. 详细性能分析:"
sudo lynis audit system --quick --debug 2>&1 | grep -E "(seconds|TEST)" | \
awk '/TEST:/ {test=$2} /seconds/ {print " " test ": " $1 " 秒"}' | \
sort -k3 -nr | head -10
echo
# 优化建议
echo "5. 性能优化建议:"
echo " - 使用 --quick 参数跳过耗时测试"
echo " - 在系统负载较低时执行审计"
echo " - 禁用不必要的测试组"
echo " - 考虑使用更快的存储"
EOF
sudo chmod +x /usr/local/bin/lynis-performance-check.sh10.2 权限问题解决
# Lynis 权限问题排查脚本
sudo tee /usr/local/bin/lynis-permission-check.sh > /dev/null << 'EOF'
#!/bin/bash
# Lynis 权限问题排查
echo "=== Lynis 权限诊断 ==="
echo
# 检查当前用户权限
echo "1. 当前用户权限:"
echo " 用户名: $(whoami)"
echo " 用户ID: $(id -u)"
echo " 组ID: $(id -g)"
echo " 所属组: $(id -Gn)"
echo
# 检查 Lynis 文件权限
echo "2. Lynis 文件权限:"
if [ -x /usr/local/bin/lynis ]; then
ls -la /usr/local/bin/lynis
else
echo " Lynis 未安装在 /usr/local/bin/lynis"
fi
if [ -d /etc/lynis ]; then
echo " /etc/lynis 权限:"
ls -la /etc/lynis/
fi
echo
# 检查 sudo 权限
echo "3. Sudo 权限检查:"
if sudo -n true 2>/dev/null; then
echo " ✓ 具有 sudo 权限"
else
echo " ✗ 无 sudo 权限"
fi
echo
# 检查特定文件访问权限
echo "4. 关键文件访问权限:"
important_files=("/etc/passwd" "/etc/shadow" "/etc/group" "/var/log/auth.log")
for file in "${important_files[@]}"; do
if [ -e "$file" ]; then
if sudo test -r "$file"; then
echo " ✓ 可读取: $file"
else
echo " ✗ 不可读取: $file"
fi
else
echo " ○ 不存在: $file"
fi
done
echo
# 解决方案
echo "5. 常见解决方案:"
echo " - 使用 sudo 执行 Lynis: sudo lynis audit system"
echo " - 检查 /etc/sudoers 配置"
echo " - 验证 Lynis 安装完整性"
echo " - 检查 SELinux/AppArmor 策略"
EOF
sudo chmod +x /usr/local/bin/lynis-permission-check.sh11.1 系统级安全加固
# 综合安全加固脚本
sudo tee /usr/local/bin/comprehensive-hardening.sh > /dev/null << 'EOF'
#!/bin/bash
# Ubuntu Server 综合安全加固脚本
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# 日志函数
log() {
echo -e "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a /var/log/security-hardening.log
}
# 执行并检查结果
run_cmd() {
local desc=$1
shift
local cmd=("$@")
log "执行: $desc"
if "${cmd[@]}"; then
log "${GREEN}成功: $desc${NC}"
return 0
else
log "${RED}失败: $desc${NC}"
return 1
fi
}
# 1. 系统更新
system_update() {
log "开始系统更新..."
run_cmd "更新包索引" apt update
run_cmd "升级软件包" apt upgrade -y
run_cmd "清理旧包" apt autoremove -y
}
# 2. 内核安全加固
kernel_hardening() {
log "配置内核安全参数..."
cat > /etc/sysctl.d/99-security.conf << 'SYSCTL'
# 网络安全
net.ipv4.ip_forward=0
net.ipv4.conf.all.send_redirects=0
net.ipv4.conf.default.send_redirects=0
net.ipv4.conf.all.accept_redirects=0
net.ipv4.conf.default.accept_redirects=0
net.ipv4.conf.all.accept_source_route=0
net.ipv4.conf.default.accept_source_route=0
net.ipv4.conf.all.log_martians=1
net.ipv4.icmp_echo_ignore_broadcasts=1
net.ipv4.icmp_ignore_bogus_error_responses=1
net.ipv4.tcp_syncookies=1
net.ipv6.conf.all.accept_redirects=0
net.ipv6.conf.default.accept_redirects=0
# 内核安全
kernel.dmesg_restrict=1
kernel.kptr_restrict=2
kernel.yama.ptrace_scope=1
kernel.core_uses_pid=1
fs.suid_dumpable=0
# 内存保护
kernel.randomize_va_space=2
SYSCTL
run_cmd "应用内核参数" sysctl -p /etc/sysctl.d/99-security.conf
}
# 3. SSH 安全加固
ssh_hardening() {
log "加固 SSH 服务..."
if [ -f /etc/ssh/sshd_config ]; then
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup.$(date +%Y%m%d)
# SSH 安全配置
cat > /etc/ssh/sshd_config << 'SSHD'
Port 22
Protocol 2
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
# 认证配置
PermitRootLogin no
StrictModes yes
MaxAuthTries 3
MaxSessions 5
ClientAliveInterval 300
ClientAliveCountMax 2
# 加密配置
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com
# 其他安全设置
UsePAM yes
PermitEmptyPasswords no
PasswordAuthentication yes
PubkeyAuthentication yes
X11Forwarding no
PrintMotd no
TCPKeepAlive yes
AllowTcpForwarding no
Compression no
SSHD
run_cmd "重启 SSH 服务" systemctl restart ssh
else
log "${YELLOW}警告: SSH 配置文件不存在,跳过 SSH 加固${NC}"
fi
}
# 4. 防火墙配置
firewall_setup() {
log "配置防火墙..."
if command -v ufw >/dev/null; then
run_cmd "重置 UFW" ufw --force reset
run_cmd "默认拒绝所有入站" ufw default deny incoming
run_cmd "默认允许所有出站" ufw default allow outgoing
run_cmd "允许 SSH" ufw allow ssh
run_cmd "启用 UFW" ufw --force enable
else
log "${YELLOW}警告: UFW 未安装,跳过防火墙配置${NC}"
fi
}
# 5. 文件系统安全
filesystem_security() {
log "加固文件系统..."
# 检查 fstab 配置
if grep -q "/tmp" /etc/fstab; then
log " /tmp 已配置"
else
log "${YELLOW}警告: /tmp 未在 fstab 中特殊配置${NC}"
fi
# 设置严格的文件权限
run_cmd "保护关键文件" chmod 600 /etc/shadow
run_cmd "保护关键文件" chmod 644 /etc/passwd
}
# 主函数
main() {
log "开始综合安全加固..."
system_update
kernel_hardening
ssh_hardening
firewall_setup
filesystem_security
log "${GREEN}安全加固完成${NC}"
log "建议重新启动系统并运行 Lynis 审计验证加固效果"
}
# 执行主函数
main
EOF
sudo chmod +x /usr/local/bin/comprehensive-hardening.sh11.2 持续安全监控
# 持续安全监控配置
sudo tee /usr/local/bin/continuous-security-monitoring.sh > /dev/null << 'EOF'
#!/bin/bash
# 持续安全监控框架
# 配置
CONFIG_FILE="/etc/security-monitor.conf"
LOG_DIR="/var/log/security-monitor"
ALERT_THRESHOLD=80
# 加载配置
[ -f "$CONFIG_FILE" ] && source "$CONFIG_FILE"
# 初始化
init_monitoring() {
mkdir -p "$LOG_DIR"
# 创建基线
create_baseline
}
# 创建安全基线
create_baseline() {
local baseline_file="${LOG_DIR}/baseline.json"
cat > "$baseline_file" << BASELINE
{
"created": "$(date -Iseconds)",
"system": {
"hostname": "$(hostname)",
"os": "$(lsb_release -d | cut -f2)",
"kernel": "$(uname -r)"
},
"lynis_score": $(get_lynis_score),
"file_hashes": $(get_critical_file_hashes),
"user_accounts": $(get_user_accounts)
}
BASELINE
}
# 获取 Lynis 分数
get_lynis_score() {
sudo lynis audit system --quick 2>/dev/null | \
grep "Hardening index" | awk '{print $3}' | head -1
}
# 获取关键文件哈希
get_critical_file_hashes() {
local critical_files=(
"/etc/passwd"
"/etc/shadow"
"/etc/group"
"/etc/sudoers"
"/etc/ssh/sshd_config"
)
echo "{"
for file in "${critical_files[@]}"; do
if [ -f "$file" ]; then
hash=$(sha256sum "$file" | awk '{print $1}')
echo " \"$file\": \"$hash\","
fi
done | sed '$ s/,$//'
echo "}"
}
# 获取用户账户信息
get_user_accounts() {
echo "["
getent passwd | awk -F: '$3 >= 1000 && $3 < 65534 {print " {\"user\": \"" $1 "\", \"uid\": " $3 ", \"home\": \"" $6 "\"},"}' | \
sed '$ s/,$//'
echo "]"
}
# 安全状态检查
check_security_status() {
local current_score=$(get_lynis_score)
local baseline_score=$(jq .lynis_score ${LOG_DIR}/baseline.json)
if [ "$current_score" -lt "$baseline_score" ]; then
send_alert "安全分数下降" "从 $baseline_score 降至 $current_score"
fi
check_file_integrity
check_new_users
check_failed_logins
}
# 文件完整性检查
check_file_integrity() {
local current_hashes=$(get_critical_file_hashes)
local baseline_hashes=$(jq .file_hashes ${LOG_DIR}/baseline.json)
if [ "$current_hashes" != "$baseline_hashes" ]; then
send_alert "关键文件变更" "检测到系统文件修改"
fi
}
# 检查新用户
check_new_users() {
local current_users=$(getent passwd | awk -F: '$3 >= 1000 && $3 < 65534 {print $1}' | sort)
local baseline_users=$(jq -r '.user_accounts[].user' ${LOG_DIR}/baseline.json | sort)
local new_users=$(comm -13 <(echo "$baseline_users") <(echo "$current_users"))
if [ -n "$new_users" ]; then
send_alert "新用户检测" "新增用户: $new_users"
fi
}
# 检查失败登录
check_failed_logins() {
local failed_count=$(sudo lastb -i | head -n -2 | wc -l)
if [ "$failed_count" -gt 50 ]; then
send_alert "高失败登录" "检测到 $failed_count 次失败登录尝试"
fi
}
# 发送告警
send_alert() {
local subject=$1
local message=$2
echo "$(date): $subject - $message" >> "${LOG_DIR}/alerts.log"
# 这里可以集成邮件、Slack 等通知方式
logger "安全告警: $subject - $message"
}
# 主循环
main() {
init_monitoring
while true; do
check_security_status
sleep 300 # 5分钟检查一次
done
}
# 执行主函数
main
EOF
sudo chmod +x /usr/local/bin/continuous-security-monitoring.sh通过本指南的深入探讨,我们全面掌握了在 Ubuntu Server 环境中使用 Lynis 进行安全审计的深度实践。从基础部署到高级定制,从单机审计到企业级规模化部署,Lynis 都展现了其作为专业安全审计工具的强大能力。
关键收获总结:
未来演进方向:
随着云原生和容器化技术的发展,Lynis 也在不断进化以适应新的基础设施形态。未来可以关注:
安全是一个持续的过程,而非一次性的项目。Lynis 作为这个过程中的重要工具,帮助我们建立可衡量、可重复、可持续的安全实践,为 Ubuntu Server 环境的安全保驾护航。
通过将 Lynis 集成到组织的安全开发生命周期中,我们能够构建更加健壮、更加安全的系统架构,在数字时代的风浪中稳步前行。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。