跳转至

安全基线与加固 (Security Baseline)

[!CAUTION] 必须执行:本文档是后续所有部署的前置条件。未通过本基线检查的服务器,严禁安装 Docker 或连接公网。 原则:Default Deny (默认拒绝) > Convenience (便利性)。


1. 网络层防御 (Network Layer)

1.1 Oracle Cloud Security List (第一道防线)

在 Oracle Cloud 控制台 -> Networking -> VCN -> Security List 中,删除默认的 "Allow All" 规则。 仅允许以下入站规则 (Ingress Rules):

⚠️ 必读配置细节: * 源端口范围 (Source Port Range): 务必留空或填 All。千万不要填 22/80 等。(这是对方机器的随机端口) * 目的端口范围 (Destination Port Range): 这里才是填 22/80/443 的地方。(这是你服务器监听的端口) * 端口格式 (Syntax): 如果控制台允许你填逗号 (如 80,443) 并保存成功,那就可以用。如果报错,请分两条规则写。 * 验证方法:配置完后在本地终端 telnet <IP> 80telnet <IP> 443 确认都通。

Protocol Destination Port Source CIDR Description Note
TCP 22 0.0.0.0/0 SSH 仅限密钥登录 (见下文)
TCP 80 0.0.0.0/0 HTTP 仅限 Web 业务
TCP 443 0.0.0.0/0 HTTPS 仅限 Web 业务
UDP 41641 0.0.0.0/0 Tailscale P2P 穿透 (必须开启)
ICMO - 0.0.0.0/0 Ping 方便监控连通性 (可选)
All All 10.0.0.0/16 VCN Internal Oracle 内网互通 (Swarm 必需)

严禁开放:9000 (Portainer), 8080 (Traefik Dashboard), 2375 (Docker API), 3306 (MySQL), 6379 (Redis)。

1.2 出站规则 (Egress Rules / Outbound)

对于普通服务器,保持全开 (Allow All) 即可。如果限制出站,你将无法执行 apt updatedocker pull 或访问外部 API。

Protocol Destination CIDR Port Description
All Protocols 0.0.0.0/0 All 允许所有出站流量 (默认配置)

💡 这会被攻击者利用吗? 是的,高级攻击者确实会利用 80/443 伪装成正常流量外传数据 (Data Exfiltration)。 但对于通用服务器,限制出站弊大于利(会导致系统更新、Docker 拉取、时钟同步频繁失败)。 真正的出站防护 需要 域名白名单 (Domain Whitelisting) 网关,这超出了基础防火墙 (Layer 4) 的能力范围。

1.3 主机防火墙 UFW (第二道防线)

即使 Oracle 安全组配置正确,主机层也必须配置防火墙,防止 Docker 自动修改 iptables 导致端口泄露 (Docker 的 iptables: true 特性会忽略 UFW,除非特殊配置,但我们要养成习惯)。

脚本:一键初始化 (分步执行)

Step 1: 基础防御 (UFW Base)

任何服务器都必须执行。

sudo apt update && sudo apt install -y ufw wget && \
sudo ufw default deny incoming && \
sudo ufw default allow outgoing && \
sudo ufw allow 22/tcp comment 'SSH' && \
sudo ufw allow 41641/udp comment 'Tailscale Direct' && \
sudo ufw allow in on tailscale0 comment 'Allow Tailscale Net' && \
sudo ufw allow from 10.0.0.0/16 comment 'Allow Oracle VCN' && \
sudo ufw --force enable && \
sudo ufw reload

Step 2: 容器增强 (ufw-docker Extension)

[新增] 如果这台机器要运行 Docker,必须执行此步以防穿透。

sudo wget -O /usr/local/bin/ufw-docker https://github.com/chaifeng/ufw-docker/raw/master/ufw-docker && \
sudo chmod +x /usr/local/bin/ufw-docker && \
sudo ufw-docker install && \
sudo ufw reload

💡 UFW 能完全接管 iptables 吗? 不能。UFW 本质上只是 iptables 的一个前端工具。 * Docker 的特权:Docker 会直接修改 iptables 的 PREROUTING 链,优先级高于 UFW。这就是 UFW 最大的坑:你以为封了端口,结果 Docker 一启容器,端口全开了。 * 解决方案: 1. Oracle 安全组 (第一道防线):必须配置。只要云厂商防火墙关了,Docker 再怎么折腾也出不去。 2. ufw-docker (修复 UFW):安装 ufw-docker 工具,让 UFW 能正确管理 Docker 暴露的端口。

🛡️ 安装 ufw-docker (强烈推荐)

解决 Docker 绕过 UFW 的问题,并提供便捷的容器防火墙管理。

# 1. 下载并安装脚本
sudo wget -O /usr/local/bin/ufw-docker https://github.com/chaifeng/ufw-docker/raw/master/ufw-docker
sudo chmod +x /usr/local/bin/ufw-docker

# 2. 安装规则 (这会修改 /etc/ufw/after.rules)
sudo ufw-docker install

# 3. 重启 UFW 生效
sudo ufw reload

⚠️ Swarm Mode 特别配置 (Critical)

注意ufw-docker 默认会拦截所有发往 Docker 容器的流量,包括 Swarm 内部的 Overlay 网络和 Ingress 流量。 必须手动添加白名单,否则 Traefik 无法连接后端服务,Ingress 端口也无法访问。

修改配置文件sudo nano /etc/ufw/after.rules 在文件末尾 (即 COMMIT 行之前) 添加:

# --- Docker Swarm & Traefik Fix ---
# 1. 允许 Docker 容器间互访 (解决 Swarm Overlay 网络不通问题)
-I DOCKER-USER -s 10.0.0.0/8 -j ACCEPT
-I DOCKER-USER -s 172.16.0.0/12 -j ACCEPT

# 2. 允许外网访问 Swarm Ingress 端口 (如 80/443)
# 即使 Oracle 安全组放行了,这里不放行也会被 reject
-I DOCKER-USER -p tcp -m tcp --dport 80 -j ACCEPT
-I DOCKER-USER -p tcp -m tcp --dport 443 -j ACCEPT
# ----------------------------------

最后重启 UFW

sudo ufw reload

🛠️ 常用命令

场景 命令 说明
查看状态 ufw-docker status 查看 Docker 相关的 UFW 规则
暴露端口 ufw-docker allow <容器名> <端口> 允许外网访问特定容器的端口
特定IP访问 ufw-docker allow <容器名> <端口> from <IP> 仅允许特定 IP 访问容器
删除规则 ufw-docker delete allow <容器名> <端口> 撤销之前的允许规则

⚠️ 注意:使用 ufw-docker 后,Docker run 的 -p 80:80 依然有效,但 ufw-docker install 会默认阻止外部访问 Docker 端口(除非显式 allow),从而修复了安全漏洞。建议配合 Oracle 安全组 双重防护。


2. 系统层防御 (OS Layer)

2.1 SSH 加固:端口要不要改?(To Change or Not To Change)

结论:改回 22 (标准化 > 隐匿性)。 * 理由 1 (无效防御):改端口属于“Security by Obscurity”。脚本扫全端口只需几秒钟就能找出来,对真正的攻击者毫无意义。 * 理由 2 (运维成本):改了端口后,所有工具 (Ansible/SCP/Git/Jenkins) 都要特殊配置,徒增心智负担。 * 正解:只要禁用了密码登录 (PasswordAuthentication no),端口 22 就是铜墙铁壁,没人能爆破 RSA/Ed25519 密钥。

2.2 SSH 核心配置 (禁止密码,仅密钥)

黑客无时无刻不在爆破你的 root 密码。

操作步骤: 1. 确保你已经配置好了 SSH Key 并能成功登录。 2. 编辑配置文件:sudo nano /etc/ssh/sshd_config 3. 修改/确认以下参数:

echo -e "PasswordAuthentication no\nPubkeyAuthentication yes\nPermitRootLogin prohibit-password" | sudo tee /etc/ssh/sshd_config.d/99-hardened.conf
4. 重启 SSHD:sudo systemctl restart sshd

2.2 自动安全更新

sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
# 选择 "Yes"

2.3 操作系统生命周期 (OS Lifecycle Strategy)

原则:宠物 (Pet) vs 牲畜 (Cattle) —— 把服务器当牲畜养。

  • 什么时候该重装?
    1. EOL (End of Life): 比如 Ubuntu 20.04 标准支持于 2025 年 4 月结束。现在是 2026 年,必须重装。
    2. 内核过旧: uname -r 显示内核版本落后主流 2 个大版本 (如还在用 4.x/5.4),且无法通过 apt upgrade 升级。
    3. 脏乱差: 系统里装了太多不知名的软件,与其清理,不如重建。
  • 最佳实践:
    • 不要做跨版本升级 (do-release-upgrade):很容易挂。
    • 直接开新机器:部署 Docker -> 导入数据 -> 切换 DNS -> 销毁旧机器。

选型原则: 1. LTS (长期支持版):必须。 2. Minimal (最小化安装)强烈推荐

发行版 推荐版本 代号 适用场景
Ubuntu 24.04 LTS (Minimal) Noble 首选通用系统。生态最好,文档最全。Minimal 版仅含内核+SSH+APT,其它全靠自己装。
Debian Debian 13.3 Trixie 极客/资源敏感型。内存占用极低,但配置稍繁琐 (无 sudo, ssh 默认禁 root)。

💡 Ubuntu 24.04 Minimal 少了什么? * 少了便利工具: vim, pico, Python3-full, net-tools, man-pages (文档)。 * 多了安全与性能: 启动更快,补丁更少,攻击面更小。 * 建议: 在安装时勾选 "Minimized" 选项,进系统后手动装回需要的工具 (sudo apt install curl wget nano htop git)。这就叫“按需分配”。

2.5 资源适配指引 (OS Sizing Strategy)

针对不同配置的服务器,建议采用 分层策略

如果您的服务器配置是... 推荐系统 理由
内存 > 2GB (如 Oracle 2核12G) Ubuntu 24.04 LTS 便利性优先。资源充裕,享受完整的生态支持和便利工具,无需折腾。
内存 ≤ 1GB (如 1核1G) Debian 12/13 生存优先。Ubuntu 待机 ~180MB,Debian 仅 ~80MB。这就差出了一个 Redis 的内存空间。

🤔 只有 1G 内存能装 Ubuntu 吗? 可以,但必须用 Minimal 版,且必须配置 ZRAM (内存压缩)Swap。否则做一次 apt upgrade 甚至 docker build 都可能 OOM (内存溢出) 导致死机。



3. Docker 安全规范 (Container Layer)

在部署任何容器前,必须遵守:

  1. Binding (绑定):管理面板 (Portainer, Traefik Dashboard) 必须 绑定到 127.0.0.1
    • ports: - "9000:9000" (危险!暴露给 0.0.0.0)
    • ports: - "127.0.0.1:9000:9000" (安全,仅本机访问)
  2. Network (网络):数据库/缓存 (Redis, MySQL) 严禁 映射端口到宿主机,除非绑定到内网 IP (10.0.x.x 或 Tailscale IP)。
    • ✅ 推荐使用 Docker Network 内部互联,不映射端口。
  3. Privilege (特权):除非是 VPN 或硬件驱动容器,严禁 使用 privileged: true

4. 持续安全运营 (Ongoing Security Operations)

安全不是一次性配置,而是持续的过程。

4.1 凭证轮换周期 (Credential Rotation)

建立定期更换密钥的习惯,防止凭证泄露导致的长期潜伏。

凭证类型 建议周期 操作方式 备注
SSH Key (User) 6-12 个月 生成新 Key -> 更新 authorized_keys -> 删除旧 Key 个人电脑端私钥同步更新
Tailscale Key 90 天 Console -> Regenerate Auth Key 使用 Ephemeral Key 部署临时节点
Portainer Admin 90 天 User Settings -> Password 开启 2FA (双因素认证)
Database User 180 天 ALTER USER ... IDENTIFIED BY ... 更新相关服务的环境变量

4.1.1 如何生成新密钥?(Client Side)

请在您的本地电脑 (Windows) 上执行,而不是在服务器上! 私钥 (id_ed25519) 必须永远留在您手里,公钥 (id_ed25519.pub) 才发给服务器。

  1. 本地生成: 打开 PowerShell,运行 ssh-keygen -t ed25519 -C "your_email"
    • System asks for passphrase: 强烈建议输入一个密码。这样即使您的电脑中了木马,私钥被偷走,黑客因为不知道密码也无法使用。
  2. 上传公钥: type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh user@host "cat >> .ssh/authorized_keys"
  3. 验证登录: ssh user@host (确认不再询问服务器密码,但可能会问 Key 的密码)

4.2 审计与监控 (Audit & Monitor)

每月检查一次服务器是否存在异常行为。

  • 登录审计:
    lastlog | grep -v "Never"  # 查看最近登录用户
    sudo cat /var/log/auth.log | grep "Accepted" # 成功登录记录
    
  • 进程审计:
    htop # 按 P (CPU) 或 M (Memory) 排序,寻找名为 "xmrig", "kdevtmpfsi" 等陌生进程
    
  • 端口审计:
    sudo ss -tulpn # 确认没有未知端口监听 0.0.0.0
    

4.3 应急响应 SOP (Emergency SOP)

当怀疑服务器被入侵时: 1. 断网: 立即去 Oracle 控制台 Deny All Ingress。 2. 取证: 不重启,保存 /var/log 和当前进程快照。 3. 重建: 以前文提到的 不可变基础设施 理念,直接销毁实例,用代码重新部署。不要尝试杀毒。


✅ 基线检查清单

  • [ ] Oracle Security List 入站规则仅剩 22/80/443/41641。
  • [ ] 运行 sudo ufw status 显示 Status: active 且规则符合预期。
  • [ ] 尝试 ssh -o PreferredAuthentications=password user@host 提示 "Permission denied" (密码登录已关闭)。
  • [ ] 确认没有 Docker 容器直接映射敏感端口到 0.0.0.0
  • [ ] [新增] 已在日历设置每季度一次的“密钥轮换日”。

🔍 5.1 自动化核查脚本 (Firewall Verification Script)

在所有节点部署完毕后,请直接复制粘贴以下脚本进行最终验收:

# === Firewall Security Audit ===
# (Tips: Copy all lines and paste into terminal)

# 1. 临时关闭历史记录扩展 (防止 ! 被转义报错)
set +H

# 2. Check UFW Status
if sudo ufw status | grep -q "Status: active"; then
    echo "✅ [PASS] UFW is ACTIVE"
else
    echo "❌ [FAIL] UFW is INACTIVE (Huge Risk!)"
fi

# 3. Check ufw-docker Integration
if sudo iptables -L DOCKER-USER -n | grep -q "ufw-docker-logging-deny"; then
    echo "✅ [PASS] ufw-docker chains detected"
else
    echo "❌ [FAIL] ufw-docker NOT detected (Docker ports are bypassing firewall!)"
fi

# 4. Check Critical Ports (Should be ALLOW)
echo "--- Port Checks ---"
sudo ufw status | grep -E "22/tcp|41641/udp"

# 5. Check Dangerous Ports (Should NOT be ALLOW)
if sudo ufw status | grep -E "9000|9001|2375|3306" | grep -q "ALLOW"; then
    echo "❌ [FAIL] DANGEROUS ports (9000/9001/3306/...) found in ALLOW list!"
else
    echo "✅ [PASS] No dangerous ports found in UFW"
fi

# 恢复历史记录扩展
set -H
echo "==============================="