云计算百科
云计算领域专业知识百科平台

Linux 安全加固完整篇:从 SSH、防火墙到SELinux/AppArmor 与审计

「密钥泄露仍被扫端口爆破」「sudo NOPASSWD 全权限」「防火墙开了但 Docker 绕过」——加固失败多在 默认配置未改、规则顺序错误、MAC 未 Enforcing。本文按 OpenSSH、firewalld/nftables、auditd 真实路径展开。

源码锚点

路径 / 配置作用
/etc/ssh/sshd_config SSH 服务端
/etc/ssh/ssh_config SSH 客户端
man sshd_config 指令说明
/etc/sudoers sudo 主配置
/etc/sudoers.d/ 片段
visudo 语法校验
/etc/firewalld/ firewalld zone
man firewalld.richlanguage 富规则
nft list ruleset nftables
/etc/nftables.conf nft 持久化
/etc/fail2ban/jail.local fail2ban
/etc/selinux/config SELinux 模式
getenforce / semanage SELinux
/etc/apparmor.d/ AppArmor profile
aa-status AppArmor
/etc/audit/auditd.conf auditd
/etc/audit/rules.d/ 审计规则
ausearch / aureport 审计查询
/etc/sysctl.d/ 内核安全参数
/var/log/auth.log 或 secure 认证日志

sshd -T | grep -Ei 'permitroot|password|pubkey'; sudo -l; firewall-cmd –list-all 2>/dev/null || nft list ruleset | head

调用链

SSH 认证

渲染错误: Mermaid 渲染失败: Parse error on line 4:
…d Accept S –> V{认证} V –>|Pubke
———————-^
Expecting 'SQE', 'DOUBLECIRCLEEND', 'PE', '-)', 'STADIUMEND', 'SUBROUTINEEND', 'PIPE', 'CYLINDEREND', 'DIAMOND_STOP', 'TAGEND', 'TRAPEND', 'INVTRAPEND', 'UNICODE_TEXT', 'TEXT', 'TAGSTART', got 'DIAMOND_START'

防火墙 zone

#mermaid-svg-S4h5ITerxiym8u1E{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-S4h5ITerxiym8u1E .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-S4h5ITerxiym8u1E .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-S4h5ITerxiym8u1E .error-icon{fill:#552222;}#mermaid-svg-S4h5ITerxiym8u1E .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-S4h5ITerxiym8u1E .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-S4h5ITerxiym8u1E .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-S4h5ITerxiym8u1E .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-S4h5ITerxiym8u1E .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-S4h5ITerxiym8u1E .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-S4h5ITerxiym8u1E .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-S4h5ITerxiym8u1E .marker{fill:#333333;stroke:#333333;}#mermaid-svg-S4h5ITerxiym8u1E .marker.cross{stroke:#333333;}#mermaid-svg-S4h5ITerxiym8u1E svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-S4h5ITerxiym8u1E p{margin:0;}#mermaid-svg-S4h5ITerxiym8u1E .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-S4h5ITerxiym8u1E .cluster-label text{fill:#333;}#mermaid-svg-S4h5ITerxiym8u1E .cluster-label span{color:#333;}#mermaid-svg-S4h5ITerxiym8u1E .cluster-label span p{background-color:transparent;}#mermaid-svg-S4h5ITerxiym8u1E .label text,#mermaid-svg-S4h5ITerxiym8u1E span{fill:#333;color:#333;}#mermaid-svg-S4h5ITerxiym8u1E .node rect,#mermaid-svg-S4h5ITerxiym8u1E .node circle,#mermaid-svg-S4h5ITerxiym8u1E .node ellipse,#mermaid-svg-S4h5ITerxiym8u1E .node polygon,#mermaid-svg-S4h5ITerxiym8u1E .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-S4h5ITerxiym8u1E .rough-node .label text,#mermaid-svg-S4h5ITerxiym8u1E .node .label text,#mermaid-svg-S4h5ITerxiym8u1E .image-shape .label,#mermaid-svg-S4h5ITerxiym8u1E .icon-shape .label{text-anchor:middle;}#mermaid-svg-S4h5ITerxiym8u1E .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-S4h5ITerxiym8u1E .rough-node .label,#mermaid-svg-S4h5ITerxiym8u1E .node .label,#mermaid-svg-S4h5ITerxiym8u1E .image-shape .label,#mermaid-svg-S4h5ITerxiym8u1E .icon-shape .label{text-align:center;}#mermaid-svg-S4h5ITerxiym8u1E .node.clickable{cursor:pointer;}#mermaid-svg-S4h5ITerxiym8u1E .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-S4h5ITerxiym8u1E .arrowheadPath{fill:#333333;}#mermaid-svg-S4h5ITerxiym8u1E .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-S4h5ITerxiym8u1E .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-S4h5ITerxiym8u1E .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-S4h5ITerxiym8u1E .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-S4h5ITerxiym8u1E .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-S4h5ITerxiym8u1E .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-S4h5ITerxiym8u1E .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-S4h5ITerxiym8u1E .cluster text{fill:#333;}#mermaid-svg-S4h5ITerxiym8u1E .cluster span{color:#333;}#mermaid-svg-S4h5ITerxiym8u1E div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-S4h5ITerxiym8u1E .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-S4h5ITerxiym8u1E rect.text{fill:none;stroke-width:0;}#mermaid-svg-S4h5ITerxiym8u1E .icon-shape,#mermaid-svg-S4h5ITerxiym8u1E .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-S4h5ITerxiym8u1E .icon-shape p,#mermaid-svg-S4h5ITerxiym8u1E .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-S4h5ITerxiym8u1E .icon-shape rect,#mermaid-svg-S4h5ITerxiym8u1E .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-S4h5ITerxiym8u1E .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-S4h5ITerxiym8u1E .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-S4h5ITerxiym8u1E :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

nftables/iptables

firewalld zone

service/port/rich rule

ACCEPT/DROP

Docker DNAT

auditd 事件

auditdkernel auditsyscallauditdkernel auditsyscall#mermaid-svg-56VZtVifGJU1OfV1{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-56VZtVifGJU1OfV1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-56VZtVifGJU1OfV1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-56VZtVifGJU1OfV1 .error-icon{fill:#552222;}#mermaid-svg-56VZtVifGJU1OfV1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-56VZtVifGJU1OfV1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-56VZtVifGJU1OfV1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-56VZtVifGJU1OfV1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-56VZtVifGJU1OfV1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-56VZtVifGJU1OfV1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-56VZtVifGJU1OfV1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-56VZtVifGJU1OfV1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-56VZtVifGJU1OfV1 .marker.cross{stroke:#333333;}#mermaid-svg-56VZtVifGJU1OfV1 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-56VZtVifGJU1OfV1 p{margin:0;}#mermaid-svg-56VZtVifGJU1OfV1 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-56VZtVifGJU1OfV1 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-56VZtVifGJU1OfV1 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-56VZtVifGJU1OfV1 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-56VZtVifGJU1OfV1 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-56VZtVifGJU1OfV1 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-56VZtVifGJU1OfV1 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-56VZtVifGJU1OfV1 .sequenceNumber{fill:white;}#mermaid-svg-56VZtVifGJU1OfV1 #sequencenumber{fill:#333;}#mermaid-svg-56VZtVifGJU1OfV1 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-56VZtVifGJU1OfV1 .messageText{fill:#333;stroke:none;}#mermaid-svg-56VZtVifGJU1OfV1 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-56VZtVifGJU1OfV1 .labelText,#mermaid-svg-56VZtVifGJU1OfV1 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-56VZtVifGJU1OfV1 .loopText,#mermaid-svg-56VZtVifGJU1OfV1 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-56VZtVifGJU1OfV1 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-56VZtVifGJU1OfV1 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-56VZtVifGJU1OfV1 .noteText,#mermaid-svg-56VZtVifGJU1OfV1 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-56VZtVifGJU1OfV1 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-56VZtVifGJU1OfV1 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-56VZtVifGJU1OfV1 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-56VZtVifGJU1OfV1 .actorPopupMenu{position:absolute;}#mermaid-svg-56VZtVifGJU1OfV1 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-56VZtVifGJU1OfV1 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-56VZtVifGJU1OfV1 .actor-man circle,#mermaid-svg-56VZtVifGJU1OfV1 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-56VZtVifGJU1OfV1 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}匹配 rules.dnetlink/var/log/audit/audit.log

重点知识

最小权限原则

账户:禁用无用账号;服务用专用系统用户;禁止共享私钥。

文件:/etc/shadow 600;SSH 私钥 600;目录 750。定期审计 SUID/SGID。

awk -F: '($3==0){print}' /etc/passwd
find / -perm -4000 -type f 2>/dev/null | head
find /home -name id_rsa -exec ls -l {} \\;

SSH 加固

推荐:PermitRootLogin no、PasswordAuthentication no、PubkeyAuthentication yes。

限制用户:AllowUsers deploy 或 AllowGroups sshusers;MaxAuthTries 3。

# /etc/ssh/sshd_config
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
AllowUsers deploy
sshd -t && systemctl reload sshd
sshd -T | grep -i permitroot

sudo 配置

用 visudo 编辑;NOPASSWD 仅必要时且 命令白名单,禁止 ALL。

Defaults logfile=/var/log/sudo.log 留痕;requiretty 自动化环境常需关闭。

# /etc/sudoers.d/deploy
deploy ALL=(ALL) NOPASSWD: /bin/systemctl reload nginx
sudo -l -U deploy
grep sudo /var/log/auth.log | tail

firewalld 与 nftables

firewalld:–permanent 写入 XML,–reload 生效。默认 zone 绑定接口。

Docker 可能插入 DOCKER 链绕过 firewalld 直觉;需 firewall-cmd –permanent –zone=trusted –change-interface=docker0 等策略。

firewall-cmd –get-active-zones
firewall-cmd –list-all –zone=public
firewall-cmd –permanent –remove-service=cockpit
firewall-cmd –reload
nft list ruleset

fail2ban

读 auth 日志匹配失败次数,调用 firewall ban IP。

jail.local 覆盖默认;filter 在 /etc/fail2ban/filter.d/。

# /etc/fail2ban/jail.local
[sshd]
enabled=true
maxretry=5
bantime=3600
fail2ban-client status sshd

SELinux

模式 Enforcing/Permissive/Disabled。容器/自定义端口需 semanage port;文件上下文 semanage fcontext + restorecon。

AVC 拒绝:ausearch -m avc -ts recent;audit2allow 生成策略(需人工审)。

getenforce
semanage port -l | grep http
semanage fcontext -a -t httpd_sys_content_t '/web(/.*)?'
restorecon -Rv /web
ausearch -m avc -ts recent

AppArmor

Ubuntu 常见。profile 在 /etc/apparmor.d/;complain 模式只记不拦。

aa-status
apparmor_parser -r /etc/apparmor.d/usr.sbin.nginx
journalctl | grep -i apparmor | tail

auditd 审计

规则 /etc/audit/rules.d/;augenrules –load 加载。跟踪文件 -w path -p wa -k key。

-w /etc/passwd -p wa -k passwd_changes
-a always,exit -F arch=b64 -S execve -k exec
augenrules –load
ausearch -k passwd_changes
aureport -x –summary

内核 sysctl 安全

防 spoof、icmp redirect、syn flood 等;ASLR randomize_va_space=2。

# /etc/sysctl.d/99-hardening.conf
net.ipv4.conf.all.rp_filter=1
net.ipv4.conf.all.accept_redirects=0
kernel.randomize_va_space=2
kernel.kptr_restrict=2
fs.protected_symlinks=1
sysctl –system

更新与漏洞响应

订阅 CVE;unattended-upgrades 或镜像仓;内核/glibc/OpenSSL 优先。

apt list –upgradable 2>/dev/null || yum check-update
needs-restarting -r 2>/dev/null
reboot # 内核更新后

常见误配

PermitRootLogin yes、chmod 777、sudo NOPASSWD:ALL、firewalld 停、SELinux Disabled、auditd 未启——五条最常见生产事故源。

项说明
误配 后果
root SSH 爆破面
777 目录 任意写
NOPASSWD ALL 等价 root
firewalld 停 全端口暴露

加固实践深化

实践 1:SSH 密钥权限

过宽 sshd 拒绝

chmod 700 ~/.ssh; chmod 600 ~/.ssh/authorized_keys

实践 2:ssh-audit

算法强度审计

ssh-audit localhost 2>/dev/null || true

实践 3:PAM faillock

账户锁定

faillock –user badguy 2>/dev/null

实践 4:sftp chroot

隔离上传

# Match Group sftp / ChrootDirectory /srv/sftp

实践 5:hosts.allow

TCP Wrappers

grep sshd /etc/hosts.allow 2>/dev/null

实践 6:AIDE

完整性

aide –check 2>/dev/null

实践 7:lynis

基线扫描

lynis audit system 2>/dev/null | tail -5

实践 8:TLS 探测

cipher 版本

openssl s_client -connect host:443 -brief </dev/null

实践 9:iptables legacy

与 nft 并存

iptables -L -n -v | head

实践 10:podman rootless

无 root 边界

podman unshare cat /proc/self/cgroup | head

实践 11:SSH ForceCommand

限制 shell

# ForceCommand /usr/bin/ls

实践 12:SSH Match User

按用户策略

# Match User alice / AllowTcpForwarding no

实践 13:firewalld rich

源 IP 白名单

firewall-cmd –add-rich-rule='rule family=ipv4 source address=10.0.0.0/8 accept'

实践 14:nft drop all

默认拒绝

nft add rule inet filter input drop

实践 15:fail2ban unban

解封

fail2ban-client set sshd unbanip 1.2.3.4

实践 16:audit execve

谁 exec 了什么

ausearch -m EXECVE -ts today

实践 17:audit login

登录事件

ausearch -m USER_LOGIN -ts today

实践 18:chattr +i

防篡改标志

lsattr /etc/passwd

实践 19:passwd -l

锁定账户

passwd -l olduser

实践 20:userdel

删户及家目录

userdel -r serviceacct

实践 21:groupmod

sudo 组成员

getent group sudo

实践 22:umask

默认创建权限

umask 027

实践 23:pam_tally2

PAM 模块

# 旧系统失败计数

实践 24:sshd AllowAgentForwarding

代理转发

sshd -T | grep allowagentforwarding

实践 25:sshd X11Forwarding

X11 转发

sshd -T | grep x11forwarding

实践 26:setroubleshoot

SELinux 建议

sealert -a /var/log/audit/audit.log 2>/dev/null

实践 27:sepolicy generate

生成 SELinux 模块草稿

sepolicy generate –init nginx

实践 28:apparmor complain

调试 profile

aa-complain /usr/sbin/nginx

实践 29:apparmor enforce

强制模式

aa-enforce /usr/sbin/nginx

实践 30:auditd space

日志轮转

grep max_log_file /etc/audit/auditd.conf

CIS 分项检查

CIS 5.2 SSH 服务端

独立项:禁止空口令、限制 root、强 MAC。

sshd -T | awk '/permitrootlogin|permitemptypasswords|maxauthtries|logingracetime/ {print}'
awk '/^PermitRootLogin|^PasswordAuthentication|^MaxAuthTries|^LoginGraceTime/ {print NR":"$0}' /etc/ssh/sshd_config
stat -c '%a %U %G' /etc/ssh/sshd_config
find /etc/ssh -name 'ssh_host_*_key' -exec stat -c '%a %n' {} \\;

期望:PermitRootLogin no;host key 600 root:root。

CIS 5.3 sudo 策略

visudo -c
grep -rE 'NOPASSWD|ALL=\\(ALL\\)|!authenticate' /etc/sudoers /etc/sudoers.d/ 2>/dev/null
awk -F: '$3==0 {print}' /etc/passwd
getent group sudo wheel
lastlog | awk '$3!="**Never logged in**" {print}' | head

CIS 3.5 防火墙与 nftables

systemctl is-enabled firewalld nftables 2>/dev/null
firewall-cmd –get-default-zone 2>/dev/null
firewall-cmd –list-all-zones 2>/dev/null | head -40
nft list ruleset | head -60
ss -lntup | awk 'NR==1 || /0.0.0.0:|\\[::\\]:/'

CIS 1.6 SELinux 状态

getenforce
grep ^SELINUX= /etc/selinux/config
sestatus
semanage boolean -l | grep -i httpd | head
ausearch -m avc -ts recent 2>/dev/null | tail -5

CIS 4.1 审计 daemon

systemctl is-active auditd
auditctl -l
grep -E '^(max_log_file|space_left_action|admin_space_left_action)' /etc/audit/auditd.conf
aureport -s | head -20
ls -la /etc/audit/rules.d/

CIS 3.3 内核网络 sysctl

sysctl net.ipv4.ip_forward net.ipv4.conf.all.rp_filter net.ipv4.conf.all.accept_redirects
sysctl net.ipv4.tcp_syncookies kernel.randomize_va_space kernel.kptr_restrict
grep -r . /etc/sysctl.d/*.conf 2>/dev/null | grep -v '^#'
sysctl –system 2>&1 | tail -5

CIS 1.8 补丁与软件源

apt list –upgradable 2>/dev/null | head -20
dnf updateinfo list security 2>/dev/null | head
rpm -q –changelog kernel | head -5
unattended-upgrades -d 2>/dev/null | tail -10
grep -r ^deb /etc/apt/sources.list /etc/apt/sources.list.d/ 2>/dev/null

漏洞扫描与 SBOM

# Trivy 主机+镜像
trivy rootfs /
trivy image –severity HIGH,CRITICAL nginx:1.25
# Grype
syft dir:/ -o json > sbom.json
grype sbom:sbom.json

# OpenSCAP
oscap xccdf eval –profile xccdf_org.ssgproject.content_profile_cis /usr/share/xml/scap/ssg/content/ssg-*.xml 2>/dev/null | tail -20

TLS 证书与 cipher 审计

openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -dates -subject -issuer
testssl.sh –quiet https://example.com 2>/dev/null | grep -E 'NOT ok|OK'
certbot certificates 2>/dev/null
grep -r SSLProtocol /etc/httpd /etc/nginx 2>/dev/null

# 本地 PEM 过期扫描
find /etc/ssl /etc/pki -name '*.pem' -exec openssl x509 -in {} -noout -enddate \\; 2>/dev/null

容器宿主机加固

docker info –format '{{.SecurityOptions}}'
grep -E 'user.max_user_namespaces|kernel.unprivileged_userns_clone' /proc/sys/*/* 2>/dev/null
systemctl show docker -p ExecStart | tr ' ' '\\n' | grep userns
auditctl -w /usr/bin/docker -p wa -k docker_bin

项建议命令
套接字 root 才能连 ls -l /var/run/docker.sock
用户命名空间 按需关闭 sysctl kernel.unprivileged_userns_clone
镜像签名 cosign verify cosign verify –key cosign.pub img

podman info –format '{{.Host.Security}}'
grep NOFILE /etc/systemd/system/docker.service.d/*.conf 2>/dev/null

应急响应取证

# 隔离但保留内存(若可行)
ip link set eth0 down
systemctl stop sshd
# 快照
tar czf /media/usb/evidence-$(hostname)$(date +%F).tgz /var/log/auth.log /var/log/audit/audit.log /root/.ssh 2>/dev/null

last -20
lastb -20 2>/dev/null
ausearch -m USER_LOGIN -sv no –interpret | tail -20
ss -antp | awk '$1=="ESTAB"'
lsof -i -P -n | head -30

# 哈希可疑二进制
sha256sum /usr/bin/.hidden 2>/dev/null
rpm -Vf /usr/bin/ss 2>/dev/null
debsums -c 2>/dev/null | head

误配案例与修复

误配检测修复
/etc/ssh/sshd_config 末尾 PermitRootLogin yes 覆盖前面 no 见上节命令 `sshd -T
firewalld public 区 –add-service=ssh 但未 –permanent 见上节命令 重启丢规则;firewall-cmd –runtime-to-permanent。
audit 规则 -e 2 未生效 见上节命令 auditctl -s 看 enabled;fix /etc/audit/rules.d/ 后 augenrules –load。
net.ipv4.ip_forward=1 忘记关 见上节命令 非网关主机:sysctl -w net.ipv4.ip_forward=0 写入 sysctl.d。
Docker 0.0.0.0:2375 无 TLS 见上节命令 `ss -lntp
sudoers %wheel ALL=(ALL) NOPASSWD: ALL 见上节命令 grep NOPASSWD /etc/sudoers.d/*;改回需密码。

# 一键导出加固快照(不含密钥)
{
echo '== sshd -T =='; sshd -T 2>/dev/null | head -30
echo '== sudoers =='; visudo -c
echo '== firewall =='; nft list ruleset 2>/dev/null | head -20
echo '== selinux =='; getenforce
echo '== audit =='; auditctl -s
} > /tmp/hardening-snapshot.txt

加固演练 1:SSH 密钥轮换

find /etc/ssh -name 'ssh_host_*_key.pub' -exec ssh-keygen -lf {} \\;
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ''

加固演练 2:PAM faillock

grep pam_faillock /etc/pam.d/system-auth /etc/pam.d/password-auth 2>/dev/null
faillock –user baduser

加固演练 3:chroot sftp

grep -i chroot /etc/ssh/sshd_config
Match Group sftpusers
ChrootDirectory /srv/sftp/%u

加固演练 4:nft 限流

nft list chain inet filter input 2>/dev/null
nft add rule inet filter input tcp dport 22 ct state new limit rate 5/minute accept

加固演练 5:AIDE 完整性

aide –check 2>/dev/null | tail -5
aideinit && mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz

CIS 5.4 账户与口令策略

login.defs 控制 PASS_MAX_DAYS、UMASK。

grep -E 'PASS_MAX_DAYS|PASS_MIN_DAYS|UMASK|ENCRYPT_METHOD' /etc/login.defs
chage -l root
awk -F: '($2=="" || $2=="!") {print}' /etc/shadow # 空口令
pam-auth-update –list 2>/dev/null

CIS 2.2 不必要服务

systemctl list-unit-files –state=enabled –type=service | grep -Ei 'telnet|rsh|ftp|tftp'
ss -lntup | grep -E ':23|:21|:513'
chkconfig –list 2>/dev/null | grep on
rpm -q telnet-server vsftpd 2>/dev/null

CIS 4.2 日志权限

ls -l /var/log/secure /var/log/auth.log /var/log/audit/audit.log 2>/dev/null
grep ^$ /etc/rsyslog.conf /etc/rsyslog.d/*.conf 2>/dev/null | head
systemctl status rsyslog journald | head -6
journalctl –verify 2>/dev/null | tail -3

CIS 3.7 禁用无线

nmcli radio wifi 2>/dev/null
rfkill list
lsmod | grep -E 'bluetooth|wifi'
systemctl is-enabled bluetooth 2>/dev/null

CIS 6.1 文件权限审计

find /etc -perm /077 -type f 2>/dev/null | head -10
find / -xdev -nouser -o -nogroup 2>/dev/null | head
rpm -Va 2>/dev/null | grep '^..5' | head
debsums -c 2>/dev/null | head

Lynis 与 OpenVAS 采样

lynis audit system –quick 2>/dev/null | tail -30
grep Suggestion /var/log/lynis.log 2>/dev/null | tail -10
gvm-cli socket –xml '<get_tasks/>' 2>/dev/null | head

nginx/apache TLS 片段

nginx -T 2>/dev/null | grep -E 'ssl_protocols|ssl_ciphers|ssl_prefer'
apachectl -S 2>/dev/null | head
grep -r SSLCertificate /etc/httpd /etc/apache2 2>/dev/null | head
openssl ciphers -v 'ECDHE+AESGCM' | head

容器 runtime 加固对照

检查命令期望
seccomp docker inspect –format '{{.HostConfig.SecurityOpt}}' id 非 unconfined
cap drop docker inspect –format '{{.HostConfig.CapDrop}}' id 去掉 ALL 再 add
read-only root –read-only
AppArmor docker inspect .HostConfig.SecurityOpt docker-default

docker run –rm –read-only –cap-drop ALL alpine id
crictl inspect $(crictl ps -q | head -1) 2>/dev/null | jq .info.runtimeSpec.linux.security

应急隔离 playbook

# 1. 断外网保内网排障
iptables -I OUTPUT 1 -d 10.0.0.0/8 -j ACCEPT
iptables -A OUTPUT -j DROP
# 2. 保留审计
systemctl restart auditd
auditctl -l | head
# 3. 导出连接
ss -antp > /root/incident-ss.txt

误配深度案例

案例检测修复
/etc/pam.d/sshd 缺 pam_faillock grep faillock /etc/pam.d/sshd 复制 password-auth 中 faillock 段
journald 未持久化 grep Storage /etc/systemd/journald.conf Storage=persistent 后 restart journald
IPv6 全暴露 `ss -lntp6 grep -v tcp6.*127`
world-writable cron find /etc/cron* -perm -002 chmod o-w
nginx 以 root 运行 `ps -o user,cmd -C nginx head`

sshd -T | grep -Ei 'ciphers|macs|kexalgorithms' | tr ',' '\\n' | head -15
update-crypto-policies –show 2>/dev/null

合规快照命令组

快照 1:账户指纹

getent passwd | awk -F: '$3>=1000 && $3<65534 {print $1,$3,$7}'

快照 2:监听端口

ss -lntup | awk 'NR>1{print $5,$7}' | sort -u

快照 3:SUID 列表

find /usr /bin -xdev -perm -4000 -type f 2>/dev/null | head -20

快照 4:计划任务

systemctl list-timers –all | head -15

快照 5:内核模块

lsmod | awk 'NR>1{print $1,$2}' | sort -k2 -rn | head

快照 6:挂载选项

findmnt -lo TARGET,OPTIONS | grep -v nodev

快照 7:PAM 栈

grep -v '^#' /etc/pam.d/sshd | head -10

快照 8:DNS 信任

resolvectl domain 2>/dev/null; cat /etc/resolv.conf

快照 9:时间同步

timedatectl show | grep -E 'NTPSynchronized|Timezone'

快照 10:容器套接字

ls -l /var/run/docker.sock /run/podman/podman.sock 2>/dev/null

SSH 客户端加固

ssh -G user@host 2>/dev/null | grep -Ei 'ciphers|macs|hostkeyalgorithms'
grep -Ei 'HashKnownHosts|StrictHostKeyChecking' /etc/ssh/ssh_config /etc/ssh/ssh_config.d/* 2>/dev/null

sudo 日志与 I/O 日志

grep -r logfile /etc/sudoers /etc/sudoers.d/ 2>/dev/null
grep iolog_dir /etc/sudoers 2>/dev/null
tail /var/log/sudo.log 2>/dev/null

firewalld rich rule 样例

firewall-cmd –permanent –add-rich-rule='rule family=ipv4 source address=10.0.0.0/8 port port=22 protocol=tcp accept'
firewall-cmd –reload
firewall-cmd –list-rich-rules

audit 关键规则样例

grep -r execve /etc/audit/rules.d/
auditctl -w /etc/passwd -p wa -k passwd_changes
ausearch -k passwd_changes -ts recent 2>/dev/null | tail

sysctl 硬化片段文件

cat > /etc/sysctl.d/99-hardening.conf <<'EOF'
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
fs.protected_hardlinks = 1
EOF

sysctl –system | tail -5

工具链 1:ModSecurity 采样

nginx -V 2>&1 | grep -i modsecurity
tail /var/log/modsec_audit.log 2>/dev/null

工具链 2:ClamAV 更新

freshclam 2>/dev/null | tail -3
clamscan -r /tmp 2>/dev/null | tail -3

工具链 3:RKHunter

rkhunter –check –sk 2>/dev/null | tail -5
grep Warning /var/log/rkhunter.log 2>/dev/null

工具链 4:USB 存储禁

grep usb-storage /etc/modprobe.d/* 2>/dev/null
lsmod | grep usb_storage

工具链 5:密码哈希

grep ENCRYPT_METHOD /etc/login.defs
awk -F: '{print $2}' /etc/shadow | head | cut -c1-3

最小暴露服务基线

systemctl list-units –type=service –state=running –no-pager | wc -l
ss -lntup | awk 'NR>1{print $5}' | sort -u

基线延伸 1:空口令账户

awk -F: '($2=="" || $2=="x") && $1!="root" {print $1}' /etc/shadow

赞(0)
未经允许不得转载:网硕互联帮助中心 » Linux 安全加固完整篇:从 SSH、防火墙到SELinux/AppArmor 与审计
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!