VPSKnow

服务器安全进阶与防 DDoS 完全指南

高级
45分钟

当您的服务器有了一定曝光度,简单修改 SSH 端口和配置 UFW 已不足以应对现代威胁。本指南从系统层、Web 服务层和 CDN 层三个维度出发,带您构建一套完整的多层纵深防御体系,让攻击者无从下手。

⚔️ 现代服务器的攻击图景

互联网上每时每刻都有自动化扫描机器人(如 Shodan、Censys 抓取引擎及各类黑客工具)在遍历公网 IP。一台新开的 VPS,通常在上线后 30 分钟内就会出现在扫描器的记录里。了解攻击类型,才能对症下药:

🔐

暴力破解

持续尝试 SSH/数据库密码。典型特征:auth.log 中大量 "Failed password" 记录。
防御: 密钥认证 + Fail2ban。

🕷️

漏洞扫描

探测 wp-admin.envphpmyadmin.git 等敏感路径,寻找未修补的已知漏洞。
防御: Fail2ban + WAF 规则。

💥

CC / 应用层 DDoS

海量并发请求耗尽 CPU 和内存,使服务无响应。典型:每秒数千次 POST 请求打某个 API 接口。
防御: 并发限速 + Cloudflare。

🌊

流量型 DDoS

Gbps 级别的垃圾流量直接堵死机房带宽,服务器内核层完全无能为力。
防御: 隐藏真实 IP 是唯一出路。

🎯 核心防御哲学

真正高效的安全策略不是"修补漏洞",而是让攻击者根本找不到目标。本指南的所有内容都围绕这个思路展开:隐藏真实 IP → 关闭不必要的端口 → 让剩余的攻击流量自动封锁或消耗在混淆层。

🥷 核心战略:彻底隐藏源站真实 IP

如果黑客掌握了您 VPS 的公网 IP,任何内核级防火墙规则都无济于事——流量型 DDoS 会直接把您的机房上行带宽塞满,导致整个机房受牵连(商家会对攻击目标 IP 执行"黑洞路由",即拔网线隔离)。防御 DDoS 的终极方法,就是让攻击者找不到真实 IP。

IP 泄露的五大常见途径

📧
MX 记录泄露

若邮件服务与网站部署在同一台服务器,发信时邮件头会携带真实 IP。解决方案:使用 SendGrid、腾讯企业邮箱等第三方邮件服务,完全隔离邮件服务器 IP。

🔍
历史 DNS 记录

Censys、SecurityTrails、ViewDNS 等工具会存档历史 DNS 解析记录。如果您的域名曾直接解析过真实 IP,这些记录永久保留。唯一出路:换一个新 IP 并从头开始。

🔒
SSL 证书透明度日志

申请 SSL 证书时,CA 会将证书信息写入公开的 CT 日志(crt.sh)。若证书包含您的域名,即使 Cloudflare 代理,攻击者仍能从证书日志中反查出域名与 IP 的关联。

🔗
子域名未代理

如 direct.yourdomain.com、api.yourdomain.com 等子域名若未开启 Cloudflare 橙云代理,直接暴露真实 IP,攻击者可通过子域名 ping 出主站 IP。

🧪
服务探针暴露

运行 Prometheus Exporter、Node Exporter 等监控服务时,若监听 0.0.0.0 且未配置认证,扫描器可通过 /metrics 接口指纹识别出您的服务器。应绑定到 127.0.0.1 或 Tailscale 内网 IP。

终极白名单模式:只允许 Cloudflare IP 访问 Web 端口

在系统防火墙层面,拒绝所有外网直连,仅放行 Cloudflare CDN 节点的 IP 段访问 80/443 端口。这样即使黑客扫到了您的真实 IP,发起的攻击也会在 UFW 层静默丢弃,完全不消耗 CPU 资源。

update-cf-whitelist.sh
#!/bin/bash
# 文件路径:/usr/local/bin/update-cf-whitelist.sh
# 功能:拉取 Cloudflare 最新 IP 段,只允许 CF 节点访问 80/443,封闭所有其他来源
# 建议每周执行一次(加入 Cron):0 4 * * 1 /usr/local/bin/update-cf-whitelist.sh

# 先关闭对 Web 端口的所有公网访问
ufw deny 80/tcp
ufw deny 443/tcp

# 拉取 Cloudflare 最新的 IPv4 地址段并逐一放行
# 截至 2026 年,CF IPv4 包含约 15 个 CIDR 块,如 103.21.244.0/22, 141.101.64.0/18 等
echo "正在更新 Cloudflare IPv4 白名单..."
for ip in $(curl -s https://www.cloudflare.com/ips-v4); do
    ufw allow from "$ip" to any port 80,443 proto tcp comment "CF-IPv4"
done

# 同样放行 Cloudflare IPv6 地址段
echo "正在更新 Cloudflare IPv6 白名单..."
for ip in $(curl -s https://www.cloudflare.com/ips-v6); do
    ufw allow from "$ip" to any port 80,443 proto tcp comment "CF-IPv6"
done

echo "Cloudflare 白名单更新完成!当前规则:"
ufw status | grep CF
💡 建议: 将此脚本加入 Cron,每周一凌晨 4 点自动更新一次(0 4 * * 1 /usr/local/bin/update-cf-whitelist.sh),因为 Cloudflare 偶尔会更新其 IP 段列表。

🚫 实战:Nginx 防 IP 直接访问与证书探测

全球扫描器(Shodan、Censys、各类黑客爬虫)在随机遍历 IP 时,会发起 HTTP/HTTPS 请求。若 Nginx 没有专门配置,默认会将第一个定义的 server 块当作响应返回——这会把您的真实域名和 SSL 证书信息暴露给扫描器。

正确做法:将一个 return 444 的 server 块设为 default_server,让所有"无主请求"(直接通过 IP 访问、Host 头不匹配任何已知域名的请求)都被直接切断 TCP 连接。

/etc/nginx/sites-available/default
# 文件路径:/etc/nginx/sites-available/default
# 此配置必须排在其他 server{} 块之前,作为 Nginx 最先匹配的"兜底"规则

server {
    # 同时监听 IPv4 与 IPv6,default_server 让 Nginx 把所有"无主"请求转到这里
    listen 80  default_server;
    listen [::]:80  default_server;
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;

    server_name _;  # 匹配任意 Host 头,包括直接 IP 访问

    # ⚠️  必须配置一个证书,否则 443 上的 TLS 握手会失败并泄露报错信息
    # 使用系统自带的蛇油(self-signed)证书即可,无需真实证书
    ssl_certificate     /etc/ssl/certs/ssl-cert-snakeoil.pem;
    ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;

    # 444 是 Nginx 专有非标准状态码
    # 效果:直接在 TCP 层关闭连接,不返回任何 HTTP 报头或报文
    # 对扫描器来说:它发出请求,什么都收不到,超时后才能判断结果——极大拖慢扫描效率
    return 444;
}
🛡️
防证书反查
444 不返回任何 TLS 握手信息,域名无从得知
极低资源消耗
TCP 层直接断开,不经过 HTTP 应用层,近乎零开销
🐌
拖慢扫描器
扫描器需等待超时才能判断结果,大幅降低扫描效率

🔑 实战:SSH 深度硬化清单

SSH 是服务器管理的核心入口,也是暴力破解攻击最集中的目标。以下是一份经过实践验证的 SSH 硬化清单,每一条都附有详细的原因说明:

/etc/ssh/sshd_config
# 编辑 SSH 配置文件:/etc/ssh/sshd_config
# 修改完成后执行 systemctl restart sshd 生效

# 【第一步】修改默认端口(将 22 改为任意非标准端口,如 39217)
# 注意:修改前务必先在防火墙放行新端口!
Port 39217

# 【第二步】禁用密码登录,强制使用密钥认证
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no

# 【第三步】禁用 root 用户直接登录(强制使用普通用户 sudo)
PermitRootLogin no

# 【第四步】限制只允许特定用户登录(将 youruser 改为您的实际用户名)
AllowUsers youruser

# 【第五步】关闭 X11 图形转发与 TCP 转发(减少攻击面)
X11Forwarding no
AllowTcpForwarding no

# 【第六步】设置无操作超时:180 秒无操作则自动踢出空闲连接
ClientAliveInterval 180
ClientAliveCountMax 2

# 【第七步】限制认证失败次数(超过 3 次密钥认证失败则断开)
MaxAuthTries 3
⚠️ 操作顺序至关重要: 修改 SSH 配置前,请先在防火墙中放行新端口(ufw allow 39217/tcp),并在新开一个 SSH 会话验证新端口能正常登录后,再关闭旧的 22 端口访问。切勿在当前唯一的 SSH 会话中直接执行 systemctl restart sshd,否则一旦配置有误将完全失去访问权限。

👊 进阶:端口敲门(Port Knocking)

端口敲门是一种让 SSH 端口在防火墙层面"完全不可见"的隐身技术。在平时,SSH 端口对外完全关闭,扫描器无论如何都无法发现它。只有当您按照预设的顺序向特定端口发送"敲门"数据包后,服务器才会临时为您的 IP 开放 SSH 端口。

工作原理示意

🖥️
您的电脑
发送敲门序列
→ 7000 → 8000 → 9000 →
🔒
knockd 守护程序
序列匹配 → 触发 UFW 放行
🔓
SSH 端口临时开放
仅对您的 IP,30 秒内有效

服务端配置(knockd)

/etc/knockd.conf
# 安装 knockd(端口敲门守护程序)
sudo apt install knockd -y

# 编辑配置文件:/etc/knockd.conf
[options]
    UseSyslog

# 定义一个"开门"序列:依次敲 7000(tcp) → 8000(udp) → 9000(tcp),10秒内完成
[openSSH]
    sequence    = 7000,8000,9000
    seq_timeout = 10
    tcpflags    = syn
    command     = /sbin/ufw allow from %IP% to any port 39217 proto tcp
    # %IP% 是 knockd 自动替换为发起敲门客户端的真实 IP

# 定义一个"关门"序列:依次敲 9000 → 8000 → 7000 关闭访问
[closeSSH]
    sequence    = 9000,8000,7000
    seq_timeout = 10
    tcpflags    = syn
    command     = /sbin/ufw delete allow from %IP% to any port 39217 proto tcp

# 启动 knockd 服务
sudo systemctl enable --now knockd

客户端操作(您的本地电脑)

本地终端 / PowerShell
# 在您的本地电脑上安装 knock 客户端
# macOS:   brew install knock
# Linux:   sudo apt install knockd
# Windows: 使用 nmap 模拟,见下文

# 执行敲门序列(依次向三个端口发一个 TCP SYN 包)
knock -v 1.2.3.4 7000 8000:udp 9000
# 1.2.3.4 替换为您的服务器公网 IP

# 敲完后 SSH 连接(使用修改后的端口)
ssh -p 39217 youruser@1.2.3.4

# Windows 用户用 nmap 模拟敲门
nmap -Pn --host-timeout 100 --max-retries 0 -p 7000 1.2.3.4
nmap -Pn --host-timeout 100 --max-retries 0 -p U:8000 1.2.3.4
nmap -Pn --host-timeout 100 --max-retries 0 -p 9000 1.2.3.4

🛡️ 实战:iptables / nftables 缓解 CC/SYN 攻击

对于没有接入 CDN 的 TCP 服务(如游戏服务器、代理节点),或需要在服务器层面加一道防护的场景,可使用内核级规则限制单个 IP 的并发连接数与连接速率。下面提供 iptables(传统)nftables(现代) 两套方案:

iptables 方案(Ubuntu 20.04 及更早)
# ── 方案一:使用传统 iptables(适合 Ubuntu 20.04 及更早版本)──

# 规则1:限制单个 IP 在 80/443 端口的并发 TCP 半连接数上限为 20
# connlimit 统计的是处于 SYN_RECV 状态的连接(即尚未完成三次握手的连接)
# --reject-with tcp-reset 相比 DROP,能让客户端更快感知到拒绝,节省服务器资源
iptables -A INPUT -p tcp --syn --dport 80  -m connlimit --connlimit-above 20 -j REJECT --reject-with tcp-reset
iptables -A INPUT -p tcp --syn --dport 443 -m connlimit --connlimit-above 20 -j REJECT --reject-with tcp-reset

# 规则2:限制新建连接速率(每秒超过 30 个新 SYN 包的 IP 直接封禁 60 秒)
# 这能有效阻断 SYN Flood:正常用户每秒新建连接不会超过个位数
iptables -A INPUT -p tcp --syn -m recent --name syn_flood --update --seconds 1 --hitcount 30 -j DROP
iptables -A INPUT -p tcp --syn -m recent --name syn_flood --set

# 规则3:ICMP 洪水防护(ping 频率限制,每秒最多 1 次,突发最多 5 次)
iptables -A INPUT -p icmp -m limit --limit 1/s --limit-burst 5 -j ACCEPT
iptables -A INPUT -p icmp -j DROP

# 持久化保存规则(重启后不丢失)
apt install iptables-persistent -y
netfilter-persistent save
nftables 方案(Ubuntu 22.04+ / Debian 11+ 推荐)
# ── 方案二:使用现代 nftables(Ubuntu 22.04+ / Debian 11+ 推荐)──
# nftables 是 iptables 的官方继任者,语法更清晰,性能更优

# 编辑或创建:/etc/nftables.conf
table inet filter {
    # 使用 meter(流量计)为每个 IP 单独计数,比 iptables connlimit 精度更高
    set tcp_flood {
        type ipv4_addr
        flags dynamic, timeout
        timeout 60s  # 计数器 60 秒后自动清零
    }

    chain input {
        type filter hook input priority 0; policy accept;

        # 限制单个 IPv4 来源每 10 秒内的 TCP SYN 数量
        # 超过 60 个即视为 SYN Flood,直接丢包
        ip protocol tcp tcp flags syn             add @tcp_flood { ip saddr limit rate over 60/minute }             drop

        # ICMP 速率限制(防止 ping 洪水)
        ip protocol icmp limit rate 10/second accept
        ip protocol icmp drop
    }
}

# 应用配置并设置开机自启
systemctl enable --now nftables
nft -f /etc/nftables.conf
对比项 iptables nftables
内核支持 长期支持(老机器兼容性最好) Linux 3.13+ 内核原生支持
语法 多个工具(iptables/ip6tables/ebtables)各自独立 统一语法,IPv4/IPv6/以太网一套规则
大规模 IP 集合 需借助 ipset,配置繁琐 内置 set,O(1) 哈希查找,性能更优
动态规则更新 需要 iptables-restore 重载整表 支持原子性局部更新,不中断流量
推荐场景 老系统、与现有工具链深度集成 新系统(Ubuntu 22.04+)、需要大规模 IP 管理
💡 重要提醒: 以上规则只能缓解中小规模的 CC/SYN 攻击(通常 <1Gbps)。真正的大规模 DDoS(如 100Gbps+)在抵达您服务器之前就已经在运营商的骨干网上触发了"黑洞路由"——您的 VPS 内核层防火墙根本来不及响应。这也再次印证了:隐藏真实 IP 才是根本

🤖 进阶:Fail2ban 恶意爬虫封锁

Fail2ban 通过实时分析日志文件,自动将触发规则的 IP 写入防火墙封禁名单。结合 Nginx 的 access.log,它可以精准封锁各类漏洞扫描爬虫。以下配置包含两个场景的 jail:

/etc/fail2ban/jail.local
# 编辑或创建:/etc/fail2ban/jail.local
# 此文件的设置会覆盖 /etc/fail2ban/jail.conf 中的默认值

[DEFAULT]
# 白名单:这些 IP 永远不会被封禁(填写您的家庭/办公室 IP)
ignoreip = 127.0.0.1/8 ::1 你的家庭IP

# ── Jail 1:封锁 WordPress 暴力破解 ──
[nginx-wordpress]
enabled  = true
port     = http,https
filter   = nginx-botsearch
logpath  = /var/log/nginx/access.log
# 60 秒内触发 3 次恶意请求(访问 wp-login.php, xmlrpc.php 等)
maxretry = 3
findtime = 60
# 封禁 7 天(604800 秒),让攻击者望而却步
bantime  = 604800

# ── Jail 2:封锁通用漏洞扫描 (.env, .git, phpmyadmin 探测) ──
[nginx-bad-requests]
enabled  = true
port     = http,https
filter   = nginx-botsearch
logpath  = /var/log/nginx/access.log
maxretry = 5
findtime = 120
bantime  = 86400  # 封禁 24 小时

# ── 重启生效 ──
# systemctl restart fail2ban
# 查看封禁状态:fail2ban-client status nginx-bad-requests

📋 nginx-botsearch 过滤器默认匹配的路径(部分)

wp-login.phpxmlrpc.phpphpmyadmin/.env/.git/config/.aws/credentials/config.json/backup.sql/shell.php/cmd.php/upload.php/.DS_Store

任何尝试访问以上路径并返回 404 的 IP,都会被计入 Fail2ban 的计数器。

☁️ 进阶:Fail2ban 联动 Cloudflare API 自动封 IP

Fail2ban 默认只封禁到达服务器网卡的 IP(iptables 层面),对于已经接入 Cloudflare CDN 的站点,攻击流量实际上来自 CF 的出口节点,服务器层面的封禁无效。

通过 Cloudflare Firewall API,我们可以让 Fail2ban 在封禁 IP 的同时,自动将恶意 IP 也添加到 Cloudflare 的防火墙规则——从 CDN 入口处就彻底拦截,连请求都不会转发到源站。

/etc/fail2ban/action.d/cloudflare-ban.sh
#!/bin/bash
# 文件路径:/etc/fail2ban/action.d/cloudflare-ban.sh
# 功能:当 Fail2ban 触发封禁时,同时通过 Cloudflare API 将恶意 IP 拉入 CF 防火墙黑名单
# 这样即使攻击者绕过 CDN 直连,CF 层面也会提前拦截

# ─ 配置区(填写您的 Cloudflare 信息)─────────────────────────────
CF_API_TOKEN="YOUR_CLOUDFLARE_API_TOKEN"  # CF 后台 -> 我的个人资料 -> API 令牌 -> 创建令牌
CF_ZONE_ID="YOUR_ZONE_ID"                 # CF 域名 -> 概述页面 -> 右侧 Zone ID
# ────────────────────────────────────────────────────────────────

ACTION=$1   # ban 或 unban
IP=$2       # 要操作的 IP 地址

if [ "$ACTION" = "ban" ]; then
    # 调用 CF API 创建一条 IP 封禁规则
    curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/firewall/access_rules/rules"          -H "Authorization: Bearer $CF_API_TOKEN"          -H "Content-Type: application/json"          --data "{
           \"mode\": \"block\",
           \"configuration\": { \"target\": \"ip\", \"value\": \"$IP\" },
           \"notes\": \"Auto-banned by Fail2ban on $(date -u +%Y-%m-%dT%H:%M:%SZ)\"
         }" > /dev/null
    echo "[CF-Ban] Blocked $IP on Cloudflare"

elif [ "$ACTION" = "unban" ]; then
    # 查询规则 ID 后删除
    RULE_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/firewall/access_rules/rules?mode=block&configuration_value=$IP"               -H "Authorization: Bearer $CF_API_TOKEN" | grep -o '"id":"[^"]*"' | head -1 | cut -d'"' -f4)
    if [ -n "$RULE_ID" ]; then
        curl -s -X DELETE "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/firewall/access_rules/rules/$RULE_ID"              -H "Authorization: Bearer $CF_API_TOKEN" > /dev/null
        echo "[CF-Ban] Unblocked $IP on Cloudflare"
    fi
fi
/etc/fail2ban/action.d/cloudflare.conf
# 创建 Fail2ban Action 配置:/etc/fail2ban/action.d/cloudflare.conf

[Definition]
actionban   = /etc/fail2ban/action.d/cloudflare-ban.sh ban   <ip>
actionunban = /etc/fail2ban/action.d/cloudflare-ban.sh unban <ip>

# 在 jail.local 中为任意 jail 启用此 action:
# [nginx-bad-requests]
# action = iptables-multiport[name=nginx, port="http,https"]
#          cloudflare

# 赋予脚本执行权限
# chmod +x /etc/fail2ban/action.d/cloudflare-ban.sh
# systemctl restart fail2ban

安全加固一键检查清单

完成本指南后,请对照以下清单逐项验证,确保没有遗漏任何防护层:

IP 隐藏

  • 所有 A/AAAA 记录均已开启 Cloudflare 橙云代理,无裸 IP 解析
  • MX 记录指向第三方邮件服务(非本机 IP)
  • 已通过 UFW 脚本只放行 Cloudflare IP 段访问 80/443
  • 已申请新 IP(若历史 IP 曾裸露在 Censys/Shodan 记录中)

SSH 安全

  • SSH 端口已修改为非标准端口(非 22)
  • 已禁用密码登录(PasswordAuthentication no)
  • 已禁用 root 直接登录(PermitRootLogin no)
  • 已配置端口敲门或 AllowUsers 白名单

Nginx 防护

  • 已配置 default_server 返回 444,防止 IP 直接访问
  • 使用蛇油证书作为 443 默认 server 的占位证书

自动防御

  • Fail2ban 已配置 SSH jail(maxretry ≤ 5)
  • Fail2ban 已配置 Nginx web 扫描 jail
  • (可选)Fail2ban 已联动 Cloudflare API 自动封 IP

DDoS 缓解

  • iptables/nftables 已配置 SYN 并发限速规则
  • ICMP 频率已限制(防 ping 洪水)
  • 规则已持久化(重启后不丢失)

常见问题解答

套了 Cloudflare 之后,我的源站 IP 就绝对安全了吗?

不能完全保证,关键在于您有没有泄露过真实 IP。Cloudflare 只是代理了您的 HTTP/HTTPS 流量,若您在套 CF 之前就用真实 IP 运行了一段时间,Shodan、Censys、ViewDNS 等数据库已经记录了该 IP 与您域名的关联。在这种情况下,攻击者可以绕过 CF 直接对真实 IP 发起攻击。最彻底的解决方案:套好 CF 后,花几美元让服务商更换一个全新的 IP 地址,彻底斩断历史记录。

return 444 和 return 403 有什么区别?我应该用哪个?

444:Nginx 专有非标准状态码,直接在 TCP 层关闭连接,不发送任何 HTTP 响应。扫描器无法判断您运行了什么服务,信息泄露最少,且不消耗 HTTP 处理资源。403:返回一个完整的 HTTP 响应(包含 Server 头和响应体),扫描器至少能确认"这里有一个 HTTP 服务",还可能暴露 Nginx 版本号。结论:对陌生的 IP 直访请求,始终用 444;403 用于对合法用户拒绝访问的场景(如限定了 allowlist 后的资源)。

端口敲门安全吗?万一序列被中间人截获怎么办?

端口敲门提供的是隐匿性而非加密性,属于"通过隐藏实现安全(Security through Obscurity)"的策略。理论上,若网络路径上存在流量嗅探,序列可能被截获并重放。实际风险较低,因为序列有 seq_timeout 时间窗口限制,且与来源 IP 绑定。最佳实践:将端口敲门作为额外的安全层使用,而非替代密钥认证。SSH 密钥认证才是安全底线,即使敲门序列被知道,没有私钥也无法登录。也可以考虑使用 fwknop(基于密钥的单包授权 SPA)作为更安全的替代方案——SPA 包经过加密且每次唯一,无法重放。

Fail2ban 封禁规则是否适用于 IPv6?如何配置?

Fail2ban 默认使用 iptables(IPv4),若您的服务器开启了 IPv6,需要额外配置。在 /etc/fail2ban/jail.local[DEFAULT] 段中添加:banaction = iptables-multiport 改为 banaction = nftables-multiport(若使用 nftables),nftables 天然同时支持 IPv4/IPv6。或者显式指定:banaction_allports = iptables-allports[chain="INPUT", protocol="all"] 并安装 ip6tables实际情况:大多数扫描器仍以 IPv4 为主,IPv6 攻击相对较少,但随着 IPv6 普及率提升,建议一并配置。

我的 VPS 遭受 DDoS 后被商家"黑洞"了,多久能解封?如何预防下次?

"黑洞路由"(Null Route)是商家为了保护整个机房将受攻击 IP 路由到空的手段。解封时间因商家而异:搬瓦工通常 1-2 小时自动解封;OVH 有时需要 24 小时;部分小商家需要人工操作。预防下次被黑洞:① 将所有对外服务切换到 Cloudflare CDN,隐藏真实 IP——这是根本;② 更换一个新 IP 地址,彻底断开与旧 IP 的关联;③ 选择有"高防"套餐的商家(如 SpartanHost、OVH),这些商家在上游已接入 DDoS 清洗服务(通常为 Voxility 或自建),可以吸收几十到几百 Gbps 的攻击而不触发黑洞。

安全加固后 iptables 规则越来越多,会影响服务器性能吗?

iptables 采用线性链式匹配,当规则数量在数千条以内时,性能影响微乎其微(个人 VPS 通常不超过 100 条)。关键优化技巧:① 将最高频匹配的规则(如 -m state --state ESTABLISHED,RELATED -j ACCEPT)放在链的最前面,大多数合法流量在第一条规则处就命中,无需继续匹配;② 若需要封禁大量 IP(如地区封锁、动态黑名单),使用 ipset——哈希表结构,无论放入多少 IP 都是 O(1) 查找;③ 新系统推荐迁移到 nftables,其内置的 set 数据结构在大规模场景下性能显著优于 iptables。

Cloudflare API 封 IP 有数量上限吗?Fail2ban 大量封禁会不会超限?

Cloudflare 免费计划的 IP Access Rules(通过 API 创建的防火墙规则)上限为 1,000 条;Pro 计划为 10,000 条;Business 及以上无上限。若 Fail2ban 封禁量巨大,建议在 cloudflare-ban.sh 中添加定期清理逻辑(解封超过 7 天的旧规则),防止接近上限。更优雅的替代方案:使用 Cloudflare 的 WAF 自定义规则 + IP Lists(Pro 计划起),可以创建包含数万个 IP 的动态黑名单列表,无数量限制,且 Fail2ban 只需调用一次 API 更新列表而非逐条写入,性能更优。

服务器安全加固完成后,如何验证防护效果是否真的生效?

多维度验证:① 外部端口扫描:从另一台机器用 nmap -p 1-65535 服务器IP 扫描,确认只有预期端口(SSH 自定义端口)是 open 状态,80/443 应是 filtered(UFW 丢弃);② IP 直接访问测试:用浏览器直接输入 http://服务器IP,应该连接超时而非返回任何内容;③ Cloudflare 绕过测试:关闭 CF 代理,用真实 IP 访问 80 端口,UFW 应静默丢弃;④ Fail2ban 状态检查fail2ban-client status 查看所有 jail 状态,fail2ban-client status sshd 查看已封禁 IP 列表;⑤ Shodan 自查:在 Shodan.io 搜索您的 IP,检查是否有不应暴露的服务信息。

完成本篇后,下一步应该按什么顺序继续学习?

按本站的 30 篇学习路径,第 10 篇(本篇,security-advanced)→ 第 11 篇(automation-scripts,自动化运维脚本)→ 第 12 篇(logs-and-troubleshooting,日志分析与排错) 是最佳进阶路径。学完安全加固后,您最迫切需要的是:① 用 Shell 脚本 + Cron 把本篇学到的封 IP、更新 CF 白名单等重复工作自动化;② 学会读懂 auth.logsyslog、Nginx access/error log,在出现问题时快速定位根因。这三篇构成了"安全加固 → 自动化维护 → 日志溯源"的完整闭环。

本文的防护措施是否适用于非 HTTP 服务(如游戏服务器、TURN 中继)?

部分适用,但需要调整。完全适用的: SSH 硬化、端口敲门、iptables/nftables 并发限速、IP 隐藏的总体思路。不适用或需替换的: Cloudflare 的 CDN 代理只支持 HTTP/HTTPS(以及部分 TCP 代理,仅限 Enterprise 计划);对于 UDP 游戏流量或 TURN 中继,无法用 CF 隐藏 IP。替代方案:① 选购带 Anti-DDoS 的专用游戏服务器(如 OVH Game 系列、SpartanHost);② 使用 TCPShield(专为 Minecraft 等游戏设计的代理层);③ 使用 Cloudflare Spectrum(收费,支持任意 TCP/UDP 协议的代理与 DDoS 防护)。