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

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

01-real_ip命令集详解

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

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

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

        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

#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,则可以用下面的命令:

set_real_ip_from 0.0.0.0/0;

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

第2个步骤:使用命令real_ip_header告诉Nignx从哪个头信息中获取真实IP。
在这个步骤里面,常见的下面两条命令:

        real_ip_header CF-Connecting-IP;
        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/
接入Cloudflare后Nginx和Django获取用户真实IP的办法_第1张图片

相关文章也说明了这一点:
链接:https://www.kchuhai.com/report/view-19321.html
接入Cloudflare后Nginx和Django获取用户真实IP的办法_第2张图片

其实按照Cloudflare的设计,最好的是从True-Client-IP Header中获取客户端的真实IP,但是如果要使用这个头,是需要付费的。
官方文档:https://developers.cloudflare.com/network/true-client-ip-header/
接入Cloudflare后Nginx和Django获取用户真实IP的办法_第3张图片

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

    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 地址:

# 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 设置。在您的配置中,您已经使用了以下指令:

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 地址。

你可能感兴趣的:(Cloudflare,tcp/ip,网络协议,网络)