每台服务器 不限流量、DDoS 防护和 IPMI 全部包含。无开通费,无长期合约。 每台服务器均不限流量 查看价格

指南 · 安全

15 分钟完成新 Linux 独立服务器的安全加固

适用于 Ubuntu 24.04 和 Debian 服务器的 15 分钟安全基线:系统更新、sudo 用户、SSH 密钥、防火墙、fail2ban、监控与备份。

  • 阅读 7 分钟
  • 更新于
  • FlexDedi 工程团队

本指南推荐配置

Core 16

  • AMD EPYC 4545P · 16 核
  • 128 GB DDR5 ECC
  • 2 × 1.92 TB NVMe Gen4
  • 10 Gbps,不限流量

$299/月

本页内容

任何拥有公网 IP 的服务器,都会被全天候不间断地探测 SSH 登录和开放的服务。下面这份清单,是全新的 Ubuntu 24.04 LTS 或 Debian 12/13 服务器在安装任何其他软件之前,都应先完成的安全基线。整个过程大约需要 15 分钟;即使某一步出了差错,你仍然可以通过带外管理控制台登录。

请以 root 身份运行这些命令;创建好你自己的用户之后,则改用 sudo 运行。将 deploy 替换为你的用户名,将 203.0.113.10 替换为你服务器的 IP 地址。

步骤用时
系统更新与自动安全更新3 分钟
创建带 SSH 密钥的 sudo 用户2 分钟
SSH 仅允许密钥登录,禁止 root 登录2 分钟
防火墙基线2 分钟
fail2ban1 分钟
时间同步与服务审查2 分钟
监控、IPMI 安全管理与备份3 分钟

全面更新系统

先把软件包更新到最新版本,然后重启一次,因为新镜像的首次升级通常会包含新内核:

bash
apt update && apt full-upgrade -y
reboot

Ubuntu Server 默认已启用 unattended-upgrades 来自动安装安全更新。在 Debian 上,需要手动安装并启用它:

bash
apt install -y unattended-upgrades
dpkg-reconfigure -plow unattended-upgrades   # answer Yes
unattended-upgrade --dry-run --debug 2>&1 | tail -n 5

重新配置这一步会写入 /etc/apt/apt.conf.d/20auto-upgrades。如果希望内核更新后在业务低峰时段自动重启服务器,请添加一个本地覆盖文件,而不要直接修改软件包自带的文件:

bash
cat > /etc/apt/apt.conf.d/52unattended-upgrades-local <<'EOF'
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "04:00";
EOF

创建带 SSH 密钥的 sudo 用户

如果你还没有密钥,先在本地工作站上生成一个:

bash
ssh-keygen -t ed25519 -C "you@workstation"

为私钥设置密码短语(passphrase)加以保护,并将其加载到 ssh-agent 中,这样每个会话只需输入一次。如果你有 FIDO2 安全密钥,可以用 ssh-keygen -t ed25519-sk 生成一个只有插入该硬件令牌时才能使用的密钥。

在服务器上创建用户并授予 sudo 权限。如果是最小化安装的 Debian,请先运行 apt install sudo。

bash
adduser deploy
usermod -aG sudo deploy

如果你是用密钥以 root 身份登录的,把密钥复制到新账户:

bash
install -d -m 700 -o deploy -g deploy /home/deploy/.ssh
install -m 600 -o deploy -g deploy /root/.ssh/authorized_keys /home/deploy/.ssh/authorized_keys

如果你是用密码登录的,则改为在工作站上运行 ssh-copy-id deploy@203.0.113.10;这两种情况在 SSH 访问文档中都有说明。然后打开第二个终端,确认 ssh deploy@203.0.113.10 可以正常登录,并且 sudo -v 能接受你的密码。在下一步验证通过之前,请保持 root 会话不要关闭。

仅允许密钥登录,禁止 root 登录

在 Ubuntu 24.04 和 Debian 上,/etc/ssh/sshd_config 在文件开头附近引入了 /etc/ssh/sshd_config.d/*.conf,而且每项设置都以最先读取到的值为准。因此,文件名排序靠前的文件会覆盖排在后面的文件,包括在启用了密码登录的镜像中存在的 50-cloud-init.conf:

bash
cat > /etc/ssh/sshd_config.d/00-hardening.conf <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
X11Forwarding no
AllowUsers deploy
EOF

sshd -t && systemctl restart ssh
sshd -T | grep -Ei 'permitrootlogin|passwordauthentication|allowusers'

在关闭任何会话之前,先从另一个终端测试一次全新登录。万一真的把自己锁在了外面,仍然可以通过带外管理工具中的 KVM 控制台或救援模式登录。

把 SSH 改到其他端口可以减少日志噪音,但算不上安全措施。如果你在 Ubuntu 24.04 上这样做(该系统通过 ssh.socket 启动 SSH),修改后需要运行 systemctl daemon-reload 并重启 ssh.socket。

防火墙基线

只选一种工具,不要同时运行两种。在 Ubuntu 和 Debian 上,UFW 最简单;如果你更喜欢显式编写规则,nftables 更合适。

UFW

bash
apt install -y ufw
ufw default deny incoming
ufw default allow outgoing
ufw limit 22/tcp
ufw allow 80,443/tcp
ufw enable
ufw status verbose

limit 会拒绝在 30 秒内发起 6 次或以上连接的源地址。UFW 会把相同的规则同样应用于 IPv6。

nftables

在 /etc/nftables.conf 中实现同样的策略:

text
flush ruleset

table inet filter {
    chain input {
        type filter hook input priority filter; policy drop;
        ct state established,related accept
        ct state invalid drop
        iif "lo" accept
        ip protocol icmp accept
        meta l4proto ipv6-icmp accept
        tcp dport { 22, 80, 443 } accept
    }
    chain forward {
        type filter hook forward priority filter; policy drop;
    }
}
bash
nft -c -f /etc/nftables.conf && systemctl enable --now nftables
nft list ruleset

nft -c 会在应用任何规则之前先检查语法。放行 ICMPv6 才能保证 IPv6 邻居发现正常工作;否则 IPv6 将无法使用。

fail2ban

fail2ban 会封禁反复认证失败的地址。读取 systemd 日志(journal)的方式在两个发行版上都适用,包括没有 /var/log/auth.log 的 Debian 系统:

bash
apt install -y fail2ban python3-systemd
cat > /etc/fail2ban/jail.local <<'EOF'
[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 ::1 198.51.100.7

[sshd]
enabled = true
backend = systemd
EOF
systemctl restart fail2ban
fail2ban-client status sshd

把你自己的办公室或 VPN 地址加入 ignoreip。在 SSH 仅允许密钥登录的情况下,fail2ban 的作用主要是减少日志噪音和无效握手;对于仍接受密码的服务(例如邮件或 Web 登录,它们各有自己的 jail),它的作用更为重要。

时间同步

正确的时间对 TLS、日志以及任何使用令牌或证书的系统都很重要:

bash
timedatectl
timedatectl set-timezone UTC

确认输出中包含 System clock synchronized: yes。两个发行版通常都使用 systemd-timesyncd 同步时间。如果 NTP service 显示为 n/a,请安装它,或者安装 chrony,它可以取而代之,并提供用于诊断的 chronyc tracking。统一使用 UTC,便于对照不同服务器上的日志。

尽量精简服务

每个监听端口都是攻击面。查看有哪些端口在监听、哪些服务在运行:

bash
ss -tulpn
systemctl list-units --type=service --state=running

用 systemctl disable --now NAME 停用不需要的服务,并卸载永远用不到的软件包。只与其他服务器通信的服务,例如数据库、指标导出器(exporter)和管理面板,应监听在 127.0.0.1 或你的内网上,绝不能监听公网地址。

从外部检查

纸面上的规则和实际生效的规则可能并不一致。从另一台机器扫描服务器,把开放的端口与你预期的列表进行对比:

bash
nmap -Pn -p- 203.0.113.10   # every TCP port; takes a few minutes

任何计划外的开放端口,要么是需要改为绑定内网地址的服务,要么是需要修正的防火墙规则。FlexDedi 始终开启的 DDoS 防护会在攻击流量到达服务器之前将其过滤,但它并不决定哪些端口开放;这由主机防火墙决定。

监控基础

  • 磁盘健康: 安装 smartmontools 和 nvme-cli。之后 smartd 会持续监控硬盘,nvme smart-log /dev/nvme0 可以显示磨损程度(percentage_used)和介质错误。如果使用软 RAID,请按照用 mdadm 配置软 RAID 中的说明设置告警。
  • 指标: apt install prometheus-node-exporter 会在 9100 端口提供 CPU、内存、磁盘和网络指标。只允许你的监控主机访问该端口,例如 ufw allow from 10.0.0.5 to any port 9100 proto tcp。
  • 外部检查: 从你的网络外部发起的可用性探测,能发现本地工具发现不了的问题,例如路由中断或证书过期。
  • 日志: journalctl -p warning -b 会列出本次启动以来的警告和错误。把日志发送到另一台机器上,这样入侵者就无法抹去痕迹。

IPMI 与 KVM 凭据

带外管理控制器可以对服务器断电重启、挂载 ISO 和打开控制台,因此请像对待 root 凭据一样对待它的凭据:

  • 如果你持有 IPMI 凭据,请把初始密码换成一个足够长、独一无二的密码,并保存在密码管理器中。访问方式请参阅 IPMI 与 KVM 文档。
  • 切勿把这个密码重复用于 SSH、控制面板或其他任何地方。
  • 严格限制掌握该密码的人员,有人离开时及时收回访问权限,用完控制台后关闭会话。
  • 用同样的方式保护控制面板的登录,因为通过它可以重装服务器。

备份

即使服务器已经加固,仍可能因为一次失败的部署或一块损坏的硬盘而丢失数据。请备份到另一台机器上,最好位于另一个机房,并测试恢复。restic 可以通过 SFTP 提供加密、去重的备份:

bash
apt install -y restic
openssl rand -base64 32 > /root/.restic-password && chmod 600 /root/.restic-password
export RESTIC_REPOSITORY="sftp:backup@10.0.0.20:/srv/restic/web01"
export RESTIC_PASSWORD_FILE=/root/.restic-password
restic init
restic backup /etc /home /var/www --exclude-caches
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
restic restore latest --target /tmp/restore-test --include /etc/ssh

在服务器之外的地方保存一份密码副本,因为没有它就无法读取备份仓库。每次备份前先把数据库导出为文件(pg_dump、mysqldump),而不是直接复制正在使用的数据文件;用 systemd timer 或 cron 运行备份任务,并在任务失败时发出告警。同一机房的存储服务器可以通过免费内网接收备份。

15 分钟之后

清单管一次,脚本管每一次。把这些步骤固化到 Ansible 或 cloud-init 等配置管理工具中,让每台新服务器都从同一基线起步,配置漂移也会一目了然。然后再看看这份基线没有覆盖哪些方面:

  • 运行 Lynis 等审计工具(先执行 apt install lynis,再运行 lynis audit system),并逐条处理它给出的建议。
  • 保持 AppArmor 处于启用状态。Ubuntu 和 Debian 默认已启用它,aa-status 可以列出已加载的配置文件。
  • 每当有人加入或离开团队,都要审查用户账户、sudo 权限和 authorized_keys 文件。

在 FlexDedi 上运行

FlexDedi 的每台服务器都具备这份基线所依赖的各项能力:SSH 无法连接时可用的 IPMI 和 HTML5 KVM 控制台,控制面板中的救援模式和一键重装,覆盖每个 IP 的始终开启的 DDoS 防护,以及可承载备份流量的免费内网。对于典型的 Web 或 API 服务器,Core 16($299/月)通常是起步之选;再搭配 Storage 264($699/月)或第二台 Core 16 作为备份目标即可。

更多指南

你的下一台服务器,几分钟后就能上线。

以 $299/月 部署一台 Core 16,或请我们的工程师为你量身规划服务器集群。

  • 无开通费
  • 不限流量
  • 随时取消