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

4 天前
 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

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

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

没必要搞那些 nginx rules 性能极差
julyclyde
4 天前
@zuotun 这种事还能猜啊?难道不是看看日志吗?
263
4 天前
你的域名( 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
4 天前
我记得 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
4 天前
Cloudflare Tunnel
yqs112358
4 天前
那直接用 Cloudflare Tunnel 不是更好(
ck65
4 天前
我的办法简单粗暴,源站简单弄个 key ,没有 key 就 4xx 掉,甚至静态的 key 都可以只要复杂一点。CF 入口弄个 worker 转发请求,带上 key 即可。
swiftg
4 天前
你要设置一个没有匹配到域名时候的默认 server ,通过 ip 直接访问,或者 hostname 匹配不到任何 server 的时候用

而且,你应该是直接在防火墙里配置源 ip ,而不是 nginx 里
00oo00
4 天前
tls 双向认证
JensenQian
4 天前
cf tunnel 隧道
NekoNeko666
3 天前
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