如何在Python(FastAPI)中不依赖第三方服务获取指定允许的公网IP
在FastAPI中无需第三方服务获取公网IP的实现方法
根据你的需求,这里提供两种完全不依赖第三方服务或付费接口的实现方案,分别对应获取服务自身公网IP和客户端真实公网IP的场景:
一、获取服务自身的公网出口IP
利用Python的socket模块,通过创建UDP套接字连接到公共地址(无需实际发送数据),即可获取本机对外的公网出口IP。这种方法本质是读取系统网络栈选择的出口IP,完全不依赖外部API。
实现代码
import socket from fastapi import FastAPI app = FastAPI() def get_self_public_ip() -> str: try: # 创建UDP套接字,连接到公共DNS服务器(仅用于触发出口IP选择) with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s: # 目标地址可替换为其他稳定的公网地址(如1.1.1.1:80) s.connect(("8.8.8.8", 80)) # getsockname()返回本地端的IP和端口,取第一个元素即为出口IP return s.getsockname()[0] except Exception as e: return f"获取失败: {str(e)}" @app.get("/self-public-ip") async def fetch_self_public_ip(): ip = get_self_public_ip() return {"service_public_ip": ip}
说明
- 无需发送任何实际请求到第三方服务,仅利用socket的连接特性获取系统分配的出口IP。
- 适用于服务需要知晓自身对外暴露的公网IP的场景,比如生成带公网IP的回调地址。
- 若机器处于多层NAT环境下,返回的IP是最外层NAT的公网IP。
二、获取客户端的真实公网IP
如果你的FastAPI服务部署在反向代理(如Nginx、Apache)之后,直接通过request.client.host只能拿到代理服务器的IP,需要通过反向代理传递的HTTP头获取客户端真实IP;无代理场景下则直接读取连接IP即可。
实现代码
from fastapi import FastAPI, Request app = FastAPI() @app.get("/client-public-ip") async def fetch_client_public_ip(request: Request): # 优先读取反向代理传递的X-Forwarded-For头 forwarded_for = request.headers.get("X-Forwarded-For") if forwarded_for: # X-Forwarded-For格式通常为"客户端IP, 代理1IP, 代理2IP...",取第一个即可 client_ip = forwarded_for.split(",")[0].strip() else: # 无代理场景下直接获取连接的客户端IP client_ip = request.client.host return {"client_public_ip": client_ip}
反向代理配置示例(以Nginx为例)
若使用Nginx作为反向代理,需在配置中添加以下指令,确保传递真实客户端IP:
location / { proxy_pass http://your-fastapi-server:port; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; }
说明
- 完全依赖HTTP请求头或直接连接信息,无需调用任何外部服务。
- 需确保反向代理正确配置IP传递,否则可能返回代理服务器的IP而非客户端真实公网IP。
注意事项
- 第一种方法中,若机器有多个网卡或特殊网络路由,可尝试更换目标地址(如
1.1.1.1:80)以获取正确的出口IP。 - 两种方法均无需额外安装依赖(仅使用Python标准库和FastAPI本身)。
内容的提问来源于stack exchange,提问作者Pabitra Pandit
相关产品推荐
相关产品推荐

