可以用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/
相关文章也说明了这一点:
链接: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配置代码
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 地址。