希望用户只能通过 Cloudflare CDN 访问网站,你们怎么配置 Nginx 的?

106 天前
52txr  52txr

我希望用户只能通过 Cloudflare CDN 访问网站,并且直接访问源站时会返回 403 Forbidden 。

在 Nginx 配置文件中,我的配置大概如下:

server {
    listen 80;
    server_name example.com;  # 替换为你的域名

    location / {
        # 允许 Cloudflare 的 IPv4 段
        allow 103.21.244.0/22;
        allow 103.22.200.0/22;
        allow 103.31.4.0/22;
        allow 104.16.0.0/12;
        allow 108.162.192.0/18;
        allow 131.0.72.0/22;
        allow 141.101.64.0/18;
        allow 162.158.0.0/15;
        allow 172.64.0.0/13;
        allow 173.245.48.0/20;
        allow 188.114.96.0/20;
        allow 190.93.240.0/20;
        allow 197.234.240.0/22;
        allow 198.41.128.0/17;

        # 允许 Cloudflare 的 IPv6 段(如果启用 IPv6 )
        allow 2400:cb00::/32;
        allow 2606:4700::/32;
        allow 2803:f800::/32;
        allow 2405:b500::/32;
        allow 2405:8100::/32;
        allow 2a06:98c0::/29;
        allow 2c0f:f248::/32;

        # 拒绝所有其他 IP
        deny all;

        # 正常的请求处理
        try_files $uri $uri/ =404;
    }
}

按理说我觉得使用直接配置后使用访问网站,应该正常显示。但是实际上是 403.

我是参考下面几个链接配置的:

[已完成] 怎样 只允许指定 IP 和域名访问网站: https://www.bt.cn/bbs/thread-72524-1-1.html

Nginx 设置只允许来自 Cloudflare CDN 的 IP 访问的方法 宝塔 NGINX 网站只允许 CF IP 访问方法: https://bnxb.com/nginx/27638.html

4596 次点击
所在节点   云计算  云计算
33 条回复
julyclyde
julyclyde
106 天前
那你看看 nginx 的日志,这个请求是从哪儿来的
yaocf
yaocf
106 天前
```shell
#!/bin/sh
set -o pipefail

export _ipv4Range=`curl --retry 10 --retry-delay 5 -s https://www.cloudflare-cn.com/ips-v4`
if [[ $? -ne 0 ]]; then
export _ipv4Range=`curl --retry 10 --retry-delay 5 -s https://www.cloudflare.com/ips-v4`
if [[ $? -ne 0 ]]; then
exit 1
fi
fi

export _ipv6Range=`curl --retry 10 --retry-delay 5 -s https://www.cloudflare-cn.com/ips-v6`
if [[ $? -ne 0 ]]; then
export _ipv6Range=`curl --retry 10 --retry-delay 5 -s https://www.cloudflare.com/ips-v6`
if [[ $? -ne 0 ]]; then
exit 1
fi
fi

#nginx real_ip
_tmpConf="/tmp/._$(date '+%Y-%m-%d-%H-%M')-$(cat /proc/sys/kernel/random/uuid).txt"
_target='/etc/nginx/conf.d/common/cloudflare/_real_ip_from-ip-set.conf'
{
echo "# Generated by ${0}"
echo "# At $(date)"
echo "# IPV4"
for i in ${_ipv4Range} ;do echo "set_real_ip_from ${i};" ;done
echo ""
echo "# IPV6"
for i in ${_ipv6Range} ;do echo "set_real_ip_from ${i};" ;done
echo ""
} |tee ${_tmpConf}
if [[ $? -eq 0 ]]; then
mv "${_tmpConf}" "${_target}"

nginx -t
if [[ $? -eq 0 ]]; then
echo "Nginx 配置正常,重载配置!"
nginx -s reload
else
/app/scripts/bin/gotify.sh --title "${_target} 文件更新成功,但 Nginx 配置有误" "请修复后手动重载 Nginx !\n""nginx -s reload"
fi
fi

#nginx allow-ip-set
#sleep 1
_tmpConf="/tmp/._$(date '+%Y-%m-%d-%H-%M')-$(cat /proc/sys/kernel/random/uuid).txt"
_target='/etc/nginx/conf.d/common/cloudflare/_allow-ip-set.conf'
{
echo "# Generated by ${0}"
echo "# At $(date)"
echo "# IPV4"
for i in ${_ipv4Range} ;do echo "allow ${i};" ;done
echo ""
echo "# IPV6"
for i in ${_ipv6Range} ;do echo "allow ${i};" ;done
echo ""
} |tee ${_tmpConf}
if [[ $? -eq 0 ]]; then
mv "${_tmpConf}" "${_target}"

nginx -t
if [[ $? -eq 0 ]]; then
echo "Nginx 配置正常,重载配置!"
nginx -s reload
else
/app/scripts/bin/gotify.sh --title "${_target} 文件更新成功,但 Nginx 配置有误" "请修复后手动重载 Nginx !\n""nginx -s reload"
fi
fi

```

我这边用来更新 allow ip 配置文件的脚本
herozzm
106 天前
不能这样设置吧,从 cf 过来的是客户端的 ip 噢
我是设置了一个很长域名,仅给 cf 回源用,不泄露
xfelix
106 天前
不理解为什么要这样设置 nginx 。直接设
防火墙 iptable 之类只允许 cf ip 段不就行了。
zuotun
106 天前
不是非要返回 403 的话,防火墙开白名单,用 CF 的 Origin 证书开 Full Strict 模式,这样配完后是绝对不能够直接访问源站的。
我的理解是 Nginx 拿到的是客户端的真实 IP ,否则日志里岂不全是 CF 的了,这要怎么溯源?
xfelix
106 天前
Ipsum
106 天前
Ipt 直接 drop 不行吗?
realpg
106 天前
网站只跑在 ipv6 上即可,不在 ipv4 上
XIU2
106 天前
直接在防火墙里限制 80 443 端口只允许 Cloudflare CDN 的 IP 访问即可,一直都是这样干的,而且效率更高。
realpg
106 天前
如果你的服务器是有一个路由过去的哪怕/64 块
只要让本站虚拟主机只监听其中一个独立的 ipv6 地址
不要用省略号,自己构造一个块内随机的 ipv6 单播地址

然后 cf 不解析 A 记录,只解析唯一 AAAA 记录只从 ipv6 回源
ipv6 网络下除非你其他方式泄露,根本没人找到的你这个源站
没有扫描 没有探测 也不会有人能直接连上 除了你自己

没必要搞那些 nginx rules 性能极差
julyclyde
106 天前
@zuotun 这种事还能猜啊?难道不是看看日志吗?
263
106 天前
你的域名( example.com )如果只解析到了 Cloudflare CDN 的 cname ,你只需要限制默认主机名。

如果有内网访问需求,server_name 需要加上自己的内网主机名或者 ip 。

下面的配置:

server {
listen 80 default_server;
server_name _;
return 444;
}

server {
listen 443 default_server;
server_name _;
ssl_certificate /etc/nginx/ssl/xxx.com.pem;
ssl_certificate_key /etc/nginx/ssl/xxx.com.key;
return 444;
}
cnt2ex
106 天前
我记得 set_real_ip_from 就没法和 allow 一起使用。如果使用了 set_real_ip_from ,ip 会被改成客户端的 IP ,从而导致 allow 看到的 IP 也是客户端的 IP ,然后就会 403 。

所以我都是在 nftable 配置 80 、443 端口只允许 cf 的 ip ,然后 nginx 里配置 set_real_ip_from
wheat0r
106 天前
Cloudflare Tunnel
yqs112358
106 天前
那直接用 Cloudflare Tunnel 不是更好(
ck65
106 天前
我的办法简单粗暴,源站简单弄个 key ,没有 key 就 4xx 掉,甚至静态的 key 都可以只要复杂一点。CF 入口弄个 worker 转发请求,带上 key 即可。
swiftg
106 天前
你要设置一个没有匹配到域名时候的默认 server ,通过 ip 直接访问,或者 hostname 匹配不到任何 server 的时候用

而且,你应该是直接在防火墙里配置源 ip ,而不是 nginx 里
00oo00
106 天前
tls 双向认证
JensenQian
105 天前
cf tunnel 隧道
NekoNeko666
105 天前
CloudFlare tunnel 然后拒绝任何 http ,https 端口访问,tunnel 直接和 CF 链接

或者,用 ufw ,允许 ssh ,只允许 CF ip 段的 http 和 https

sudo ufw allow ssh

# Allow HTTP (port 80) for Cloudflare IPv4 ranges
sudo ufw allow from 173.245.48.0/20 to any port 80
sudo ufw allow from 103.21.244.0/22 to any port 80
sudo ufw allow from 103.22.200.0/22 to any port 80
sudo ufw allow from 103.31.4.0/22 to any port 80
sudo ufw allow from 141.101.64.0/18 to any port 80
sudo ufw allow from 108.162.192.0/18 to any port 80
sudo ufw allow from 190.93.240.0/20 to any port 80
sudo ufw allow from 188.114.96.0/20 to any port 80
sudo ufw allow from 197.234.240.0/22 to any port 80
sudo ufw allow from 198.41.128.0/17 to any port 80
sudo ufw allow from 162.158.0.0/15 to any port 80
sudo ufw allow from 104.16.0.0/12 to any port 80
sudo ufw allow from 172.64.0.0/13 to any port 80
sudo ufw allow from 131.0.72.0/22 to any port 80

# Allow HTTPS (port 443) for Cloudflare IPv4 ranges
sudo ufw allow from 173.245.48.0/20 to any port 443
sudo ufw allow from 103.21.244.0/22 to any port 443
sudo ufw allow from 103.22.200.0/22 to any port 443
sudo ufw allow from 103.31.4.0/22 to any port 443
sudo ufw allow from 141.101.64.0/18 to any port 443
sudo ufw allow from 108.162.192.0/18 to any port 443
sudo ufw allow from 190.93.240.0/20 to any port 443
sudo ufw allow from 188.114.96.0/20 to any port 443
sudo ufw allow from 197.234.240.0/22 to any port 443
sudo ufw allow from 198.41.128.0/17 to any port 443
sudo ufw allow from 162.158.0.0/15 to any port 443
sudo ufw allow from 104.16.0.0/12 to any port 443
sudo ufw allow from 172.64.0.0/13 to any port 443
sudo ufw allow from 131.0.72.0/22 to any port 443

# Allow HTTP (port 80) for Cloudflare IPv6 ranges
sudo ufw allow from 2400:cb00::/32 to any port 80
sudo ufw allow from 2606:4700::/32 to any port 80
sudo ufw allow from 2803:f800::/32 to any port 80
sudo ufw allow from 2405:b500::/32 to any port 80
sudo ufw allow from 2405:8100::/32 to any port 80
sudo ufw allow from 2a06:98c0::/29 to any port 80
sudo ufw allow from 2c0f:f248::/32 to any port 80

# Allow HTTPS (port 443) for Cloudflare IPv6 ranges
sudo ufw allow from 2400:cb00::/32 to any port 443
sudo ufw allow from 2606:4700::/32 to any port 443
sudo ufw allow from 2803:f800::/32 to any port 443
sudo ufw allow from 2405:b500::/32 to any port 443
sudo ufw allow from 2405:8100::/32 to any port 443
sudo ufw allow from 2a06:98c0::/29 to any port 443
sudo ufw allow from 2c0f:f248::/32 to any port 443

sudo ufw deny 80
sudo ufw deny 443

sudo ufw enable

或者 iptables

或者,用你云服务商的防火墙设置,允许 cf 的 ip 段

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1095751

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX