上一篇 下一篇 分享链接 返回 返回顶部

如何在香港服务器上配置 Linux LSM(安全模块),满足金融与跨境支付业务的合规要求?

发布人:Minchunlin 发布时间:2025-08-19 10:35 阅读量:560


凌晨 01:20,我站在香港将军澳机房的冷通道里,手背贴着 1U 机箱的前面板,温度显示 23℃。那盏熟悉的红色告警灯刚刚熄灭,旁边同事把工单夹回透明夹板:“合规审计清单最后一项——生产支付网关启用 LSM 强化——今天必须落地。”

两周前,审计给了我们一摞要求:最小权限、强制访问控制(MAC)、系统调用约束、审计可追溯、变更可回滚。落地在 Linux 上,就是把 LSM(Linux Security Modules) 这套能力(SELinux/AppArmor/Yama/seccomp 等)真正跑起来,并把证据留好。纸面上很简单,机房里一旦开错一个布尔量或者标签,凌晨的报警会让你记得一辈子。

这篇文,是我把那一夜以及之后一周收尾的过程,完整写给做金融和跨境支付的同行。不是玄学,也不是“开个开关就安全”,而是一步步、带数据、可复现的实操笔记。

免责声明:本文分享技术落地经验,不构成法律意见。金融合规应与法务/内控/审计共同评估。

1. 场景与硬件清单(HK 机房真实参数)

我们三类节点:

角色 型号与配置 操作系统 主要软件
支付网关 (GW01~GW04) Dell R740(2×Xeon Silver 4210, 128GB RAM, 2×1.92TB NVMe PM983, 2×10GbE Intel X710) CentOS 7.9(3.10.0-1160.el7.x86_64) Nginx/OpenResty、LuaJIT、Keepalived、rsyslog、auditd、Docker 20.10(container-selinux)
风控服务 (RK01~RK02) Supermicro 1029U-TRT(同等配置) CentOS 7.9 Java 11、gRPC、Redis、Zookeeper
结算与账务 (DB01~DB02) Dell R740xd(改为 8×1.92TB NVMe, HBA 模式) CentOS 7.9 PostgreSQL 12、Patroni、pgBouncer、WAL-G

为什么 CentOS 7? 历史原因 + 兼容性稳定,且我们有长期维护的基线脚本。LSM 选择以 SELinux(targeted 策略)+ Yama 为主;容器侧用 seccomp 与 SELinux MCS。

注:如果你是新部署,建议直接上 RHEL 9/AlmaLinux 9 或 Ubuntu 22.04+,获得更新的内核与 LSM stacking(多模块并存)与 Landlock/BPF LSM 能力。本文也在后文给出迁移路线。

2. 合规目标与控制矩阵(把“要求”翻译成“配置”)

合规/审计要求 技术控制 在本文中的实现
最小权限(资源访问隔离) 强制访问控制(MAC) SELinux Targeted 策略 + 自定义 TE 模块;容器卷使用 :Z/ :z 语义
变更可追溯 审计日志(Who/When/What) auditd 规则 + rsyslog 远程写入 + 完整性校验(AIDE)
入侵面收敛 系统调用过滤 Docker 默认 seccomp profile(精简版)+ 对关键 Daemon 的 NoNewPrivileges
调试能力控制 ptrace 限制 Yama kernel.yama.ptrace_scope=2,仅允许父子关系
口令/密钥保护 文件标签与布尔量 semanage fcontext 标注密钥目录,仅特定域可读
数据面/控制面分离 网络与进程域限制 Nginx、Postgres 各自独立域,最小布尔放行;手工允许特定端口绑定
可验证性 可重复交付与证据 基线 Ansible 角色、执行记录、策略包(.pp)与审计报表(CSV/JSON)

3. 方案选型与变更策略

LSM 选型:CentOS/RHEL 系列首选 SELinux;Ubuntu 选 AppArmor(后文给替代步骤)。

上线策略:三阶段——Permissive → Enforcing(灰度) → 全量 Enforcing。

回滚:Grub 启动项保留 selinux=0 enforcing=0 备选;关键节点保留 policy-rollback.pp;策略包版本化。

窗口:00:30–02:30,DNS/流量按 25% → 50% → 100% 切换。

4. 上线前的“安全基线”

4.1 内核参数(/etc/sysctl.d/99-security.conf)

# 调试与信息泄露面
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
kernel.perf_event_paranoid = 3
kernel.unprivileged_bpf_disabled = 1
kernel.yama.ptrace_scope = 2

# 网络面
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0

应用并持久化:

sysctl --system

4.2 审计与日志

yum install -y audit audit-libs audispd-plugins rsyslog
systemctl enable --now auditd rsyslog

/etc/audit/rules.d/lsm.rules:

## 关键目录与二进制完整性
-w /etc/selinux/ -p wa -k selinux
-w /etc/audit/ -p wa -k auditconf
-w /usr/sbin/semanage -p x -k selinux_tools
-w /usr/sbin/setsebool -p x -k selinux_tools
-w /usr/sbin/semodule -p x -k selinux_tools

## 身份与特权
-a always,exit -F arch=b64 -S sethostname -S setdomainname -k sysctl
-a always,exit -F arch=b64 -S init_module -S finit_module -S delete_module -k module
-a always,exit -F arch=b64 -S mount -S umount2 -k mount
auditctl -R /etc/audit/rules.d/lsm.rules
augenrules --load

远程日志 /etc/rsyslog.d/50-remote.conf:

*.* @@10.66.8.10:514;RSYSLOG_SyslogProtocol23Format

记得在合规里保留日志链路图与样例记录。

5. SELinux 部署:从探路到落地

5.1 当前状态与模式

getenforce
sestatus
cat /etc/selinux/config | grep -E 'SELINUX|TYPE'

期望:SELINUX=permissive 起步,策略 SELINUXTYPE=targeted。

切换到 Permissive(若原先是 disabled):

sed -ri 's/^SELINUX=.*/SELINUX=permissive/' /etc/selinux/config
touch /.autorelabel
reboot

.autorelabel:首次启用必做,否则大量 denied 来自错误标签。

5.2 标注关键路径(fcontext)

支付密钥与证书:

semanage fcontext -a -t cert_t "/var/secure/keys(/.*)?"
restorecon -Rv /var/secure/keys

Nginx 网关静态与 Lua 脚本:

semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/gw(/.*)?"
restorecon -Rv /var/www/gw

PostgreSQL 数据:

semanage fcontext -a -t postgresql_db_t "/pgdata(/.*)?"
restorecon -Rv /pgdata

5.3 服务布尔量(Booleans)

getsebool -a | grep httpd
setsebool -P httpd_can_network_connect on
setsebool -P httpd_can_network_connect_db on
setsebool -P nis_enabled off

常见布尔量清单:

服务 布尔量 说明
Nginx/OpenResty httpd_can_network_connect 允许对外发起连接(上游、Redis 等)
Nginx → DB httpd_can_network_connect_db 连接数据库所需
反向代理 WebSocket httpd_can_network_relay WebSocket/转发场景
Docker/容器 container_use_cephfs 视存储插件而定

原则:只开必要的开关,开前先在 Permissive 收集 AVC,再精准放行。

5.4 从审计生成策略(audit2allow → .te/.pp)

触发业务流量,收集 AVC:

ausearch -m avc -ts recent > /root/avc.log
sealert -a /var/log/audit/audit.log | tee /root/sealert.txt

生成最小策略:

cat /root/avc.log | audit2allow -M gw_custom
semodule -i gw_custom.pp

典型自定义策略(gw_custom.te 示例节选):

module gw_custom 1.0;
require {
  type httpd_t; type redis_port_t; class tcp_socket name_connect;
}
# 仅允许 httpd_t 连接 Redis 端口
allow httpd_t redis_port_t:tcp_socket name_connect;

小技巧:把“端口语义化”,而不是放开全部 name_connect。

5.5 灰度到 Enforcing

灰度:仅切一台 GW 到 Enforcing,由 LVS/Keepalived 调度 25% 流量,观察 30 分钟。

setenforce 1

平稳后覆盖到全部 GW,最后到风控与数据库节点。

6. 容器场景:SELinux + seccomp + 卷标注

6.1 Docker 与 SELinux

确保装有 container-selinux:

yum install -y container-selinux

挂载卷使用 :Z(私有标签)或 :z(共享标签):

docker run --name gw \
  -v /var/www/gw:/usr/local/openresty/nginx/html:Z \
  -p 443:443 -d openresty/openresty:alpine

6.2 Seccomp 精简配置(支付容器)

在 /etc/docker/seccomp-gw.json:

{
  "defaultAction": "SCMP_ACT_ERRNO",
  "syscalls": [
    { "names": ["accept4", "epoll_wait", "read", "write", "recvfrom", "sendto"], "action": "SCMP_ACT_ALLOW" },
    { "names": ["clone", "unshare", "kexec_load"], "action": "SCMP_ACT_ERRNO" }
  ]
}

运行:

docker run --security-opt seccomp=/etc/docker/seccomp-gw.json ...

6.3 systemd 限权(非容器进程)

/etc/systemd/system/gw.service 节选:

[Service]
ExecStart=/usr/local/openresty/nginx/sbin/nginx -g 'daemon off;'
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=true
CapabilityBoundingSet=CAP_NET_BIND_SERVICE

7. AppArmor 替代(Ubuntu 节点速用)

若边缘接入在 Ubuntu:

apt install apparmor apparmor-utils auditd
aa-status
aa-enforce /etc/apparmor.d/usr.sbin.nginx

自定义 profile(节选):

/usr/sbin/nginx {
  # 网络只允许 443 出口
  network inet stream,
  deny network raw,
  /var/www/gw/** r,
  /var/cache/nginx/** rw,
}

AppArmor 的语义对目录/文件粒度更直接,策略学习曲线更平。

8. 性能与压测数据(开启前后对比)

场景 QPS P95 延迟 CPU 利用 备注
GW(SELinux Permissive) 28k 12.4 ms 61% 基线
GW(SELinux Enforcing) 27.5k 12.9 ms 62% -1.8% QPS,影响可接受
GW(Enforcing+seccomp) 27.3k 13.1 ms 62% 再下降 0.7%
DB(Enforcing) 9.1k 18.7 ms 58% 无显著差异

观测:在我们业务模型下,SELinux 的额外开销可控;只要策略足够“窄”,长尾影响很小。

9. 典型坑点与现场排障手记

  • “.autorelabel 忘记”:重启后疯狂 denied,大量 system_u:object_r:default_t。解决:touch /.autorelabel && reboot,等待 10–20 分钟。
  • 布尔量开大:早期直接 httpd_can_network_connect on 但没限定端口,渗透测试提示可横向。解决:收集 AVC → 自定义 TE 仅放 redis_port_t/postgresql_port_t 等。
  • 容器卷没加 :Z:容器读写 13。解决:卷统一 :Z;共享目录再用 :z。
  • PostgreSQL 迁移:pg_wal 新盘忘了 restorecon,主从延迟。解决:新增 fcontext + restorecon -Rv。
  • auditd 规则太多:CPU 抖动。解决:聚焦关键事件 + 远程汇聚;为高频事件加 -F success=0 过滤。

排障速查:

ausyscall --dump | head
ausearch -m avc -ts recent
semanage boolean -l | column -t | less
ps -eZ | grep nginx
ls -Z /var/www/gw

10. 可验证交付:把“做了”变成“证据”

  • 策略包:gw_custom.pp、版本号、变更单号、生成时间、生成命令。
  • 系统状态快照:sestatus、getenforce、关键布尔量导出(见下脚本)。
  • 审计报表:ausearch 导出近 24h 关键 -k 的事件 CSV。
  • 配置留痕:Ansible 角色(selinux, auditd, rsyslog)与运行日志。

导出脚本 /usr/local/bin/lsm-report.sh:

#!/usr/bin/env bash
set -euo pipefail
mkdir -p /var/reports/lsm/$(date +%F)
D=/var/reports/lsm/$(date +%F)

# SELinux 状态
sestatus > "$D/sestatus.txt"
getenforce > "$D/getenforce.txt"

# 布尔量
getsebool -a | sort > "$D/booleans.txt"

# 策略模块
semodule -l > "$D/semodule_list.txt"

# 审计关键事件
ausearch -k selinux -ts yesterday | aureport -x --summary > "$D/audit_exec_summary.txt"
ausearch -k selinux -ts yesterday > "$D/audit_selinux.log" || true

tar czf "$D/../lsm-$(hostname)-$(date +%F).tar.gz" -C "$D/.." "$(date +%F)"
echo "Report at $D/../lsm-$(hostname)-$(date +%F).tar.gz"

11. 升级与迁移路线(想要更“新”的 LSM)

RHEL/Alma 9:保留 SELinux 主体,获得 LSM stacking 更完整支持;容器侧可配合 cgroup v2 + 系统 seccomp;可探索 eBPF LSM 精细化钩子(更高阶)。

Ubuntu 22.04+:AppArmor 默认;可引入 Landlock 在应用侧做“最小文件访问”沙箱(开发/批处理很香)。

蓝绿迁移:新老机房/机架并行,先在新平台 Enforcing,压测达标后再迁。

12. SOP:一键到位的变更流程卡

  • 变更评审(需求→控制矩阵)
  • 备份与回滚(快照/策略/Grub)
  • 基线(sysctl、auditd、rsyslog)
  • SELinux Permissive 启用与 .autorelabel
  • fcontext 标注关键路径
  • 业务压测 + 收集 AVC
  • audit2allow 生成最小策略 + 代码评审
  • 单机 Enforcing 灰度 + 指标观察
  • 全量 Enforcing + 报表归档
  • 渗透测试/红队验证 + 复盘

结尾:关灯之前

02:18,我从冷通道走出来,机柜门轻轻合上。监控屏上,GW 的 95 线稳定,审计规则也不再刷屏。门外港岛的风从电梯口灌进来,手机里弹出一条消息:“策略评审通过,证据齐全,可以收口了。”

我知道这事远没完:合规不是“通过一次审计”,而是把 安全变成系统的默认形态。LSM 不会替你做选择,它只是把“选择”固定下来。下一次——也许是 RHEL 9 的迁移,也许是 Landlock 的试点——我还会在这条冷风里,把每一次“开关”的动作,写成你能复用的 SOP。

如果你也在香港的某个机房加班,希望这份实操手记,能让你少踩几个坑,多睡一会

目录结构
全文