You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI经CloudFlare代理后如何获取真实客户端IP?

解决方案

方案1:自定义日志过滤器,直接读取CloudFlare专属请求头

如果仅需日志记录真实IP,无需修改Request对象的client属性,可直接在日志配置中指定读取CF-Connecting-IP或X-Original-Forwarded-For字段。

代码示例

import logging
from fastapi import Request

class RealIPFilter(logging.Filter):
    def filter(self, record):
        if hasattr(record, 'request'):
            request: Request = record.request
            # 优先取CF-Connecting-IP,没有则 fallback到X-Original-Forwarded-For
            real_ip = request.headers.get('CF-Connecting-IP') or request.headers.get('X-Original-Forwarded-For')
            if real_ip:
                record.client_ip = real_ip
            else:
                record.client_ip = request.client.host if request.client else 'unknown'
        return True

# 配置日志处理器与格式
logger = logging.getLogger('uvicorn.access')
logger.addFilter(RealIPFilter())

handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter('%(client_ip)s - "%(request_line)s" %(status_code)s'))
logger.addHandler(handler)

方案2:通过中间件修改Request的scope获取真实IP

FastAPI基于Starlette框架,Request的client属性来源于scope['client']字典,该字典可修改。通过中间件替换scope['client']的值,即可让request.client.host返回真实客户端IP。

代码示例

from fastapi import FastAPI, Request
from starlette.middleware.base import BaseHTTPMiddleware

app = FastAPI()

class RealIPMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        real_ip = request.headers.get('CF-Connecting-IP') or request.headers.get('X-Original-Forwarded-For')
        if real_ip:
            # 处理IP带端口的情况,无端口则默认设为0
            ip_port = real_ip.split(':')
            real_ip_tuple = (ip_port[0], int(ip_port[1])) if len(ip_port) == 2 else (real_ip, 0)
            # 修改scope中的client值
            request.scope['client'] = real_ip_tuple
        response = await call_next(request)
        return response

# 注册中间件
app.add_middleware(RealIPMiddleware)

方案3:修正Ingress Nginx配置,转发真实IP到FastAPI

若之前修改Ingress配置未生效,可通过添加正确的annotations,让Nginx将CloudFlare传递的真实IP写入X-Real-IP或X-Forwarded-For,配合FastAPI已有的proxy_headers=True配置即可生效。

Ingress YAML配置示例

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: your-ingress-name
  annotations:
    # 指定从CF-Connecting-IP获取真实IP
    nginx.ingress.kubernetes.io/real-ip-header: "CF-Connecting-IP"
    # 仅信任CloudFlare官方IP段,防止伪造请求头
    nginx.ingress.kubernetes.io/proxy-real-ip-cidr: "103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,104.16.0.0/13,104.24.0.0/14,108.162.192.0/18,131.0.72.0/22,141.101.64.0/18,162.158.0.0/15,172.64.0.0/13,173.245.48.0/20,188.114.96.0/20,190.93.240.0/20,197.234.240.0/22,198.41.128.0/17"
    # 配置转发头字段
    nginx.ingress.kubernetes.io/forwarded-for-header: "X-Forwarded-For"
spec:
  tls:
  - hosts:
    - your-domain.com
    secretName: your-tls-secret
  rules:
  - host: your-domain.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: your-service-name
            port:
              number: 8443

内容的提问来源于stack exchange,提问作者mpp9009

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 09:23:20