接入Cloudflare后Nginx和Django获取用户真实IP的办法

可以用Nginx的real_ip的相关命令来实现这个需求。

01-real_ip命令集详解

real_ip命令的使用分为两个步骤:

01-1-设置从哪些代理IP获取真实IP

第1个步骤:通过set_real_ip_from命令设置从哪些代理IP请求获取真实的IP,比如下面的命令:

lua 复制代码
        set_real_ip_from 103.21.244.0/22;
        set_real_ip_from 103.22.200.0/22;
        set_real_ip_from 103.31.4.0/22;
        set_real_ip_from 104.16.0.0/12;
        set_real_ip_from 108.162.192.0/18;
        set_real_ip_from 131.0.72.0/22;
        set_real_ip_from 141.101.64.0/18;
        set_real_ip_from 162.158.0.0/15;
        set_real_ip_from 172.64.0.0/13;
        set_real_ip_from 173.245.48.0/20;
        set_real_ip_from 188.114.96.0/20;
        set_real_ip_from 190.93.240.0/20;
        set_real_ip_from 197.234.240.0/22;
        set_real_ip_from 198.41.128.0/17;

上面这个些IP就是chatgpt给出的所有的Cloudflare的IP。

我通过另一个网站,还获取到了一份含cloudflare的IPV6地址的set_real_ip_from命令集,如下:
https://cloud.tencent.com/developer/article/2203939?areaSource=102001.15&traceId=BtaYzKMt3Qz7kwpj2CLdo

lua 复制代码
#cfip4
set_real_ip_from 103.21.244.0/22; #cfipv4
set_real_ip_from 103.22.200.0/22; #cfipv4
set_real_ip_from 103.31.4.0/22; #cfipv4
set_real_ip_from 104.16.0.0/12; #cfipv4
set_real_ip_from 108.162.192.0/18; #cfipv4
set_real_ip_from 131.0.72.0/22; #cfipv4
set_real_ip_from 141.101.64.0/18; #cfipv4
set_real_ip_from 162.158.0.0/15; #cfipv4
set_real_ip_from 172.64.0.0/13; #cfipv4
set_real_ip_from 173.245.48.0/20; #cfipv4
set_real_ip_from 188.114.96.0/20; #cfipv4
set_real_ip_from 190.93.240.0/20; #cfipv4
set_real_ip_from 197.234.240.0/22; #cfipv4
set_real_ip_from 198.41.128.0/17; #cfipv4
#cfip6
set_real_ip_from 2400:cb00::/32; #cfipv6
set_real_ip_from 2405:8100::/32; #cfipv6
set_real_ip_from 2405:b500::/32; #cfipv6
set_real_ip_from 2606:4700::/32; #cfipv6
set_real_ip_from 2803:f800::/32; #cfipv6
set_real_ip_from 2c0f:f248::/32; #cfipv6
set_real_ip_from 2a06:98c0::/29; #cfipv6

如果想设置从所有的代理IP获取客户端的真实IP,则可以用下面的命令:

lua 复制代码
set_real_ip_from 0.0.0.0/0;

01-2-设置从哪个头信息获取真实IP

第2个步骤:使用命令real_ip_header告诉Nignx从哪个头信息中获取真实IP。

在这个步骤里面,常见的下面两条命令:

lua 复制代码
        real_ip_header CF-Connecting-IP;
lua 复制代码
        real_ip_header X-Forwarded-For;

两条命令任选一条,但是推荐用第1个,即CF-Connecting-IP,chatgpt对此的解释如下:

在一般情况下,CF-Connecting-IP 更为推荐,因为它是专门为 Cloudflare 设计的头信息,能够提供更可靠的真实 IP地址。

关于CF-Connecting-IP,cloudflare的官方文档有说明:
https://developers.cloudflare.com/fundamentals/reference/http-request-headers/

相关文章也说明了这一点:

链接:https://www.kchuhai.com/report/view-19321.html

其实按照Cloudflare的设计,最好的是从True-Client-IP Header中获取客户端的真实IP,但是如果要使用这个头,是需要付费的。

官方文档:https://developers.cloudflare.com/network/true-client-ip-header/

02-理解以上信息后,得出我觉得不错的Nginx配置代码

lua 复制代码
    location / {
        # 设置 Cloudflare 的 IP 地址范围,因为只有下面这些IP才来自cloudflare
		#cfip4
		set_real_ip_from 103.21.244.0/22; #cfipv4
		set_real_ip_from 103.22.200.0/22; #cfipv4
		set_real_ip_from 103.31.4.0/22; #cfipv4
		set_real_ip_from 104.16.0.0/12; #cfipv4
		set_real_ip_from 108.162.192.0/18; #cfipv4
		set_real_ip_from 131.0.72.0/22; #cfipv4
		set_real_ip_from 141.101.64.0/18; #cfipv4
		set_real_ip_from 162.158.0.0/15; #cfipv4
		set_real_ip_from 172.64.0.0/13; #cfipv4
		set_real_ip_from 173.245.48.0/20; #cfipv4
		set_real_ip_from 188.114.96.0/20; #cfipv4
		set_real_ip_from 190.93.240.0/20; #cfipv4
		set_real_ip_from 197.234.240.0/22; #cfipv4
		set_real_ip_from 198.41.128.0/17; #cfipv4
		#cfip6
		set_real_ip_from 2400:cb00::/32; #cfipv6
		set_real_ip_from 2405:8100::/32; #cfipv6
		set_real_ip_from 2405:b500::/32; #cfipv6
		set_real_ip_from 2606:4700::/32; #cfipv6
		set_real_ip_from 2803:f800::/32; #cfipv6
		set_real_ip_from 2c0f:f248::/32; #cfipv6
		set_real_ip_from 2a06:98c0::/29; #cfipv6
		
		# 从CF-Connecting-IP头信息中获取真实 IP 地址
        real_ip_header CF-Connecting-IP;

        # 其他 Nginx 配置...
        # 这里可以配置代理到您的后端服务器
        proxy_pass http://127.0.0.1:41854;
    }

03-Django中如何获取真实IP?

在 Nginx 中使用 real_ip_header CF-Connecting-IP; 指令,表示您希望从 Cloudflare 的 CF-Connecting-IP 头中获取真实 IP 地址。在 Django 中,您可以通过 request 对象的 META 属性来获取这个真实 IP 地址。

下面是一个示例视图函数,演示如何在 Django 中获取真实 IP 地址:

python 复制代码
# views.py

from django.http import HttpResponse

def get_real_ip(request):
    # 获取 CF-Connecting-IP 头信息
    cf_connecting_ip = request.META.get('HTTP_CF_CONNECTING_IP')

    # 提取真实 IP 地址
    if cf_connecting_ip:
        real_ip = cf_connecting_ip
    else:
        # 如果 CF-Connecting-IP 头不存在,直接使用 REMOTE_ADDR
        real_ip = request.META.get('REMOTE_ADDR')

    return HttpResponse(f'Real IP: {real_ip}')

在这个例子中,request.META 是包含请求元数据的字典,HTTP_CF_CONNECTING_IP 键对应于 Cloudflare 的 CF-Connecting-IP 头。如果这个头存在,我们就直接使用它的值作为真实 IP 地址。如果头不存在,我们就回退到使用 REMOTE_ADDR

确保在您的 Nginx 配置中配置了正确的 real_ip_header 指令,以确保它与 Cloudflare 的头信息一致。这样,Django 中的视图就能够正确地获取来自 Cloudflare 的真实 IP 地址了。

04-提问:在使用了命令real_ip_header后,在反向代理时还需要用命令proxy_set_header不?

通过命令real_ip_header设置的header值在通过命令:proxy_pass http://127.0.0.1:41854;进行反向代理也会传递给Django是吧,而无需再用proxy_set_header进行设置是吧?

答:是的。当您使用 real_ip_header 指令设置了真实 IP 地址的头信息后,Nginx 会将这个头信息传递给后端服务器,而无需额外的 proxy_set_header 设置。在您的配置中,您已经使用了以下指令:

nginx 复制代码
real_ip_header CF-Connecting-IP;

这告诉 Nginx 使用 Cloudflare 的 CF-Connecting-IP 头作为真实 IP 地址。接着,通过 proxy_pass http://127.0.0.1:41854; 指令,Nginx 会将请求转发到 Django 的后端服务器,同时将 CF-Connecting-IP 头传递给 Django。

因此,您无需额外的 proxy_set_header 来设置真实 IP 地址头信息,因为 real_ip_header 已经处理了这个任务。在 Django 中,您可以通过 request.META.get('HTTP_CF_CONNECTING_IP') 来访问这个头信息,以获取真实的客户端 IP 地址。

相关推荐
白开水不加冰27 分钟前
HTTP 和 HTTPS 的区别
网络协议·http·https
2401_874275171 小时前
websocket
网络·笔记·websocket·网络协议·学习
mzhan0171 小时前
wireshark: Display Filter Reference
网络·测试工具·wireshark
炎码工坊2 小时前
云原生安全:网络协议TCP详解
网络协议·tcp/ip·网络安全·云原生·云计算
鲨鱼吃橘子2 小时前
HTTPS协议原理
网络·c++·网络协议·算法·http·https
MIT_CompNote_探索者2 小时前
Linux操作系统向上提供了哪些系统调用?
linux·服务器·网络
le1616164 小时前
TCP建立连接为什么不是两次握手,而是三次,为什么不能在第二次握手时就建立连接?
java·网络·tcp/ip·面试
对World说Hello4 小时前
ping、tcpping、psping、paping、hping的区别
网络协议
还有几根头发呀4 小时前
HTTP 与 HTTPS
网络协议·http·https
源力祁老师4 小时前
Odoo: Owl Props 深度解析技术指南
前端·javascript·网络