使用 nftables 配置 Web 服务器仅允许 Cloudflare IP 访问
status
Published
type
Post
slug
nftables-restrict-web-server-cloudflare-ips
date
Dec 22, 2024
tags
Config
Linux
Cloudflare
Network
summary
文章记录了如何使用 nftables(Linux 中现代化的防火墙框架)配置防火墙规则实现仅允许来源自 Cloudflare IP 源地址的访问,确保所有流量都通过 Cloudflare 处理。
将网站接入 Cloudflare CDN 是提高其性能和安全性的常用方法。然而,如果您的源服务器仍然可以直接通过其 IP 地址访问,那么 Cloudflare 带来的许多安全优势(如 DDoS 防护、WAF)可能会被绕过。
为了确保仅接收来自 Cloudflare 代理的流量,一是可以通过建立 Cloudflare Tunnel 之类的隧道来排除其他流量,再一个就是配置 Linux 自身的网络防火墙仅允许 Cloudflare 的 源 IP 访问服务器。
下面是修改
nftables
配置文件的记录获取 Cloudflare IP 地址范围
我们可以从 Cloudflare 官方文档中找到这些列表:
为了确保防火墙规则始终有效,必须使用这些官方且最新的 IP 范围。Cloudflare 会定期更新其用于连接源服务器的 IP 地址列表,因此需要定期检查并更新您的防火墙规则,或者使用自动化脚本来保持同步,此处不做展开。
第二步:修改 nftables 配置
nftables 的配置文件通常位于
/etc/nftables.conf
sudo vim /etc/nftables.conf
在配置文件中,我们将定义一个
inet
(IPv4/IPv6) 类型的 filter
表,并在 input
链(处理进入服务器的数据包)中添加规则。以下是一个配置示例,可以将其内容整合到您现有的
nftables.conf
文件中,或者如果文件为空,则直接使用它。
记得将示例中的 IP 地址列表替换为您在第一步中获取的 最新 Cloudflare IP 范围。#!/usr/sbin/nft -f # 完全清除现有规则集,确保配置从干净状态开始 flush ruleset # 定义 Cloudflare IPv4 地址集合 define cloudflare_ipv4 = { 173.245.48.0/20, 103.21.244.0/22, 103.22.200.0/22, 103.31.4.0/22, 141.101.64.0/18, 108.162.192.0/18, 190.93.240.0/20, 188.114.96.0/20, 197.234.240.0/22, 198.41.128.0/17, 162.158.0.0/15, 104.16.0.0/13, 104.24.0.0/14, 172.64.0.0/13, 131.0.72.0/22 } # 定义 Cloudflare IPv6 地址集合 define cloudflare_ipv6 = { 2400:cb00::/32, 2606:4700::/32, 2803:f800::/32, 2405:b500::/32, 2405:8100::/32, 2a06:98c0::/29, 2c0f:f248::/32 } # 定义 HTTP/HTTPS 端口 define http_ports = { 80, 443 } table inet filter { # 输入链处理进入系统的数据包 chain input { type filter hook input priority 0; # 使用明确的默认策略:拒绝所有流量,仅允许特定规则 policy drop; # 允许本地回环接口流量 iif lo accept comment "允许本地回环流量" # 允许已建立和相关的连接 ct state established,related accept comment "允许已建立和相关连接" # 允许来自 Cloudflare 的 HTTP/HTTPS 流量 ip saddr $cloudflare_ipv4 tcp dport $http_ports accept comment "允许 Cloudflare IPv4 HTTP/HTTPS 流量" ip6 saddr $cloudflare_ipv6 tcp dport $http_ports accept comment "允许 Cloudflare IPv6 HTTP/HTTPS 流量" # 允许 ICMP 流量用于网络诊断 ip protocol icmp accept comment "允许 ICMPv4 流量" ip6 nexthdr ipv6-icmp accept comment "允许 ICMPv6 流量" # SSH 访问控制(默认注释掉,建议仅在需要时启用并限制源 IP) # tcp dport 22 ip saddr { 192.168.1.0/24, 10.0.0.0/8 } accept comment "仅允许特定 IP 范围的 SSH 访问" # 记录被拒绝的 HTTP/HTTPS 请求(可选,用于调试) # tcp dport $http_ports counter log prefix "BLOCKED HTTP/HTTPS: " drop comment "记录并阻止非 Cloudflare HTTP/HTTPS 访问" # 记录所有其他被拒绝的请求(可选,用于调试) # counter log prefix "BLOCKED OTHER: " comment "记录所有其他被拒绝的请求" } # 转发链处理通过系统转发的数据包 chain forward { type filter hook forward priority 0; policy drop; # 如需添加转发规则,请在此处添加 } # 输出链处理从系统发出的数据包 chain output { type filter hook output priority 0; policy accept; # 默认允许所有出站流量 # 如需限制出站流量,请在此处添加规则 } }
配置说明(如下解释均由 AI 生成):
table inet filter { ... }
: 定义一个用于 IPv4 和 IPv6 的过滤表。
chain input { ... }
: 定义处理入站流量的链。
type filter hook input priority 0;
: 指定这是一个过滤链,挂载到input
钩子上,优先级为 0。
policy accept;
: 默认策略是接受所有流量。我们稍后会添加特定的drop
规则。或者,您可以将此设置为policy drop;
并仅显式accept
您需要的流量(更安全的默认设置)。
iif "lo" accept
: 允许本地回环接口(localhost)的通信。非常重要,否则本地服务可能无法通信。
ct state established,related accept
: 允许属于已建立连接或与现有连接相关的包通过。这通常是必要的,以允许双向通信正常工作。
ip saddr { ... } tcp dport { 80, 443 } accept
: 允许源 IP 地址 (saddr
) 在指定列表中的 IPv4 流量访问 TCP 目标端口 (dport
) 80 或 443。
ip6 saddr { ... } tcp dport { 80, 443 } accept
: 同上,但针对 IPv6 地址。
ip protocol tcp tcp dport { 80, 443 } drop
: 拒绝所有 其他 访问 TCP 端口 80 或 443 的 IPv4 流量。
ip6 nexthdr tcp tcp dport { 80, 443 } drop
: 同上,但针对 IPv6 流量。
comment "..."
: 为规则添加注释,便于理解。
应用 nftables 配置
保存对
/etc/nftables.conf
文件的更改后,需要加载这些新规则。使用以下命令:sudo nft -f /etc/nftables.conf
这条命令会检查配置文件的语法,如果无误,则原子性地应用新规则集。
或者我们可以使用 systemd 服务来管理
nftables
,从而使得配置在重启后也能持久化(通常需要先启用服务 sudo systemctl enable nftables
),可以使用:sudo systemctl restart nftables
注意: 在应用防火墙规则之前,请确保有其他访问服务器的方式(例如,控制台访问、允许 SSH 的规则),以防配置错误导致网络连接中断。
验证 nftables 配置
应用配置后,验证规则是否已按预期加载至关重要。使用以下命令查看当前的完整规则集:
sudo nft list ruleset
检查输出,确保在
inet filter
表的 input
链中能看到刚刚添加的允许 Cloudflare IP 和拒绝其他 HTTP/HTTPS 访问的规则。此时我们还可以尝试从 非 Cloudflare 的 IP 地址访问您的网站(端口 80 或 443)。这些连接应该被阻止(例如,超时或连接被拒绝)。同时,通过 Cloudflare 访问网站应能正常工作。