背景

整个架构是:

用户访问域名 =》 cloudflare =》 nginx =》 django

默认情况, 通过 request.META.get('REMOTE_ADDR') 获取到的是 cloudflare 的 ip(由于我用了docker,所以我拿到的似乎是docker内部ip), 而不是用户真实ip。

request.META.get('HTTP_X_REAL_IP') 拿到的, 也不是真实ip

解决步骤

花了不少时间在网上搜, 各种花里胡哨的办法 都尝试了, 比如:

1、修改 nginx 把 cloudflare 的ip 存到 nginx 配置

2、比如 map 映射

3、。。。。

都感觉太繁琐,而且似乎也不行, 最后发现, cloudflare 似乎 默认就给设置了 一个 HTTP_CF_CONNECTING_IP 这个就是真实ip

通过 request.META.get('HTTP_CF_CONNECTING_IP') 就可以拿到 用户真实ip了。

解决办法

只需要一个步骤: request.META.get('HTTP_CF_CONNECTING_IP')

封装为一个函数

def get_real_ip(request):
    """
    获取用户真实ip
    """
    if 'HTTP_CF_CONNECTING_IP' in request.META:
        remote_ip_tmp = request.META.get('HTTP_CF_CONNECTING_IP')
    elif 'X-Forwarded-For' in request.META:
        remote_ip_tmp = request.META.get('X-Forwarded-For').split(',')[0] # 第一个也是真实ip,作为备选项
    else:
        remote_ip_tmp = request.META.get('REMOTE_ADDR', None)
    return remote_ip_tmp
 

另外

cloudflare 还有其他一个 http的头:

'HTTP_CF_RAY': 'xxxxxxx-LHR',  // 不知道做什么的
'HTTP_CF_IPCOUNTRY': 'CN', // 国家?
'HTTP_CF_VISITOR': '{"scheme":"https"}', // 不知道做什么的
'HTTP_CF_CONNECTING_IP': 'xxx.xx.xx.xx', // 真实ip

cf这些头的 说明文档: https://developers.cloudflare.com/fundamentals/reference/http-request-headers/