Python socket服务端经ngrok转发后无法获取客户端公网IP
问题原因
ngrok的本质是反向代理转发服务,你将本地端口暴露到公网后,请求链路如下:
- 手机端的访问请求首先发送到ngrok的公网服务器
- ngrok公网服务器将请求转发到你本地运行的ngrok客户端进程
- 本地ngrok客户端再向你监听在127.0.0.1:9999的socket服务发起新的TCP连接,把请求内容转发给你的服务
你调用socket.accept()获取到的地址,是本地ngrok客户端和你的socket服务建立连接的地址,自然不是手机端的公网IP。
解决方法
ngrok在HTTP模式下转发请求时,会自动在请求头中添加X-Forwarded-For字段,该字段的值就是原始请求客户端的真实公网IP。你可以直接从已经解析出的HTTP请求头中提取该字段即可,不需要从socket层获取地址。
你可以在现有代码的headers = headers.decode('utf-8') 行后添加如下逻辑获取真实IP:
real_client_ip = None # 逐行遍历请求头匹配X-Forwarded-For字段 for line in headers.split("\r\n"): if line.lower().startswith("x-forwarded-for:"): # 拆分冒号,取后面的值并去除首尾空格 real_client_ip = line.split(":", 1)[1].strip() # X-Forwarded-For格式为 真实IP, 代理1IP, 代理2IP,取第一个值即可 real_client_ip = real_client_ip.split(",")[0].strip() break if real_client_ip: print(f"客户端真实公网IP为: {real_client_ip}")
内容的提问来源于stack exchange,提问作者Priyansh Gupta
相关产品推荐
相关产品推荐

