当前位置: 首页 > news >正文

内网穿透工具【frp】的核心功能底层处理逻辑解析

文章目录

  • 概述
  • 技术架构
    • 整体架构模式
    • 核心组件关系
      • 1. 服务端核心组件
      • 2. 客户端核心组件
  • 核心处理流程
    • 1. 连接建立流程
      • 客户端登录过程
    • 2. 消息处理机制
      • 消息分发架构
    • 3. 代理创建与管理
      • 代理生命周期管理
    • 4. 心跳与连接保活
      • 心跳机制
  • 高级功能实现
    • 1. P2P模式与NAT穿透
      • NAT类型分类
      • 穿透模式选择
      • 穿透实现流程
    • 2. 多协议支持架构
      • 代理类型工厂
      • 协议处理差异
    • 3. 连接池与多路复用
      • 工作连接池设计
  • 安全机制
    • 1. 传输安全
    • 2. 访问控制
  • 项目地址


概述

frp(Fast Reverse Proxy)是一个高性能的反向代理应用,专注于内网穿透。本文档详细介绍了frp核心功能的底层处理逻辑,帮助第一次接触该项目的开发者深入理解其技术架构和实现原理。

技术架构

整体架构模式

frp采用典型的客户端-服务器(C/S)架构模式,包含以下核心组件:

外部用户
frps服务端
内网客户端frpc
本地服务
ControlManager
ProxyManager
PluginManager
ProxyManager
VisitorManager
Control连接

核心组件关系

1. 服务端核心组件

  • Service: 服务端主服务,负责管理所有连接和组件
  • ControlManager: 管理所有客户端控制连接
  • ProxyManager: 管理所有代理实例
  • MessageTransporter: 消息传输层,处理客户端-服务端通信

2. 客户端核心组件

  • Service: 客户端主服务,管理与服务端的连接
  • Control: 控制连接管理器,维护与服务端的控制通道
  • ProxyManager: 管理客户端代理实例
  • VisitorManager: 管理访问者连接(用于P2P)

核心处理流程

1. 连接建立流程

客户端登录过程

frpc客户端frps服务端ControlManager发送Login消息验证认证信息创建Control实例返回LoginResp消息建立控制连接发送ReqWorkConn请求创建工作连接frpc客户端frps服务端ControlManager

核心代码逻辑

  1. 客户端登录

    • 客户端发送Login消息包含版本、主机名、认证信息
    • 服务端验证认证信息(Token或OIDC)
    • 创建唯一的RunID标识客户端会话
  2. 控制连接建立

    // 服务端创建Control实例
    ctl, err := NewControl(ctx, rc, pxyManager, pluginManager, authVerifier, ctlConn, !internal, loginMsg, serverCfg)// 客户端创建Control实例
    ctl := &Control{sessionCtx:     sessionCtx,msgDispatcher:  msg.NewDispatcher(conn),msgTransporter: transport.NewMessageTransporter(dispatcher.SendChannel()),
    }
    

2. 消息处理机制

消息分发架构

frp使用了一套完善的消息处理系统,类似于HTTP2的多路复用机制:

网络连接
MessageDispatcher
消息解析
类型路由
Handler处理
MessageTransporter
消息发送
响应等待
响应分发

核心实现

  1. 消息分发器(Dispatcher)

    type Dispatcher struct {rw io.ReadWritersendCh         chan MessagemsgHandlers    map[reflect.Type]func(Message)defaultHandler func(Message)
    }// 注册消息处理器
    dispatcher.RegisterHandler(&msg.NewProxy{}, handleNewProxy)
    dispatcher.RegisterHandler(&msg.ReqWorkConn{}, handleReqWorkConn)
    
  2. 消息传输器(MessageTransporter)

    type MessageTransporter interface {Send(msg.Message) errorDo(ctx context.Context, req msg.Message, laneKey, recvMsgType string) (msg.Message, error)Dispatch(m msg.Message, laneKey string) bool
    }
    
  3. 消息类型系统

    • 支持多种消息类型:Login、NewProxy、ReqWorkConn、StartWorkConn等
    • 每种消息都有对应的处理逻辑和响应机制

3. 代理创建与管理

代理生命周期管理

发送NewProxy
服务端确认
启动失败
关闭代理
重试
健康检查失败
重新启动
ProxyPhaseNew
ProxyPhaseWaitStart
ProxyPhaseRunning
ProxyPhaseStartErr
ProxyPhaseClosed
ProxyPhaseCheckFailed

核心处理逻辑

  1. 代理工厂模式

    var proxyFactoryRegistry = map[reflect.Type]func(*BaseProxy, v1.ProxyConfigurer) Proxy{}func RegisterProxyFactory(proxyConfType reflect.Type, factory func(*BaseProxy, v1.ProxyConfigurer) Proxy) {proxyFactoryRegistry[proxyConfType] = factory
    }
    
  2. 代理包装器(Wrapper)

    • 管理代理状态和生命周期
    • 实现健康检查机制
    • 处理重连和错误恢复
  3. 工作连接处理

    func (pm *Manager) HandleWorkConn(name string, workConn net.Conn, m *msg.StartWorkConn) {pw, ok := pm.proxies[name]if ok {pw.InWorkConn(workConn, m)  // 将工作连接分发给对应代理}
    }
    

4. 心跳与连接保活

心跳机制

客户端服务端Ping消息Pong响应检查Pong超时重连或关闭alt[超时检测]检查Ping超时关闭连接alt[服务端检测]loop[心跳循环]客户端服务端

实现细节

  1. 心跳发送

    func (ctl *Control) heartbeatWorker() {sendHeartBeat := func() (bool, error) {pingMsg := &msg.Ping{}ctl.sessionCtx.AuthSetter.SetPing(pingMsg)return false, ctl.msgDispatcher.Send(pingMsg)}go wait.BackoffUntil(sendHeartBeat, backoffManager, true, ctl.doneCh)
    }
    
  2. 超时检测

    • 客户端检测Pong消息超时
    • 服务端检测Ping消息超时
    • 超时后自动重连或关闭连接

高级功能实现

1. P2P模式与NAT穿透

NAT类型分类

frp实现了智能的NAT类型检测和穿透算法:

NAT类型检测
STUN服务器探测
地址映射分析
NAT类型
EasyNAT: 端口固定
HardNAT: 端口变化
行为分析
端口变化规律
BehaviorNoChange
BehaviorPortChanged
BehaviorIPChanged
BehaviorBothChanged

穿透模式选择

type NatFeature struct {NatType            string  // EasyNAT/HardNATBehavior           string  // 端口变化行为PortsDifference    int     // 端口差值RegularPortsChange bool    // 是否规律变化PublicNetwork      bool    // 是否公网
}

穿透算法

  1. 模式0: 双方都是EasyNAT或一方在公网

    • 简单的双向探测
    • 低TTL消息探测
  2. 模式1: HardNAT与EasyNAT,端口变化规律

    • 多端口范围探测
    • 基于端口预测算法
  3. 模式2: HardNAT与EasyNAT,端口变化不规律

    • 随机端口探测
    • 多监听端口策略
  4. 模式3/4: 双HardNAT场景

    • 复合探测策略
    • 适应性算法选择

穿透实现流程

Visitorfrps服务端ClientNatHoleVisitor消息NatHoleClient消息分析NAT特征选择穿透策略NatHoleResp(策略A)NatHoleResp(策略B)UDP探测包UDP探测包par[并发穿透]建立P2P连接Visitorfrps服务端Client

2. 多协议支持架构

代理类型工厂

// 通用TCP代理
type GeneralTCPProxy struct {*BaseProxy
}// UDP代理
type SUDPProxy struct {*BaseProxycfg *v1.SUDPProxyConfiglocalAddr *net.UDPAddr
}// HTTP代理(继承TCP)
func init() {RegisterProxyFactory(reflect.TypeOf(&v1.TCPProxyConfig{}), NewGeneralTCPProxy)RegisterProxyFactory(reflect.TypeOf(&v1.HTTPProxyConfig{}), NewGeneralTCPProxy)RegisterProxyFactory(reflect.TypeOf(&v1.SUDPProxyConfig{}), NewSUDPProxy)
}

协议处理差异

  1. TCP类协议 (TCP/HTTP/HTTPS):

    • 使用GeneralTCPProxy统一处理
    • 支持连接池和多路复用
    • HTTP协议额外支持虚拟主机路由
  2. UDP协议 (UDP/SUDP):

    • 无连接状态管理
    • 数据包级别的转发
    • 支持NAT穿透
  3. 特殊协议 (STCP/XTCP):

    • STCP:安全的内网直连
    • XTCP:P2P模式的大数据传输

3. 连接池与多路复用

工作连接池设计

控制连接
工作连接池
WorkConn1
WorkConn2
WorkConn3
用户请求
代理分发

实现机制

type Control struct {workConnCh chan net.Conn  // 工作连接池poolCount  int             // 池大小
}func (ctl *Control) GetWorkConn() (net.Conn, error) {select {case workConn := <-ctl.workConnCh:// 获取到连接后,请求服务端补充新连接ctl.msgDispatcher.Send(&msg.ReqWorkConn{})return workConn, nilcase <-time.After(timeout):return nil, fmt.Errorf("获取工作连接超时")}
}

安全机制

1. 传输安全

  • TLS加密:控制和数据连接加密
  • Token验证:防止未授权访问
  • IP白名单:访问控制

2. 访问控制

  • 用户权限:基于用户的代理访问控制
  • 域名限制:HTTP代理的域名白名单
  • 端口限制:服务端端口使用限制

项目地址

作者:https://afdian.com/a/fatedier
源码:https://github.com/fatedier/frp
在线文档:https://gofrp.org/zh-cn/docs/

http://www.dtcms.com/a/355487.html

相关文章:

  • WINTRUST!_ExplodeMessage的作用是赋值psIndirectData
  • Windows 11 中 PowerShell 与 CMD 的深度对比:从定位到实战
  • 集成 A2A Protocol - BeeAI 框架的智能代理通信解决方案
  • 机器人芯片:驱动智能机器的核心技术引擎
  • 有限与无限的游戏 之感
  • 稳石氢能受邀出席2025势银绿氢产业大会,荣获“2025绿氢技术突破奖”!
  • SAP SD模块用户经常遇到的痛点以及解决方案
  • Circuitjs 测试点的使用
  • HTML+CSS、JavaScript、Vue、Ajax
  • Docker 40个自动化管理脚本-2 (40/40)
  • 【动态规划】子数组、子串问题
  • 国产芯力量!贴片式SD卡搭载北京君正Rk瑞芯微,打造嵌入式存储低延迟+高可靠黄金组合​
  • MongoDB 文档模型设计:JSON 结构的灵活性与陷阱
  • Mac训练大模型:MLX-LM框架LoRA训练Qwen3并集成SwanLab进行可视化
  • 基于mac的智能语音处理与应用开发-环境部署
  • 【LangGraph】核心概念速通:State/Node/Edge、通道、事件与流式输出
  • Java8-21的核心特性以及用法
  • FPGA位宽调整模块
  • 跨语言 UDP 聊天程序实现:Go 客户端与 Python 服务端[超简单 入门级聊天程序 包含完整源码]
  • 线段树 (Segment Tree)
  • 理解AI智能体:智能体记忆
  • day04-kubernetes(k8s)
  • 微动开关-电竞鼠标核心!5000万次寿命微动开关评测
  • windows PowerToys之无界鼠标:一套键鼠控制多台设备
  • 【详细教程】如何将SQLBot的MCP服务集成到n8n
  • Linux_详解线程池
  • 【mysql】SQL HAVING子句详解:分组过滤的正确姿势
  • SystemVerilog学习【六】功能覆盖率详解
  • OpenCV 4.9+ 进阶技巧与优化
  • Shell编程(一)