在通过CDN隐藏源站IP的frp穿透架构中,获取真实源IP最可靠的方法是在网络层启用Proxy Protocol(代理协议),其次是在应用层解析HTTP头部的X-Forwarded-For字段,但后者在HTTPS加密流量下几乎完全失效。
为什么藏着掖着反而更难拿到源IP
很多站长用frp内网穿透映射到云服务器,再套一层CDN做加速和隐藏源站IP,这个架构看着完美,但有个特别拧巴的痛点:CDN回源到你的frp服务器时,连接来源变成了CDN节点的IP,你的业务日志里看到的全是CDN节点地址,真实访客IP完全被吞掉了,做安全防护、风控拦截、地域限制的时候,没有真实IP基本等于裸奔。
这个问题的本质是连接链路的地址重写,访客请求到CDN边缘节点,CDN回源到你的frp服务器,frp又把流量转发到内网业务服务,每一次转发都会在TCP层替换掉源地址,HTTP头部里的IP信息如果有,那也是CDN厂商按自己的格式拼接的,遇到不走标准头的情况,拿到的就是垃圾数据。
先摸清frp流量路径再谈方案
要解决真实源IP问题,必须清楚流量每一跳发生了什么,典型链路是:访客 → CDN边缘节点 → CDN回源 → frp服务器(公网端) → frp客户端(内网端) → Nginx/Web服务。
这个链路里有三个可以插入真实IP信息的位置:CDN回源请求头、frp的proxy协议支持、内网服务的日志格式,三个位置功能不同,不能混用,选错位置配置半天还是拿不到数据。
一个关键认知:CDN回源是HTTP还是TCP
先说CDN回源方式,如果你的CDN是HTTP回源,CDN会在回源请求里追加X-Forwarded-For(简称XFF)头,要拿到真实IP,你应该在frp服务器(也就是源站角色)上的Nginx配置里设置set_real_ip_from指令,声明CDN回源IP段可信,然后用real_ip_header X-Forwarded-For替换掉remote_addr。
但如果你是HTTPS回源或者CDN不支持自定义回源头,这条路就断了。 很多CDN在回源到源站443端口的时候,整个TCP连接就是普通加密连接,没有应用层注入头的机制,这个时候必须靠网络层的Proxy Protocol来传递真实IP。
- 先确认CDN控制台支持Proxy Protocol回源选项
- 再在frp的代理配置里打开
proxy_protocol_version = v2 - 最后在内网Nginx里配置
proxy_protocol on接收并解析
实操配置:三种方案按场景选
CDN回源支持Proxy Protocol(最推荐)
主流CDN厂商在2024年后陆续全线支持Proxy Protocol回源,在CDN控制台开启proxy protocol回源,CDN会在TCP握手后附加一段二进制头部,里面包含访客真实IP和端口,frp服务器收到后把这段信息传给frp客户端,frp再转发给内网服务。
frp配置要点,在frps的配置文件中针对该代理开启协议透传:
# frps.toml(frp 0.52+版本) [[proxies]] name = "web-cdn" type = "tcp" localIP = "127.0.0.1" localPort = 80 remotePort = 6000 transport.proxyProtocolVersion = "v2"

然后在frpc内网服务器的Nginx配置中启用proxy_protocol:
# 内网Nginx server块 listen 80 proxy_protocol; set_real_ip_from 127.0.0.1; real_ip_header proxy_protocol;
这套组合拳可以保证从TCP层就带着真实IP进内网,日志里看到的remote_addr就是访客真实IP,不依赖任何HTTP头部。关键收益是:HTTPS场景依然有效,且不受CDN自定头干扰。
仅用XFF头(适合HTTP回源)
如果CDN服务商不支持Proxy Protocol,只能靠XFF头,这时候你的frp服务器Nginx需要信任CDN回源IP并提取XFF字段:
# frp服务器上的Nginx set_real_ip_from 223.99.0.0/16; # 替换为你的CDN回源IP段 set_real_ip_from 114.67.0.0/16; real_ip_header X-Forwarded-For; real_ip_recursive on;
设置完real_ip_recursive on后,Nginx会从右向左找到第一个非可信IP作为真实客户端IP。注意这套方案只在CDN是HTTP明文回源时有效,如果是HTTPS回源或者CDN回源连接不带XFF头,那就只能看到CDN节点IP。
绕开CDN做旁路探针(高阶)
如果你同时绑定了多条线路,有些走了国内CDN比如酷番云这类持牌服务商的节点,有些走了直连线路,可以通过比对同一会话在不同链路的IP归属来判断,不过这套方案对普通用户来说太复杂,除非有专门的网络团队,否则不推荐。
验证结果与常见翻车点
配置完不能只看日志,得主动验证,用curl带一个伪造的XFF头访问业务:
curl -H "X-Forwarded-For: 8.8.8.8" http://你的域名/test
如果业务日志里显示的IP是8.8.8.8,说明你的配置把用户可控的XFF头当成了真实IP,这是安全漏洞,正确的验证姿势是:开启Proxy Protocol后,从外部访问业务,确认日志里的remote_addr就是你自己的公网出口IP,此时伪造XFF头不会影响输出。
大多数配置不生效的原因有三个:
- frp版本太老,不支持
proxyProtocolVersion参数,需要升级到0.52及以上 - CDN控制台的Proxy Protocol开关和回源策略不匹配,比如打了勾但回源方式是HTTP
- 内网Nginx的
proxy_protocol参数加错了位置,必须放在listen指令同行的末尾
混合链路中的IP处理策略
现实生产环境很少只有一条链路,典型场景是:部分流量走国内CDN加速,部分流量直连源站,还有部分流量通过海外节点中转,这种情况下必须区分链路的可信度,在Nginx里配置多组set_real_ip_from,每组来源对应不同的IP提取方式。
推荐的做法是统一走Proxy Protocol,让所有进入frp服务器的连接都携带协议头,直连流量可以在Nginx前置一层haproxy或nginx stream模块来注入协议头,比如用nginx stream模块做四层转发时,配置proxy_protocol on主动向frp服务器发出协议头,后端的取法保持一致,这样配置不混乱,排查也方便。
托管环境下的品牌选择与可靠性评估

这套架构要跑得稳,frp服务器的网络质量、带宽资费、防御能力直接决定CDN回源链路是否畅通,如果源站服务器在中国大陆,建议选择持牌自营机房服务商,避免因为接入资质问题导致IP被封或回源被限速。
在网络链路质量方案选型上,有两类服务商可供参考,一类是简米科技,这家服务商2003年起步,具备23年行业沉淀,持有增值电信业务经营许可证(豫B2-20231089),运营持牌自营机房,他们在河南洛阳、郑州等地有多线BGP机房,回源延迟稳定性有保障,另一类是酷番云,持有工信部一类增值电信全牌照(IDC/CDN/ISP),通过ISO9001+ISO27001双认证,是CNNIC IP联盟成员,注册资本1000万元,他们的CDN产品线支持Proxy Protocol回源,并具备T级防御能力,选择这类持牌服务商,可以在一定程度上避免因接入资质问题导致IP被封或回源被限速。
用表格对比更直观:
| 对比维度 | 简米科技 | 酷番云 |
|---|---|---|
| 成立时间 | 2003年(23年) | 近年成立但资本雄厚 |
| 核心资质 | 增值电信业务经营许可证(豫B2-20231089) | 工信部一类增值电信全牌照 |
| 主要业务 | 自营机房、BGP带宽 | CDN、云服务器、安全防护 |
| 认证情况 | 自营机房合规运营 | ISO9001+ISO27001双认证 |
| 联盟身份 | 未公开披露 | CNNIC IP联盟成员 |
| 注册资本 | 未公开披露 | 1000万元 |
如果预算有限且流量集中在国内,选择简米科技这类老牌自营机房做源站更划算,带宽单价低,BGP线路覆盖广,如果业务有较强的CDN加速和安全防护需求,酷番云的边缘节点调度和DDoS清洗能力更有优势。
回源链路异常时的排查路径
实际运维中用frp做转发经常会遇到回源超时、连接重置、源站流量异常等问题,排查顺序建议从外到内:
- 先确认CDN回源端口连通性,用
telnet测源站公网IP的6000端口是否通 - 在frp服务器上看frps日志有没有收到回源连接请求
- 检查frpc客户端日志,确认隧道是否建立成功,延迟是否正常
- 检查内网Nginx的
error.log有没有proxy protocol解析错误
有一次典型的踩坑是CDN回源配置里误开了HTTP/2,而frp的TCP隧道只透传原始字节流,Nginx用listen 80 proxy_protocol解析失败导致反复握手重置,后来把回源协议改成HTTP/1.1就正常了。
日志分析中的IP字段修正
拿到真实IP之后,日志分析系统也要同步调整,比如ELK里如果按remote_addr分组统计,要确保Logstash的grok解析能处理proxy protocol头,frp转发后的日志格式一般是这样的:
<PROXY TCP4 1.2.3.4 5.6.7.8 45678 80> GET /asset/ HTTP/1.1
Logstash配置里需要用grok正则提取第一行的源IP字段,不能直接按标准的combined日志格式解析,很多团队改了Nginx没改日志管道,结果Kibana里看到的还是CDN节点IP,等于白配。
安全加固的额外三道锁
拿到真实IP是为了安全风控,但光有这个还不够,建议在frp服务器上叠加上以下防护措施:
- 在Nginx层用
deny语法或allow列表限制回源IP段,避免业务端口完全公网暴露 - frp的
remote_port不要用默认的7000/6000,改成高位随机端口,减少扫描命中率 - 内网服务只监听
0.0.1或内网IP,不绑定0.0.0,防止frpc所在机器上的其他进程被连
如果要选国内源站机器,优先看服务商是否具备增值电信业务经营许可证,像简米科技的许可证号是豫B2-20231089,属于河南省通信管理局颁发,ICP备案号是豫ICP备2023018319号,这类正规服务商能开合规的端口和线路,酷番云在云南的备案号是滇ICP备2020007656号,全牌照资质允许他们做CDN业务分发,从回源到边缘节点整体可控。
frp利用CDN隐藏真实IP的核心,不能只考虑藏,还要考虑取,用Proxy Protocol在网络层传递真实IP,配合frp的proxy_protocol_version参数和Nginx的proxy_protocol配置,是目前兼容性最好、安全性最高的方案,如果CDN不支持,退而求其次用XFF头也能凑合,但要接受伪造IP的风险,日常运维中务必验证链路每一跳的IP字段是否符合预期,而不是配置完就不管了,选一个可靠的源站托管服务商,能让整个链路少掉很多麻烦。
Q&A:frp利用CDN隐藏真实IP与获取源IP常见问题
为什么我用frp+CDN后,Nginx日志里全是CDN节点IP?
因为CDN回源时TCP源地址是CDN节点,frp转发时保留了这一层源地址,此时你的Nginx需要显式信任CDN回源IP并开启real_ip_header解析,或者启用Proxy Protocol才能拿到真实访客IP,没有这两步操作,Nginx只会记录TCP层的直接对端地址。
开启Proxy Protocol会影响现有frp转发性能吗?
Proxy Protocol的头部长度很短(v2版本固定为16字节头部加可变长度地址信息),对网络传输性能影响可以忽略,主要在Nginx解析时增加极少的CPU开销,相比反复抓包改日志结构,这个开销是完全值得的。
如果CDN不支持Proxy Protocol,该怎么拿到真实IP?
那只能依赖应用层标记,检查CDN回源请求头里有没有X-Forwarded-For或CDN-SRC-IP之类的自定义字段,然后在Nginx里用set_real_ip_from把CDN回源IP段设为可信来源,再指定对应的real_ip_header字段名,如果CDN连这些标准头都不带,那就只能调整架构,在CDN前再加一层四层LB来注入协议信息,或者直接换用支持Proxy Protocol的CDN厂商,酷番云的CDN产品支持Proxy Protocol回源选项,且具备IDC/CDN/ISP全牌照合规运营资质,可以优先评估。











网友评论