10/15 款服务器配置有货即时交付免安装费

安全

新服务器安全加固:防火墙、fail2ban 与自动更新

关闭所有不对外提供服务的端口,加固 SSH,封禁暴力破解尝试,自动安装补丁,并避免 Docker 造成的防火墙漏洞。附 Ubuntu、Debian、AlmaLinux 和 Rocky Linux 的命令。

阅读约 6 分钟更新于 UbuntuDebianAlmaLinuxRocky Linux

适用于
UbuntuDebianAlmaLinuxRocky Linux
阅读时间
6 分钟
更新日期
主题
安全

遇到问题?工程师 7×24 小时为您解答

本页目录

新服务器一上线就能被整个互联网访问,自动化扫描程序很快就会发现新地址。加固遵循一条原则:只暴露您实际提供的服务,并及时打补丁。请按顺序完成以下步骤,并保持一个 SSH 会话处于打开状态,直到每项更改都测试通过。

避免把自己锁在外面。启用防火墙之前先放行 SSH,在第二个终端中测试每项更改,并请记住:即使某条规则出错,控制面板中的 IPMI 控制台仍然可用。

检查正在监听的服务

Shell
ss -tulpn

每一行代表一个开放的端口。在 Local Address 列中,0.0.0.0、[::] 或 * 表示所有网络接口(包括公网接口);127.0.0.1 和 [::1] 表示仅限本地。停止并禁用您不需要的服务,例如:

Shell
systemctl disable --now rpcbind.service rpcbind.socket

仅供您自己的应用程序使用的服务应监听 localhost:MySQL 和 MariaDB 使用 bind-address = 127.0.0.1,PostgreSQL 使用 listen_addresses = 'localhost',Redis 使用 bind 127.0.0.1 -::1 并配合 protected-mode yes。切勿将数据库、Redis、Memcached 或 Elasticsearch 暴露在互联网上。如果其他服务器需要访问它们,请使用服务器之间的免费私有 VLAN(需申请)或 VPN,并配合防火墙白名单。

配置防火墙

默认拒绝所有入站流量,只开放您提供服务的端口。示例中开放了 SSH、HTTP 和 HTTPS。

Ubuntu 和 Debian:ufw

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

只要在 /etc/default/ufw 中设置了 IPV6=yes(这是默认设置),ufw 就会同时写入对应的 IPv6 规则。如需只允许来自您自己地址的 SSH 连接,请先添加这条具体规则,再删除通用规则:

Shell
ufw allow from 198.51.100.7 to any port 22 proto tcp
ufw delete allow 22/tcp

如果您的地址经常变化,请改用 ufw limit 22/tcp:它会拒绝在 30 秒内发起 6 次及以上连接的地址。

AlmaLinux 和 Rocky Linux:firewalld

Shell
dnf install -y firewalld
systemctl enable --now firewalld
firewall-cmd --permanent --add-service=http --add-service=https
firewall-cmd --permanent --remove-service=cockpit
firewall-cmd --reload
firewall-cmd --list-all

默认的 public 区域通常允许 ssh、cockpit 和 dhcpv6-client;如果您要使用其 Web 控制台,请跳过 cockpit 这一行。未指定协议族(family)的规则同时适用于 IPv4 和 IPv6。如需只允许来自您地址的 SSH 连接(如果您通过 IPv6 连接,请用 family="ipv6" 再添加一条规则):

Shell
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="198.51.100.7/32" service name="ssh" accept'
firewall-cmd --permanent --remove-service=ssh
firewall-cmd --reload

在当前版本中,ufw 和 firewalld 底层都由 nftables 实现。您也可以改为手动编写 /etc/nftables.conf,但请只选择一种方式:将手写的规则集与 ufw 或 firewalld 混用,会使结果难以预测。

加固 SSH

仅使用密钥登录。使用 SSH 密钥登录一文会逐步引导您完成设置,并创建用于关闭密码登录的 /etc/ssh/sshd_config.d/00-keys-only.conf。然后在第二个 drop-in 配置文件 /etc/ssh/sshd_config.d/10-hardening.conf 中添加几项限制。当前版本会在读取主配置之前读取这些文件,并以最先读取到的值为准:

配置文件
MaxAuthTries 3
LoginGraceTime 30
X11Forwarding no

检查语法,然后重新加载(在 AlmaLinux 和 Rocky Linux 上,服务名为 sshd):

Shell
sshd -t
systemctl reload ssh

当您能够以 sudo 用户(例如 deploy)登录后,请在 00-keys-only.conf 中将 PermitRootLogin 改为 no。将 SSH 改到其他端口可以减少日志噪音,但这并不是一项安全控制措施。

使用 fail2ban 拦截暴力破解

fail2ban 从 systemd 日志(journal)中读取登录失败记录,并在防火墙中暂时封禁来源地址。在 AlmaLinux 和 Rocky Linux 上,请先启用 EPEL(dnf install -y epel-release),再使用 dnf 安装同样的两个软件包:

Shell
apt install -y fail2ban python3-systemd

创建 /etc/fail2ban/jail.local:

INI
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 ::1 198.51.100.7

[sshd]
enabled = true
backend = systemd
Shell
systemctl enable --now fail2ban
fail2ban-client status sshd

在公网服务器上,Total failed 通常几分钟内就会开始计数。如果一直为 0,说明过滤器与您的日志不匹配:在 OpenSSH 9.8 及更高版本中,登录失败由 sshd-session 记录,旧版 fail2ban 的过滤器无法识别,因此请更新 fail2ban。解除封禁:fail2ban-client set sshd unbanip 198.51.100.7。

自动安装安全更新

Ubuntu 通常默认已启用 unattended-upgrades。在 Debian 上,请安装并启用它:

Shell
apt install -y unattended-upgrades
dpkg-reconfigure -plow unattended-upgrades

/etc/apt/apt.conf.d/20auto-upgrades 中的两个值都必须为 "1";可使用 unattended-upgrade --dry-run --debug 预览一次运行。内核更新需要重启:如需在业务低峰时段自动重启,请在 /etc/apt/apt.conf.d/50unattended-upgrades 中设置 Unattended-Upgrade::Automatic-Reboot "true"; 和 Unattended-Upgrade::Automatic-Reboot-Time "04:00";。

在 AlmaLinux 和 Rocky Linux 上,安装 dnf-automatic:

Shell
dnf install -y dnf-automatic dnf-plugins-core

在 /etc/dnf/automatic.conf 的 [commands] 部分中设置 upgrade_type = security 和 apply_updates = yes,然后启用定时器。dnf needs-restarting -r 会告诉您何时需要重启:

Shell
systemctl enable --now dnf-automatic.timer
dnf needs-restarting -r

Docker 会绕过 ufw 和 firewalld

Docker 会写入自己的 iptables 规则,发往已发布容器端口的流量在防火墙的入站规则检查之前就已被转发。使用 -p 6379:6379 启动的容器可以从整个互联网访问,无论 ufw 如何设置。有两种解决方法:

  1. 仅在 localhost 上发布端口,并在所有对外服务前放置反向代理。在 Compose 中写作 "127.0.0.1:6379:6379"。

    Shell
    docker run -d -p 127.0.0.1:6379:6379 redis
  2. 在 DOCKER-USER 链中过滤,Docker 会先于自身规则评估该链。将 eth0 替换为您的公网接口(ip route show default):

    Shell
    iptables -I DOCKER-USER -i eth0 -p tcp -m conntrack --ctorigdstport 6379 --ctdir ORIGINAL -j DROP

    这些规则在重启后不会保留:请通过 systemd 单元或您的配置管理工具应用它们;如果容器使用 IPv6,请使用 ip6tables 添加相同的规则。

切勿在 TCP 端口 2375 上暴露 Docker API:任何能访问它的人都能获得宿主机的 root 权限。请改为通过 SSH 管理远程引擎,例如 DOCKER_HOST=ssh://deploy@203.0.113.10。

时间同步、安全审计与控制台访问

  • 保持时钟准确。TLS、双重验证(2FA)验证码和日志关联分析都依赖准确的时间。timedatectl 必须显示 System clock synchronized: yes;如果没有运行任何时间服务,请安装 chrony。除非您打算对外提供时间服务,否则不要使用 chrony 的 allow 指令:对互联网开放的 NTP 服务器可能被滥用于放大攻击。
  • 使用 Lynis 进行审计(可选,Debian、Ubuntu 和 EPEL 中均有软件包)。lynis audit system 会输出具体建议:请将其视为检查清单,而不是要追求最高的分数。
  • 不要公开带外管理访问。只通过控制面板使用 IPMI 控制台,并为控制面板账户设置独一无二的密码。

后续步骤

需要帮助?

拥有在用服务器的客户可在账户中提交工单,工程师 7×24 小时为您解答。

技术支持流程