内网穿透工具【frp】的核心功能底层处理逻辑解析
文章目录
- 概述
- 技术架构
- 整体架构模式
- 核心组件关系
- 1. 服务端核心组件
- 2. 客户端核心组件
- 核心处理流程
- 1. 连接建立流程
- 客户端登录过程
- 2. 消息处理机制
- 消息分发架构
- 3. 代理创建与管理
- 代理生命周期管理
- 4. 心跳与连接保活
- 心跳机制
- 高级功能实现
- 1. P2P模式与NAT穿透
- NAT类型分类
- 穿透模式选择
- 穿透实现流程
- 2. 多协议支持架构
- 代理类型工厂
- 协议处理差异
- 3. 连接池与多路复用
- 工作连接池设计
- 安全机制
- 1. 传输安全
- 2. 访问控制
- 项目地址
概述
frp(Fast Reverse Proxy)是一个高性能的反向代理应用,专注于内网穿透。本文档详细介绍了frp核心功能的底层处理逻辑,帮助第一次接触该项目的开发者深入理解其技术架构和实现原理。
技术架构
整体架构模式
frp采用典型的客户端-服务器(C/S)架构模式,包含以下核心组件:
核心组件关系
1. 服务端核心组件
- Service: 服务端主服务,负责管理所有连接和组件
- ControlManager: 管理所有客户端控制连接
- ProxyManager: 管理所有代理实例
- MessageTransporter: 消息传输层,处理客户端-服务端通信
2. 客户端核心组件
- Service: 客户端主服务,管理与服务端的连接
- Control: 控制连接管理器,维护与服务端的控制通道
- ProxyManager: 管理客户端代理实例
- VisitorManager: 管理访问者连接(用于P2P)
核心处理流程
1. 连接建立流程
客户端登录过程
核心代码逻辑:
-
客户端登录:
- 客户端发送
Login
消息包含版本、主机名、认证信息 - 服务端验证认证信息(Token或OIDC)
- 创建唯一的RunID标识客户端会话
- 客户端发送
-
控制连接建立:
// 服务端创建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的多路复用机制:
核心实现:
-
消息分发器(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)
-
消息传输器(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 }
-
消息类型系统:
- 支持多种消息类型:Login、NewProxy、ReqWorkConn、StartWorkConn等
- 每种消息都有对应的处理逻辑和响应机制
3. 代理创建与管理
代理生命周期管理
核心处理逻辑:
-
代理工厂模式:
var proxyFactoryRegistry = map[reflect.Type]func(*BaseProxy, v1.ProxyConfigurer) Proxy{}func RegisterProxyFactory(proxyConfType reflect.Type, factory func(*BaseProxy, v1.ProxyConfigurer) Proxy) {proxyFactoryRegistry[proxyConfType] = factory }
-
代理包装器(Wrapper):
- 管理代理状态和生命周期
- 实现健康检查机制
- 处理重连和错误恢复
-
工作连接处理:
func (pm *Manager) HandleWorkConn(name string, workConn net.Conn, m *msg.StartWorkConn) {pw, ok := pm.proxies[name]if ok {pw.InWorkConn(workConn, m) // 将工作连接分发给对应代理} }
4. 心跳与连接保活
心跳机制
实现细节:
-
心跳发送:
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) }
-
超时检测:
- 客户端检测Pong消息超时
- 服务端检测Ping消息超时
- 超时后自动重连或关闭连接
高级功能实现
1. P2P模式与NAT穿透
NAT类型分类
frp实现了智能的NAT类型检测和穿透算法:
穿透模式选择
type NatFeature struct {NatType string // EasyNAT/HardNATBehavior string // 端口变化行为PortsDifference int // 端口差值RegularPortsChange bool // 是否规律变化PublicNetwork bool // 是否公网
}
穿透算法:
-
模式0: 双方都是EasyNAT或一方在公网
- 简单的双向探测
- 低TTL消息探测
-
模式1: HardNAT与EasyNAT,端口变化规律
- 多端口范围探测
- 基于端口预测算法
-
模式2: HardNAT与EasyNAT,端口变化不规律
- 随机端口探测
- 多监听端口策略
-
模式3/4: 双HardNAT场景
- 复合探测策略
- 适应性算法选择
穿透实现流程
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)
}
协议处理差异
-
TCP类协议 (TCP/HTTP/HTTPS):
- 使用GeneralTCPProxy统一处理
- 支持连接池和多路复用
- HTTP协议额外支持虚拟主机路由
-
UDP协议 (UDP/SUDP):
- 无连接状态管理
- 数据包级别的转发
- 支持NAT穿透
-
特殊协议 (STCP/XTCP):
- STCP:安全的内网直连
- XTCP:P2P模式的大数据传输
3. 连接池与多路复用
工作连接池设计
实现机制:
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/