菜单

连接管理

相关源文件

本页面介绍了frp如何管理服务器 (frps) 和客户端 (frpc) 组件之间的连接,以及用于建立、维护和复用连接的各种机制。连接管理是frp架构的核心部分,它能够通过NAT/防火墙有效地隧道传输流量。

连接类型与架构

frp涉及多种连接类型,它们在系统中承担不同的功能

连接类型:

  1. 控制连接:frpc与frps之间用于控制消息的持久性TCP/KCP/QUIC/WebSocket连接
  2. 工作连接:用于传输实际的代理数据
  3. 用户连接:用户到代理服务的连接

来源: client/control.go34-81; server/control.go97-128; client/service.go62-134; server/service.go74-128

控制连接生命周期

控制连接是frpc和frps之间最基本的通信通道。它负责处理认证、代理注册和工作连接协调。

控制连接建立

  1. 客户端发起与服务器的连接,并发送包含认证信息的 Login 消息
  2. 如果认证成功,服务器将使用 LoginResp 消息进行响应,并请求工作连接
  3. 客户端和服务器之间交换心跳信号以维持连接

来源: client/service.go246-308; server/service.go420-428; server/control.go202-218

控制连接维护

客户端和服务器都实现了心跳机制来检测连接故障

  1. 客户端定期向服务器发送 Ping 消息
  2. 服务器用 Pong 消息进行响应
  3. 如果在配置的超时时间内未收到响应,则认为连接已断开

来源: client/control.go237-276; server/control.go299-312

工作连接管理

工作连接用于传输实际的代理数据。它们通过一个池化机制进行管理。

工作连接池

服务器为每个客户端维护一个工作连接池

  1. 当客户端控制连接建立时,服务器会请求多个工作连接
  2. 这些连接存储在 workConnCh 通道中
  3. 当需要代理用户连接时,服务器会从池中获取一个工作连接
  4. 如果池为空,服务器会向客户端请求一个新的工作连接

来源: server/control.go232-297; client/control.go125-161

连接复用

frp实现了多种连接复用机制,以高效利用网络资源。

控制连接的Yamux复用

当启用TCP复用时,系统使用 hashicorp/yamux 在单个TCP连接上复用多个逻辑流

  1. 客户端建立一个到服务器的TCP连接
  2. 然后使用yamux将此连接升级为一个复用会话
  3. 在此会话中创建多个逻辑流,用于控制和工作连接

来源: server/service.go516-536; client/connector.go

传输协议

frp 支持多种用于控制连接的传输协议:

协议描述优点
TCP标准TCP连接可靠,支持广泛
KCP基于UDP的可靠传输在丢包网络中性能更佳
QUIC基于UDP的复用传输安全,低延迟,连接迁移
WebSocket基于TCP的WebSocket协议与代理/防火墙兼容性更好
TLS加密TCP连接安全通信

来源: server/service.go222-262; server/service.go274-279

HTTP和HTTPS复用

对于HTTP和HTTPS代理,frp实现了虚拟主机功能,将请求路由到不同的后端。

  1. HTTP(S)请求包含Host头和路径
  2. frp利用这些信息将请求路由到适当的后端
  3. vhost 包为此目的提供了 HTTPReverseProxyHTTPSMuxer

来源: pkg/util/vhost/http.go41-200; pkg/util/vhost/https.go26-37

连接处理流程

以下章节描述了frp中如何处理不同的连接场景。

服务器端连接处理

当新连接建立到服务器时

  1. 服务器读取第一个消息以确定其类型
  2. 根据消息类型,它会相应地处理连接
    • Login:注册为控制连接
    • NewWorkConn:注册为工作连接
    • NewVisitorConn:注册为访问者连接

来源: server/service.go420-480; server/service.go567-649

客户端连接建立

客户端服务

  1. 连接到服务器并发送Login消息
  2. 创建控制实例以管理连接
  3. 注册消息处理程序以处理服务器请求
  4. 当服务器请求工作连接时,创建新连接并进行注册

来源: client/service.go168-202; client/control.go125-161

基于消息的通信

frp使用基于消息的协议在客户端和服务器之间进行通信。与连接管理相关的主要消息包括:

消息类型目的方向
Login认证并建立控制连接客户端 → 服务器
LoginResp对Login尝试的响应服务器 → 客户端
NewProxy注册新的代理服务客户端 → 服务器
NewProxyResp对代理注册的响应服务器 → 客户端
Ping/Pong心跳消息双向
ReqWorkConn请求新的工作连接服务器 → 客户端
NewWorkConn注册新的工作连接客户端 → 服务器
StartWorkConn开始使用工作连接服务器 → 客户端

来源: pkg/msg/msg.go; client/control.go230-235; server/control.go361-367

连接错误处理与恢复

frp实现了多种机制来处理连接错误并确保系统稳定性

  1. 心跳超时:客户端和服务器都监控心跳信号以检测连接故障
  2. 自动重连:如果控制连接丢失,客户端会自动使用退避策略尝试重新连接
  3. 工作连接池:维护多个工作连接以优雅地处理故障

重连策略

当控制连接失败时,客户端

  1. 通过显式错误或错过的心跳检测到故障
  2. 尝试使用指数退避策略进行重连
  3. 对于一分钟内的前三次重试,使用较短的重试间隔
  4. 逐渐增加间隔,直到达到最大值(通常为20秒)

来源: client/service.go215-244; client/control.go237-276

SSH 隧道网关

frp 也支持通过 SSH 隧道网关建立连接,这为连接管理提供了一种替代方法。

  1. 服务器可以运行一个允许客户端安全连接的 SSH 服务器。
  2. 这使得在不直接运行 frpc 的情况下创建代理成为可能。
  3. 通过 SSH 隧道建立的连接的处理方式与常规连接类似。

来源: pkg/ssh/gateway.go32-147; server/service.go264-271

结论

frp 中的连接管理围绕着维护客户端和服务器之间稳定的控制连接,通过池化和多路复用高效管理工作连接,并支持各种传输协议。这种灵活的架构使 frp 能够在不同的网络环境和约束条件下提供可靠的代理服务。