找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4091

积分

0

好友

538

主题
发表于 2 小时前 | 查看: 3| 回复: 0

写在前面

Linux 服务器安全加固是个“看起来简单,做起来碎”的活。网上随手能搜到的教程通常只给几条命令,但真正落地到生产环境时,要兼顾:

  • 业务不能中断(远程登录断了自己都进不去)。
  • 加固不能一刀切(不同业务角色要不同策略)。
  • 必须有可逆的操作流程(误操作能回滚)。
  • 要有验证手段(改完知道有没有生效)。

这篇文章不是把 CIS Benchmark 抄一遍,而是把生产里真正做过、能落地、有验证手段的步骤按“风险等级 + 验证方式 + 回滚方式”的格式写清楚。每个步骤都标注风险点,照着做不会出大事。

适用读者:负责 Linux 服务器运维的初中级工程师、安全工程师、DevOps。

一、加固前的准备

1.1 操作窗口与备份

加固工作必须选在业务低峰期进行,并且:

  • 提前公告所有相关方。
  • 准备堡垒机 / 控制台(IPMI、iLO、iDRAC)作为兜底登录方式。
  • 对所有改动的文件做备份:
mkdir -p /root/secbak/$(date +%F-%H%M%S)
cd /root/secbak/$(date +%F-%H%M%S)
cp /etc/ssh/sshd_config .
cp /etc/pam.d/system-auth .
cp /etc/pam.d/password-auth .
cp /etc/sysctl.conf .
cp -r /etc/sysctl.d/ .
cp -r /etc/firewalld/ . 2>/dev/null
cp -r /etc/iptables/ . 2>/dev/null
cp /etc/sudoers .
cp /etc/passwd .
cp /etc/shadow .
cp /etc/group .
  • 准备回滚脚本:
#!/bin/bash
# rollback.sh
SECBAK=$(ls -td /root/secbak/*/ | head -1)
echo "Rollback from: $SECBAK"
cp $SECBAK/sshd_config /etc/ssh/sshd_config
systemctl reload sshd
cp $SECBAK/sysctl.conf /etc/sysctl.conf
sysctl -p
# 其他回滚命令

1.2 风险点全景

下表给每个操作步骤标一个风险等级,方便排期:

风险等级 操作类型 风险说明
P0(极高) 改 SSH 配置、防火墙规则 一旦错改,可能远程登录不进
P1(高) 改 PAM、改 sudoers 错改可能所有用户都进不来
P2(中) 改 sysctl、关服务 一般可逆,风险较低
P3(低) 改文件权限、加 audit 规则 出问题影响面小

风险提示:P0 操作前必须开两个 SSH 会话,一个用来改,一个用来验证。一旦配置改错,第二个会话还能进。

二、账号与认证

2.1 锁定不必要的系统账号

# 查看所有登录 shell 是 /sbin/nologin 的账号
awk -F: '$7 !~ /(nologin|false)/ && $3 < 1000 {print $1}' /etc/passwd

# 锁定账号
passwd -l games
passwd -l ftp
passwd -l rpc
passwd -l rpcuser
passwd -l nfsnobody

# 实际上更狠:
usermod -s /sbin/nologin games
usermod -s /sbin/nologin ftp
usermod -s /sbin/nologin rpc
usermod -s /sbin/nologin rpcuser
usermod -s /sbin/nologin nfsnobody
usermod -s /sbin/nologin ntp
usermod -s /sbin/nologin unbound

风险提示:锁定前要确认这个用户没有被业务用到,比如有些业务以 nobody 身份跑但不需要登录。

2.2 删除无用账号

# 实际生产中保留这些系统账号
# root, bin, daemon, adm, lp, sync, shutdown, halt, mail, operator, ftp, sshd, nobody, systemd-network, dbus, polkitd, sshd, postfix, chrony
# 其它可能都是不必要的

# 删除
userdel -r games 2>/dev/null
userdel -r ftp 2>/dev/null

风险提示:删账号前确认 find / -user games 2>/dev/null 没有遗留文件;不能删 daemonbinsys 等有进程用的账号。

2.3 强制密码策略

/etc/security/pwquality.conf(CentOS 7+,用 pam_pwquality 模块):

minlen = 12
dcredit = -1
ucredit = -1
lcredit = -1
ocredit = -1
dictpath = /usr/share/dict/words
retry = 3
enforce_for_root

参数说明:

  • minlen:密码最小长度。
  • dcredit / ucredit / lcredit / ocredit:数字、大写、小写、特殊字符的最小数量。负数表示至少需要的数量。
  • enforce_for_root:root 改密码也受策略限制。

/etc/login.defs

PASS_MAX_DAYS   90
PASS_MIN_DAYS   1
PASS_WARN_AGE   7
PASS_MIN_LEN    12
LOGIN_RETRIES   5
LOGIN_TIMEOUT   60

2.4 登录失败锁定

CentOS 7+ 用 pam_faillock(比老版本的 pam_tally2 健壮):

/etc/pam.d/system-auth/etc/pam.d/password-auth 顶部加:

auth        required      pam_faillock.so preauth deny=5 unlock_time=900 fail_interval=900
auth        sufficient   pam_unix.so try_first_pass
auth        [default=die] pam_faillock.so authfail deny=5 unlock_time=900 fail_interval=900

/etc/pam.d/system-auth 底部加:

account     required      pam_faillock.so

参数说明:

  • deny=5:连续 5 次失败。
  • unlock_time=900:900 秒(15 分钟)后自动解锁。
  • fail_interval=900:900 秒内累计 5 次。

/etc/security/faillock.conf(可选,统一配置):

deny = 5
unlock_time = 900
fail_interval = 900

注意 pam_faillock 必须在 pam_unix.so 之前,否则可能不生效。

2.5 历史命令时间戳

/etc/profile.d/history.sh

export HISTTIMEFORMAT="%F %T "
export HISTSIZE=10000
export HISTFILESIZE=10000
export HISTCONTROL=ignoredups
export HISTIGNORE="ls:cd:exit:history"
export PROMPT_COMMAND="history -a"
shopt -u histappend

history -a 让多个会话的命令历史能合并保存。

2.6 限制 root 直接登录

只在 su 切到 root,不允许直接 SSH root 登录。这个放到 SSH 配置里(见下节)。

三、SSH 加固

3.1 改默认端口

# /etc/ssh/sshd_config
Port 2222

风险提示:改端口前确认云上安全组、本地 iptables 都放行新端口。

3.2 禁用 root 直接登录

PermitRootLogin no

允许 root 登录的几种模式(按安全等级从高到低):

  • no:完全禁止。
  • prohibit-password:禁止密码、允许密钥。
  • forced-commands-only:仅允许密钥 + forced command。
  • yes:都允许(默认,最不安全)。

3.3 强制密钥认证

PubkeyAuthentication yes
PasswordAuthentication no
ChallengeResponseAuthentication no
KerberosAuthentication no
GSSAPIAuthentication no
UsePAM yes

风险提示:关掉 PasswordAuthentication 之前,确保当前 SSH 客户端已经用密钥成功登录过一次,否则改完可能登不进。

3.4 限制登录尝试

MaxAuthTries 3
MaxSessions 5
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2

ClientAliveInterval 300 + ClientAliveCountMax 2 表示客户端 5 分钟(300 * 2)没活动,服务器主动断开。

3.5 限制允许登录的用户

AllowUsers opsuser1 opsuser2
AllowGroups ops

或者用 DenyUsersDenyGroups 显式禁止。

3.6 关闭无用特性

X11Forwarding no
PermitEmptyPasswords no
PermitUserEnvironment no
AllowAgentForwarding no
AllowTcpForwarding no
PermitTunnel no

X11 转发是常被忽略的攻击面,生产必须关。

3.7 配置 banner

/etc/issue.net

This system is for authorized users only. All activities are monitored and recorded.

/etc/ssh/sshd_config

Banner /etc/issue.net

3.8 强加密套件

KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,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,hmac-sha2-512,hmac-sha2-256

不要用 MD5、SHA1、3DES 这些老旧算法。

3.9 验证 SSH 配置

# 语法检查
sshd -t

# 看实际生效配置
sshd -T | grep -E '^(port|permitrootlogin|passwordauthentication|maxauthtries|allowusers)'

# 重启
systemctl reload sshd
# reload 不影响现有连接

# 验证新连接
ssh -p 2222 -i ~/.ssh/id_rsa opsuser1@server_ip

3.10 SSH 密钥管理

生产环境的密钥策略:

  • 每位运维各自一对密钥,不共享。
  • 私钥加密码保护。
  • 定期轮换(90 天)。
  • 离职人员密钥从 authorized_keys 立即删除。

~/.ssh/authorized_keys 权限:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R opsuser1:opsuser1 ~/.ssh

风险提示:权限不对,sshd 会拒绝登录。

四、防火墙配置

4.1 firewalld 方案

CentOS 7+ 默认使用 firewalld。基础配置:

# 看默认 zone
firewall-cmd --get-default-zone

# 看当前规则
firewall-cmd --list-all

# 放行 SSH(用新端口)
firewall-cmd --permanent --add-port=2222/tcp
firewall-cmd --reload

# 放行 HTTP/HTTPS
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https

# 放行特定 IP 段访问 MySQL
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.0/8" port port="3306" protocol="tcp" accept'

# 拒绝所有未声明的入站
firewall-cmd --permanent --set-target=DROP
firewall-cmd --reload

风险提示:改 firewall 之前要确认 SSH(22 或新端口)已经放行,并且 panic-on 没启用。

4.2 iptables 方案

更老牌的方案,控制更细:

# 备份
iptables-save > /root/iptables.bak.$(date +%F)

# 默认策略
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# 放行回环
iptables -A INPUT -i lo -j ACCEPT

# 已建立的连接
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# SSH
iptables -A INPUT -p tcp --dport 2222 -j ACCEPT

# HTTP / HTTPS
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# 业务端口
iptables -A INPUT -p tcp --dport 8080 -j ACCEPT

# 内网互通
iptables -A INPUT -s 10.0.0.0/8 -j ACCEPT

# ICMP
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT

# 防 SYN flood
iptables -A INPUT -p tcp --syn -m limit --limit 1/s --limit-burst 3 -j ACCEPT
iptables -A INPUT -p tcp --syn -j DROP

# 记录被丢弃的包
iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: "

保存规则:

# CentOS 7
service iptables save
# /etc/sysconfig/iptables

风险提示:iptables 规则在重启后会丢失(CentOS 6),CentOS 7+ 用 iptables-services

yum install -y iptables-services
systemctl enable iptables
systemctl start iptables

4.3 nftables 方案

CentOS 8 / RHEL 8 / Ubuntu 20.04+ 默认用 nftables。配置更简洁:

/etc/nftables.conf

#!/usr/sbin/nft -f

flush ruleset

table inet filter {
    chain input {
        type filter hook input priority 0; policy drop;

        # 放行回环
        iif "lo" accept

        # 已建立的连接
        ct state established,related accept

        # ICMP
        ip protocol icmp accept

        # SSH
        tcp dport 2222 accept

        # HTTP / HTTPS
        tcp dport { 80, 443 } accept

        # 业务端口
        tcp dport 8080 accept

        # 记录
        log prefix "nftables denied: " limit rate 5/minute
    }

    chain output {
        type filter hook output priority 0; policy accept;
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
    }
}
nft -c -f /etc/nftables.conf
systemctl reload nftables

4.4 防止 SSH 爆破

fail2ban 自动封禁:

yum install -y fail2ban

/etc/fail2ban/jail.local

[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5

[sshd]
enabled = true
port = 2222
filter = sshd
logpath = /var/log/secure
maxretry = 3
bantime = 7200
systemctl enable fail2ban
systemctl start fail2ban
fail2ban-client status sshd

五、SELinux / AppArmor

5.1 SELinux 基础

CentOS / RHEL 默认启用 SELinux,模式有:

  • enforcing:强制执行策略。
  • permissive:只记录违规,不阻断。
  • disabled:关闭。

不建议直接 disable。生产上保持 enforcing。

# 看当前模式
getenforce

# 临时改 permissive(用来排错)
setenforce 0

# 永久改
sed -i 's/^SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config

风险提示setenforce 0 后再开回来要 setenforce 1,但配置文件改动需要重启。

5.2 常见 SELinux 排错

# 看拒绝日志
ausearch -m avc -ts recent | less

# 安装 setroubleshoot
yum install -y setroubleshoot-server

# 看拒绝原因
sealert -a /var/log/audit/audit.log

5.3 端口绑定 SELinux 限制

非标准端口(22 → 2222)需要 SELinux 放行:

# 添加端口到 ssh_port_t
semanage port -a -t ssh_port_t -p tcp 2222

# 验证
semanage port -l | grep ssh

5.4 文件上下文

# 把 /data/web 修改为 httpd_sys_content_t
semanage fcontext -a -t httpd_sys_content_t "/data/web(/.*)?"
restorecon -Rv /data/web

5.5 AppArmor(Ubuntu/Debian)

# 看当前配置
aa-status

# 放某进程到 enforce 模式
aa-enforce /usr/bin/nginx

# permissive 模式(排错用)
aa-complain /usr/bin/nginx

/etc/apparmor.d/local/usr.bin.nginx

/var/log/nginx/** rw,
/data/web/** r,

六、内核参数

6.1 安全相关 sysctl

/etc/sysctl.d/99-security.conf

# IP 转发(路由器开,业务机关)
net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0

# 禁用源路由
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0

# 禁用 ICMP 重定向
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0

# 启用 syncookies
net.ipv4.tcp_syncookies = 1

# 启用 rp_filter
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# 忽略 ICMP echo(防 ping)
# net.ipv4.icmp_echo_ignore_all = 1

# 记录可疑包
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1

# 减少 fin 超时
net.ipv4.tcp_fin_timeout = 15

# 防止 time-wait 攻击
net.ipv4.tcp_rfc1337 = 1

# 禁止 IP 欺骗
net.ipv4.conf.all.rp_filter = 1

# 内核指针限制
kernel.kptr_restrict = 2

# dmesg 限制
kernel.dmesg_restrict = 1

# ASLR
kernel.randomize_va_space = 2

# 限制 ptrace
kernel.yama.ptrace_scope = 1

应用:

sysctl -p /etc/sysctl.d/99-security.conf

6.2 性能相关 sysctl

/etc/sysctl.d/99-performance.conf

net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.core.netdev_max_backlog = 300000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216

七、服务最小化

7.1 关闭不必要的服务

# 看当前启用的服务
systemctl list-unit-files --type=service | grep enabled

# 关闭典型不需要的服务
systemctl disable --now telnet.socket
systemctl disable --now rsh.socket
systemctl disable --now rlogin.socket
systemctl disable --now rexec.socket
systemctl disable --now vsftpd
systemctl disable --now xinetd
systemctl disable --now tftp
systemctl disable --now nfs
systemctl disable --now rpcbind
systemctl disable --now named
systemctl disable --now dhcpd
systemctl disable --now snmpd
systemctl disable --now ypserv
systemctl disable --now tftpd
systemctl disable --now rsyncd

风险提示:关闭服务前确认业务没有依赖。比如 MySQL 服务器上不能关 rpcbind(可能 NFS 客户端需要),vsftpd 看似可以关,但有些老业务用 FTP 拉文件。

7.2 监听端口审计

# 看所有监听端口
ss -tulnp

# 看具体进程
lsof -i :22
lsof -i :80

任何不明端口都是潜在的入侵迹象。

7.3 关闭桌面服务

# 服务器一般不需要 GUI
systemctl disable --now gdm
systemctl disable --now lightdm

八、文件权限与 umask

8.1 关键目录权限

chmod 700 /root
chmod 750 /etc
chmod 750 /etc/ssh
chmod 600 /etc/ssh/sshd_config
chmod 600 /etc/shadow
chmod 640 /etc/passwd
chmod 640 /etc/group
chmod 600 /etc/sudoers
chmod 440 /etc/sudoers.d/*

# 关键配置文件
chmod 600 /etc/security/opasswd
chmod 600 /boot/grub2/grub.cfg 2>/dev/null

8.2 重要文件加锁

# 锁定关键文件
chattr +i /etc/passwd
chattr +i /etc/shadow
chattr +i /etc/group
chattr +i /etc/gshadow
chattr +i /etc/sudoers
chattr +i /etc/ssh/sshd_config
chattr +i /etc/issue
chattr +i /etc/issue.net

# 解除锁定
chattr -i /etc/passwd

风险提示chattr +i 后即使 root 也不能修改 / 删除。修改前必须先解锁。

8.3 默认 umask

/etc/profile

umask 027

新建文件权限 = 666 - umask = 640,新建目录权限 = 777 - umask = 750。

8.4 敏感文件查找

# 找 777 权限的文件
find / -perm -o+w -type f 2>/dev/null | head -20

# 找没有属主的文件
find / -nouser -o -nogroup 2>/dev/null

# 找 SUID 文件
find / -perm -u+s -type f 2>/dev/null

# 找 SGID 文件
find / -perm -g+s -type f 2>/dev/null

九、时间同步

9.1 chrony

yum install -y chrony

/etc/chrony.conf

server ntp1.aliyun.com iburst
server ntp2.aliyun.com iburst
server ntp3.aliyun.com iburst

# 允许内网客户端同步
allow 10.0.0.0/8

# 记录时间漂移
makestep 1.0 3
rtcsync
logdir /var/log/chrony
systemctl enable chronyd
systemctl start chronyd
chronyc tracking
chronyc sources -v

风险提示:日志分析和安全审计都依赖准确的时间。timedatectl 看时区。

十、审计与日志

10.1 auditd

yum install -y audit

/etc/audit/rules.d/audit.rules

# 监控时间修改
-w /etc/localtime -p wa -k time-change

# 监控账号/认证变更
-w /etc/group -p wa -k identity
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/sudoers -p wa -k identity
-w /etc/sudoers.d/ -p wa -k identity

# 监控 SSH 配置
-w /etc/ssh/sshd_config -p wa -k sshd
-w /etc/ssh/sshd_config.d/ -p wa -k sshd

# 监控登录登出
-w /var/log/faillog -p wa -k logins
-w /var/log/lastlog -p wa -k logins
-w /var/log/tallylog -p wa -k logins
-w /var/log/secure -p wa -k auth

# 监控特权命令
-a always,exit -F path=/usr/bin/sudo -F perm=x -k privileged
-a always,exit -F path=/usr/bin/su -F perm=x -k privileged
-a always,exit -F path=/usr/bin/passwd -F perm=x -k privileged

# 监控关键目录变更
-w /etc -p wa -k config
-w /var/log -p wa -k log

# 不可改变 audit 配置
-e 2
systemctl enable auditd
systemctl restart auditd

# 查记录
ausearch -k sshd
ausearch -ts today -k identity
aureport --summary
aureport --auth
aureport --login

10.2 rsyslog 远程日志

生产上把所有重要日志集中到中心化日志服务器,避免入侵后被删。

/etc/rsyslog.d/remote.conf

*.* @10.0.10.10:514

10.3 logwatch / logcheck

每天跑一次的日志分析工具,生成日报。

yum install -y logwatch

/etc/logwatch/conf/logwatch.conf

MailTo = ops@example.com
Detail = High
Service = All
Range = yesterday

十一、入侵排查命令速查

11.1 当前登录用户

who
w
last
lastb
lastlog

11.2 历史命令

# 所有用户
for h in /home/*; do cat $h/.bash_history 2>/dev/null; done

# 加时间戳的 history
HISTTIMEFORMAT="%F %T " history

11.3 异常进程

# CPU 占用高的进程
ps aux --sort=-%cpu | head

# 内存占用高的进程
ps aux --sort=-%mem | head

# 看进程启动时间
ps -eo pid,etime,cmd

# 看进程命令行
cat /proc/<pid>/cmdline | tr '\0' ' '
cat /proc/<pid>/environ | tr '\0' '\n'

# 找异常父进程
ps -ef --forest

11.4 异常网络连接

# 全部连接
ss -ant
ss -tunap

# 看监听
ss -tlnp

# 看进程占用的连接
lsof -i

# 看 DNS 查询
tcpdump -i any -nn -s 0 port 53

11.5 文件完整性检查

# 安装 AIDE
yum install -y aide

# 初始化数据库
aide --init
mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz

# 检查
aide --check

/etc/aide.conf

/etc p+i+n+u+g+s+b+m+c+md5+sha256
/bin p+i+n+u+g+s
/sbin p+i+n+u+g+s
/usr/bin p+i+n+u+g+s
/usr/sbin p+i+n+u+g+s
/var/log p+i+n+u+g

11.6 计划任务排查

# 当前用户的
crontab -l
crontab -u root -l

# 系统级
cat /etc/crontab
ls -la /etc/cron.d/
ls -la /etc/cron.hourly/ /etc/cron.daily/ /etc/cron.weekly/ /etc/cron.monthly/

# systemd 定时器
systemctl list-timers --all

# 看 /var/spool/cron
ls -la /var/spool/cron/
ls -la /var/spool/cron/crontabs/

# anacron
ls -la /var/spool/anacron/

11.7 内核模块

# 看已加载模块
lsmod

# 看隐藏模块
cat /proc/modules

# 看内核版本
uname -a

11.8 rootkit 排查

# 安装 chkrootkit / rkhunter
yum install -y chkrootkit rkhunter

chkrootkit
rkhunter --check

十二、sudo 配置

12.1 最小权限

/etc/sudoers(用 visudo 编辑):

Defaults    env_reset
Defaults    secure_path = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
Defaults    log_input
Defaults    log_output
Defaults    iolog_dir = /var/log/sudo-io/%{user}
Defaults    !requiretty

# ops 组
%ops  ALL=(ALL) NOPASSWD: ALL

# 业务用户只允许重启服务
%deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart myapp
%deploy ALL=(root) NOPASSWD: /usr/bin/systemctl status myapp
%deploy ALL=(root) NOPASSWD: /usr/bin/systemctl stop myapp
%deploy ALL=(root) NOPASSWD: /usr/bin/systemctl start myapp

# 数据库管理员
%dba ALL=(postgres) NOPASSWD: ALL

# 备份用户
%backup ALL=(root) NOPASSWD: /usr/local/bin/backup.sh

风险提示%ops ALL=(ALL) NOPASSWD: ALL 等价于给 ops 完整 root 权限,生产上慎用,建议拆成更细的角色。

12.2 sudo 日志

# 看 sudo 历史
journalctl -u sudo
grep sudo /var/log/secure
cat /var/log/sudo-io/*/seq

/var/log/sudo-io 是会话级日志,能看到 sudo 执行的命令和输出。

十三、防爆破

13.1 SSH 爆破识别

# 看大量失败的 SSH 登录
grep 'Failed password' /var/log/secure | awk '{print $11}' | sort | uniq -c | sort -rn | head

# 启用 fail2ban
systemctl status fail2ban
fail2ban-client status sshd

13.2 临时封禁

# 手工封禁
iptables -I INPUT -s 1.2.3.4 -j DROP

# 解封
iptables -D INPUT -s 1.2.3.4 -j DROP

13.3 阻断常见扫描

# 用 portsentry 自动监听未使用端口
yum install -y portsentry

十四、备份与恢复

14.1 关键文件备份

#!/bin/bash
# /usr/local/bin/sec_backup.sh
BACKUP_DIR=/data/backup/sec/$(date +%F)
mkdir -p $BACKUP_DIR

# 关键文件
cp /etc/passwd $BACKUP_DIR/
cp /etc/shadow $BACKUP_DIR/
cp /etc/group $BACKUP_DIR/
cp /etc/sudoers $BACKUP_DIR/
cp -r /etc/sudoers.d $BACKUP_DIR/
cp -r /etc/ssh $BACKUP_DIR/
cp -r /etc/pam.d $BACKUP_DIR/
cp -r /etc/security $BACKUP_DIR/
cp /etc/sysctl.conf $BACKUP_DIR/
cp -r /etc/sysctl.d $BACKUP_DIR/
cp -r /etc/firewalld $BACKUP_DIR/
cp -r /etc/iptables $BACKUP_DIR/
cp -r /etc/audit/rules.d $BACKUP_DIR/
cp -r /etc/sudoers.d $BACKUP_DIR/

# 关键目录大小
du -sh /etc /var/log /home /root > $BACKUP_DIR/sizes.txt

# 压缩
tar -czf $BACKUP_DIR.tar.gz $BACKUP_DIR
rm -rf $BACKUP_DIR

14.2 配置版本化

/etc/ 全部纳入 Git:

cd /etc
git init
git add .
git commit -m "initial"

每次加固前先 commit,加固后再 commit,对比 diff。

14.3 异地备份

# 用 rsync 推送到异地
rsync -avz /data/backup/sec/ backup@backup-server:/backup/sec/

十五、合规检查工具

15.1 OpenSCAP

yum install -y openscap-scanner openscap-utils
# 扫描 CIS
oscap xccdf eval --profile xccdf_org.ssgproject.content_profile_cis --results scan.xml /usr/share/xml/scap/ssg/content/ssg-rhel8-ds.xml

# 生成 HTML 报告
oscap xccdf generate report scan.xml > report.html

15.2 Lynis

yum install -y lynis
lynis audit system

Lynis 给出的报告有加固建议。

15.3 CIS-CAT

Lite 版免费,能针对 CIS Benchmark 自动扫描。

十六、典型加固场景的步骤清单

16.1 新机交付清单

# 1. 更新系统
yum update -y

# 2. 安装基础包
yum install -y chrony vim wget curl net-tools bind-utils

# 3. 设置时区
timedatectl set-timezone Asia/Shanghai

# 4. 启用 chrony
systemctl enable --now chronyd

# 5. 关闭无用服务
systemctl disable --now firewalld  # 如果走云上安全组
systemctl disable --now postfix

# 6. 加固 SSH
cp /etc/ssh/sshd_config /root/secbak/
# 编辑 /etc/ssh/sshd_config
sshd -t
systemctl reload sshd

# 7. 配置密码策略
vim /etc/security/pwquality.conf
vim /etc/login.defs

# 8. 配置 PAM 失败锁定
vim /etc/pam.d/system-auth
vim /etc/pam.d/password-auth

# 9. 配置 sysctl
cp /etc/sysctl.conf /root/secbak/
# 编辑 /etc/sysctl.d/99-security.conf
sysctl -p /etc/sysctl.d/99-security.conf

# 10. 配置 auditd
cp /etc/audit/rules.d/audit.rules /root/secbak/
# 编辑
systemctl enable --now auditd

# 11. 设置文件权限
chmod 700 /root
chmod 600 /etc/ssh/sshd_config
chattr +i /etc/passwd /etc/shadow

# 12. 启动 fail2ban
yum install -y fail2ban
systemctl enable --now fail2ban

# 13. 装监控 agent
# 14. 装日志 agent
# 15. 装巡检 agent

16.2 周期巡检清单

每周一次:

# 1. 看最近 7 天的 SSH 失败登录
grep 'Failed password' /var/log/secure* | tail -50

# 2. 看 SUID 文件变化
find / -perm -u+s -type f 2>/dev/null > /tmp/suid.today
diff /tmp/suid.yesterday /tmp/suid.today

# 3. 看用户变化
diff <(sort /etc/passwd) <(sort /etc/passwd.yesterday)

# 4. 看 crontab
diff <(crontab -l) <(cat /tmp/crontab.yesterday)

# 5. 看包更新
yum check-update

# 6. 看内核升级
uname -a
rpm -q kernel

# 7. 看磁盘
df -h | grep -E '100%|9[0-9]%'

# 8. 看内存
free -h

# 9. 看 fail2ban 状态
fail2ban-client status sshd

# 10. 看 audit 报告
aureport --summary

十七、容器与虚拟化环境

17.1 Docker 镜像加固

  • 使用官方最小镜像(alpine、distroless)。
  • 不要在镜像里写密码、token、key。
  • 用 multi-stage 构建减小镜像体积。
  • 用户切换到非 root:
RUN useradd -r -u 10001 -g root myuser
USER myuser
  • 加 healthcheck:
HEALTHCHECK --interval=30s --timeout=5s CMD curl -f http://localhost/ || exit 1

17.2 容器运行时加固

  • 用 rootless containerd。
  • 启用 seccomp、apparmor、capabilities drop。
  • 限制容器资源(CPU、内存、PID)。
  • 禁止 privileged 容器。
  • 容器只读文件系统。

十八、云上特殊场景

18.1 阿里云 ECS 加固

  • 用云安全中心做基线检查。
  • 用 ActionTrail 审计 API 调用。
  • 用 RAM 给运维子账号,按需授权。
  • 密钥管理用 KMS,不在代码里明文。

18.2 AWS EC2 加固

  • IAM Role 取代 ssh 密钥访问 S3。
  • Security Group 限定 IP 段。
  • VPC Flow Logs 记录流量。
  • CloudTrail 审计 API。
  • SSM Session Manager 取代 SSH 22 端口。

18.3 避免常见云上错误

  • 0.0.0.0/0 暴露 SSH/RDP 到公网。
  • 安全组规则不设上限(任意 IP 任意端口)。
  • IAM 账号用 root 或者 AccessKey 长期不轮换。
  • 存储桶公开读 / 公开写。

十九、回滚方案

加固工作的每一步都必须能回滚。模板:

#!/bin/bash
# /root/secbak/rollback.sh
SECBAK=$1
if [ -z "$SECBAK" ]; then
echo "Usage: $0 <backup_dir>"
exit 1
fi

# 1. 恢复 sshd 配置
cp $SECBAK/sshd_config /etc/ssh/sshd_config
systemctl reload sshd

# 2. 恢复 sysctl
cp $SECBAK/sysctl.conf /etc/sysctl.conf
sysctl -p

# 3. 恢复 PAM
cp $SECBAK/system-auth /etc/pam.d/system-auth
cp $SECBAK/password-auth /etc/pam.d/password-auth

# 4. 恢复 sudo
cp $SECBAK/sudoers /etc/sudoers
chmod 440 /etc/sudoers

# 5. 恢复账号
cp $SECBAK/passwd /etc/passwd
cp $SECBAK/shadow /etc/shadow
cp $SECBAK/group /etc/group

# 6. 解除 chattr 锁
chattr -i /etc/passwd /etc/shadow

# 7. 恢复防火墙
firewall-cmd --reload

echo "Rollback completed. Please verify."

二十、验证清单

加固完成后逐项验证:

  • [ ] SSH 密钥登录正常。
  • [ ] 密码登录被禁。
  • [ ] 密码复杂度生效(用弱密码改密码会被拒)。
  • [ ] 失败 5 次后被锁 15 分钟。
  • [ ] 普通用户能 su 到 root,root 不能直接登录。
  • [ ] 防火墙规则生效(扫描端口确认)。
  • [ ] SELinux enforcing,业务正常。
  • [ ] sysctl 全部生效(sysctl -a | grep xxx)。
  • [ ] 时间同步正常(chronyc tracking)。
  • [ ] auditd 记录到关键事件(ausearch -k sshd)。
  • [ ] fail2ban 在工作(fail2ban-client status)。
  • [ ] 无用服务关闭(systemctl list-unit-files --state=enabled)。
  • [ ] chattr 锁生效(尝试改 /etc/passwd 应该失败)。
  • [ ] rootkit 扫描通过(chkrootkit)。

二十一、常见误区

21.1 “关闭 SELinux 就一了百了”

错。SELinux 是最严密的强制访问控制,关闭等于少一层防护。改成 permissive 排错,再切回 enforcing

21.2 “密码策略越严越好”

不是。密码 20 位 + 4 种字符 + 90 天过期 = 用户记不住 = 把密码写在便签上 = 更危险。12 位 + 数字字母 + 180 天 + 多因素认证是更合理的组合。

21.3 “disable root 登录就安全了”

错。disable root SSH 之后,攻击者会爆破普通用户,普通用户 sudo 到 root 同样危险。要配合 sudo 细粒度授权 + 审计。

21.4 “防火墙只开 22、80、443 就够了”

错。Redis 6379、MySQL 3309 都要限制内网 IP,不开公网。Web 业务尽量走云上 LB,让云上 LB 终结公网。

21.5 “加固一次就一劳永逸”

错。加固是一个持续的过程,新漏洞、新服务、新员工都会带来新风险。定期做 OpenSCAP / Lynis 扫描。

二十二、附录:常用命令

# 账号
id <user>
passwd -l <user>  # 锁定
passwd -u <user>  # 解锁
chage -l <user>   # 看密码策略
chage -M 90 -W 7 -m 1 <user>  # 改密码策略
useradd -m -s /bin/bash -G ops <user>
usermod -aG sudo <user>

# SSH
sshd -t
systemctl reload sshd
systemctl status sshd
journalctl -u sshd --no-pager | tail

# 防火墙
firewall-cmd --list-all
firewall-cmd --reload
iptables -L -n -v
nft list ruleset

# SELinux
getenforce
sestatus
sealert -a /var/log/audit/audit.log
semanage port -l
restorecon -Rv /path

# sysctl
sysctl -a
sysctl -p /etc/sysctl.d/99-security.conf

# 文件
lsattr /etc/passwd
chattr +i /etc/passwd
stat /etc/passwd
find / -perm -o+w -type f 2>/dev/null

# 时间
timedatectl
chronyc tracking
chronyc sources -v

# 审计
ausearch -k sshd
ausearch -ts today
aureport --summary
auditctl -l

# 防爆破
fail2ban-client status
fail2ban-client status sshd
fail2ban-client set sshd banip 1.2.3.4
fail2ban-client set sshd unbanip 1.2.3.4

# 检查工具
chkrootkit
rkhunter --check
lynis audit system

二十三、总结

Linux 加固不是一次性工作,是持续运营。把这篇里的内容按重要程度排个序:

  • 必须做:SSH 强制密钥、关闭无用服务、密码策略、密码失败锁定、防火墙、SELinux enforcing、time sync、auditd、文件权限。
  • 应该做:内核参数、fail2ban、文件完整性、rootkit 扫描、sysctl 调优、账号锁定。
  • 锦上添花:OpenSCAP 扫描、配置版本化、配置中心、合规报告自动生成。

加固的本质是“降低攻击面 + 增加入侵成本 + 提高可观测性”。改完一个步骤要问自己:

  1. 这个改动降低了什么攻击面?
  2. 如果改错了,回滚路径是什么?
  3. 怎么验证生效?
  4. 怎么监控这个改动没被人改回去?

带着这四个问题去加固,每一步都踏实。

二十四、容器安全加固

24.1 Docker 守护进程加固

/etc/docker/daemon.json

{
  "icc": false,
  "userland-proxy": false,
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "10"
  },
  "live-restore": true,
  "no-new-privileges": true,
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Hard": 65535,
      "Soft": 65535
    }
  },
  "storage-driver": "overlay2"
}

icc=false 禁止容器间通信,需要时显式 docker network create + --link

24.2 Dockerfile 最佳实践

# 用最小基础镜像
FROM gcr.io/distroless/java:11

# 显式声明工作目录
WORKDIR /app

# 拷贝文件
COPY --chown=appuser:appgroup target/app.jar /app/

# 切到非 root 用户
USER 10001

# 暴露端口
EXPOSE 8080

# 启动
ENTRYPOINT ["java", "-jar", "/app/app.jar"]

# 加 healthcheck
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
    CMD wget --spider http://localhost:8080/health || exit 1

风险提示:生产镜像必须用具体版本 tag,不要用 latest

24.3 Kubernetes Pod 安全

Pod Security Standards(PSS)有三个级别:privilegedbaselinerestricted。生产上一般用 restricted

Pod 示例:

apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 10001
    runAsGroup: 10001
    fsGroup: 10001
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: app
    image: myapp:1.0
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop:
        - ALL
      runAsNonRoot: true
    resources:
      requests:
        cpu: "100m"
        memory: "128Mi"
      limits:
        cpu: "500m"
        memory: "512Mi"
    volumeMounts:
    - name: tmp
      mountPath: /tmp
  volumes:
  - name: tmp
    emptyDir: {}

24.4 镜像签名与扫描

  • 镜像签名:cosign(sigstore)能给镜像签名,部署时验证。
  • 镜像扫描:Trivy、Snyk、Anchore 能扫镜像中的 CVE。
  • 准入控制:OPA / Kyverno 在 K8s 部署时校验镜像签名。

二十五、网络层加固

25.1 限制登录源 IP

# iptables 限制 SSH 只能从堡垒机
iptables -A INPUT -p tcp --dport 22 -s 10.0.10.10 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j DROP

25.2 限制内网外联

# 防挖矿:禁止服务器主动连外网
iptables -A OUTPUT -p tcp --dport 443 -d 10.0.0.0/8 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 80 -d 10.0.0.0/8 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 443 -d 0.0.0.0/0 -j ACCEPT  # 允许更新
# 其他拒绝

更彻底的做法:在交换机 / 防火墙上做白名单出口。

25.3 DDoS 防护

应用层:Cloudflare、阿里云高防、AWS Shield。 主机层:内核调优 + fail2ban + 限流。

# 调内核参数缓解 SYN flood
sysctl -w net.ipv4.tcp_syncookies=1
sysctl -w net.ipv4.tcp_max_syn_backlog=65535
sysctl -w net.ipv4.tcp_synack_retries=2

二十六、密码与密钥管理

26.1 不用明文密码

生产上所有密码必须:

  • 不在配置文件明文。
  • 不在脚本明文。
  • 不在聊天工具明文。
  • 不在 Git 仓库。

26.2 密码存储

  • HashiCorp Vault:开源、功能全面。
  • AWS Secrets Manager / Parameter Store:云上方案。
  • Kubernetes Secrets + RBAC + Encryption at Rest
  • Ansible Vault:配置管理用。
  • /etc/shadow 的 hash:用户密码。

26.3 密钥轮换

  • 数据库密码:90 天。
  • API key:90 天。
  • 运维 SSH 私钥:90 天。
  • 服务器证书:1 年。
  • 内部 CA 证书:3 年。

26.4 私钥保护

# 私钥必须 600 权限
chmod 600 /path/to/private.key

# 私钥用密码保护
openssl rsa -aes256 -in private.key -out private.enc.key

# 不要把私钥 commit 到 Git
echo "*.key" >> .gitignore

二十七、零信任实践

27.1 不信任内网

  • 内网服务也要身份认证。
  • mTLS 替代明文协议。
  • 服务间调用用 JWT / mTLS。
  • 不在防火墙后面“躺平”。

27.2 最小权限

  • 运维账号按角色分(开发、运维、安全)。
  • 每个角色只能访问必要的资源。
  • 按需申请,用完回收。

27.3 全程审计

  • 任何操作都要留痕。
  • 用操作录制工具(录屏)做合规审计。
  • 异常操作自动告警。

27.4 持续验证

  • 定期对加固策略做验证(自动化测试)。
  • 定期做红蓝对抗。
  • 用 OpenSCAP / Lynis 持续扫描。

二十八、安全事件响应

28.1 应急响应流程

  1. 发现告警:监控告警、用户报告。
  2. 初步评估:影响范围、紧急程度。
  3. 隔离:断网、停服务、禁账号。
  4. 调查:日志、内存、磁盘、网络。
  5. 恢复:备份还原、补丁升级、密码重置。
  6. 复盘:写 incident report、改进防御。

28.2 入侵后的清理步骤

# 1. 立即断网(不要断电,方便取证)
iptables -I INPUT 1 -j DROP
iptables -I OUTPUT 1 -j DROP

# 2. 取证
dd if=/dev/sda of=/mnt/external/image.dd
tar -czf /mnt/external/evidence.tar.gz /var/log /etc /home

# 3. 排查入侵点
# 看 cron、systemd、SUID 文件、内核模块、SSH 密钥

# 4. 重装系统
# 不要尝试在已经被入侵的系统上修复,重装 + 数据恢复

28.3 强密码生成

# 16 位密码
openssl rand -base64 16

# 32 位密码
openssl rand -base64 32

二十九、加固效果的可视化

把加固成果做成 dashboard:

  • OpenSCAP / Lynis 扫描得分。
  • auditd 事件数趋势。
  • fail2ban 封禁 IP 数。
  • 弱密码账号数。
  • 异常登录事件数。

Grafana 上面板示例:

  • CIS Compliance Score。
  • SSH 失败登录趋势。
  • 关键文件变更告警。
  • 入侵检测告警数。

三十、给初中级工程师的实操路线图

如果你刚接触 Linux 加固,按以下顺序学习,每步 1~2 周:

  1. 第 1 周:SSH 加固、密码策略、登录失败锁定。学会用 visudo、了解 PAM。
  2. 第 2 周:firewalld / iptables 基础。学会放行、拒绝、限速。
  3. 第 3 周:SELinux 基础。能在不关 SELinux 的情况下让服务跑起来。
  4. 第 4 周:sysctl 调优。理解每个参数的作用。
  5. 第 5 周:服务最小化。关掉无用服务。
  6. 第 6 周:auditd 基础。学会写规则、查日志。
  7. 第 7 周:fail2ban。学会配 jail。
  8. 第 8 周:入侵排查命令。能在 5 分钟内定位可疑进程。
  9. 持续:周期性跑 OpenSCAP / Lynis,看报告改进。

Linux 加固看似千头万绪,本质上就是“减少攻击面 + 加快响应 + 全程可观测”。每改一步都有目标、有验证、有回滚,几年做下来,机器就是一块铁板。

三十一、加固案例实战

最后给一个真实生产环境加固案例,把所有步骤串起来。

31.1 背景

某公司新上 100 台 CentOS 7.9 服务器,需要按金融行业基线加固,30 天内完成 100% 合规扫描通过。

31.2 角色与计划

  • 实施:3 个运维工程师。
  • 验证:1 个安全工程师。
  • 时间窗口:业务低峰 23:00~05:00。
  • 工具:Ansible 批量执行 + Jenkins 流水线 + OpenSCAP 验证。

31.3 步骤

第一周:搭建堡垒机、备份所有服务器配置、把所有服务器纳入 Ansible。

第二周:用 Ansible 批量执行 SSH 加固(端口 22 → 2222)、关闭无用服务、配置 chrony、配置 auditd。

第三周:配置 firewalld,按角色(Web、DB、缓存、消息)下发不同规则集。

第四周:配置密码策略、登录失败锁定、sudo 细粒度授权。

第五~六周:跑 OpenSCAP,按报告逐项修。每台机器都过一遍基线扫描,得分 95+ 才算合格。

31.4 关键产出

  • /etc/ 全部纳入 Git,写明每次变更原因。
  • 加固操作手册一份,包含每个步骤的命令、风险、回滚。
  • OpenSCAP 报告统一归档到对象存储,作为合规证据。
  • 每月一次的例行扫描任务,自动跑、自动报告。

31.5 复盘

踩过的坑:

  • 一次配 tcp_syncookies=0 导致某业务在 SYN flood 演练时假死。
  • 一次配 PermitRootLogin noAllowUsers 没写,结果所有用户都登不进。
  • 一次 chattr +i 把 /etc/shadow 锁了,添加用户前忘了解锁。

经验:所有改动必须有验证步骤、有应急回退、有第二人复核。

三十二、致谢与参考

加固领域的几个关键参考:

  • CIS Benchmarks(Center for Internet Security):行业公认基线。
  • NIST SP 800-53:美国联邦信息安全控制目录。
  • DISA STIG:国防部安全技术实施指南。
  • OWASP:Web 应用安全。
  • MITRE ATT&CK:攻击者战术和技战术库,做威胁建模时参考。

工具:

  • OpenSCAP:基线扫描。
  • Lynis:通用安全审计。
  • fail2ban:防爆破。
  • chkrootkit / rkhunter:rootkit 检测。
  • AIDE / Tripwire:文件完整性。
  • auditd:系统审计。

保持好奇心、保持怀疑、保持记录。加固这件事永远是 80% 实践 + 20% 理论,看完就去动手做。欢迎在云栈社区与更多工程师交流你的实战心得。




上一篇:跑刀去非洲:中国商人在马达加斯加的游戏代练创业实录
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-6-17 04:05 , Processed in 1.218352 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表