# tio-frp **Repository Path**: ppnt/tio-frp ## Basic Information - **Project Name**: tio-frp - **Description**: 将 FRP 客户端嵌入 Java 应用。TCP 收发由 tio-core 承载,应用启动时读取 `frpc.toml`,建立控制连接、注册代理并转发流量,无需运行独立的 frpc 进程。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-09 - **Last Updated**: 2026-10-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # tio-frp 将 FRP 客户端嵌入 Java 应用。TCP 收发由 tio-core 承载,应用启动时读取 `frpc.toml`,建立控制连接、注册代理并转发流量,无需运行独立的 frpc 进程。 支持 TCP 和 HTTP 代理。完整教程见 [docs:从零实现到部署](./docs/README.md),包含协议实现、frps/Nginx/客户端配置和 Java 应用集成。 ## 运行要求 - Java 21 或更高版本。 - 可访问的 frps 服务端和匹配的 token。 - socket 模式的目标服务已监听 `localIP:localPort`;tio 模式传入同 JVM 已启动的 `TioServer`。 两种模式按代理配置,详见[内部转发与通用转发](./docs/06-local-transport.md)。生产代码不依赖 tio-boot,POM 中 tio-boot 仅用于集成测试。 ## 构建与依赖 按照 `build.txt` 执行: ```shell mvn clean install -Dgpg.skip=true -Pproduction ``` 应用添加依赖;版本属性由应用的依赖管理统一设置: ```xml nexus.io tio-frp ${tio-frp.version} ``` ## 嵌入启动 将 `frpc.example.toml` 复制为工作目录中的 `frpc.toml`,填写服务端地址、token 和端口。先启动本地服务,再启动隧道: ```java import java.time.Duration; import nexus.io.frp.service.FrpClient; public class TunnelBootstrap { public static FrpClient start() throws Exception { FrpClient client = FrpClient.startDefault(); Runtime.getRuntime().addShutdownHook(new Thread(client::close, "frp-shutdown")); if (!client.awaitReady(Duration.ofSeconds(20))) { System.out.println("Tunnel is reconnecting: " + client.getLastError()); } return client; } } ``` `startDefault()` 通过 `EnvUtils.get("frp.config", "frpc.toml")` 获取配置路径,默认相对进程工作目录解析。启动是异步的;网络不可用时后台继续重试。`awaitReady` 超时不关闭客户端。`isReady()` 表示控制连接中所有代理已收到注册成功响应;它不代表本地业务服务健康。 需要自定义生命周期时保留 `FrpClient`,在应用停止或重新加载前调用 `close()`。同一实例只允许启动一次;关闭后如需重启,应创建新实例。关闭仅释放该客户端的连接,保留应用共享的 tio 执行器。 ## 配置示例 ### TCP 代理 ```toml serverAddr = "frps.example.com" serverPort = 7000 auth.token = "replace-with-your-token" [[proxies]] name = "web" type = "tcp" localIP = "127.0.0.1" localPort = 80 remotePort = 1039 ``` ### HTTP 子域名代理 ```toml serverAddr = "frps.example.com" serverPort = 8000 auth.token = "replace-with-your-token" [[proxies]] name = "web-001" type = "http" localIP = "127.0.0.1" localPort = 80 subdomain = "001" ``` 服务端设置 `vhostHTTPPort` 和 `subDomainHost`,Nginx 转发到该 HTTP 端口并保留 Host。HTTP 模式不设置 `remotePort`。支持 `customDomains`、`locations`、`hostHeaderRewrite`、`httpUser`、`httpPassword`;完整示例见 [三端配置](./docs/03-configuration.md)。 默认启用 `transport.tcpMux` 和 `transport.tls.enable`,支持 `transport.tls.disableCustomTLSFirstByte`。`transport.tcpMux` 必须与服务端设置一致。 支持的可选字段: | 字段 | 默认值 | 用途 | | --- | --- | --- | | `user` | 空字符串 | 为代理名称添加用户前缀 | | `auth.method` | `token` | token 鉴权 | | `transport.protocol` | `tcp` | 服务端连接协议 | | `transport.tcpMux` | `true` | Yamux 连接复用 | | `transport.tls.enable` | `true` | 客户端与 frps 之间的 TLS | | `transport.tls.disableCustomTLSFirstByte` | `true` | 使用标准 TLS 首字节 | | `transport.tls.trustedCaFile` | 空字符串 | PEM CA 文件,相对配置文件目录解析 | | `transport.tls.serverName` | `serverAddr` | TLS 服务名称 | | `transport.heartbeatInterval` | `30` | 心跳间隔,秒 | | `transport.heartbeatTimeout` | `90` | 心跳超时,秒,必须大于间隔 | | `transport.dialServerTimeout` | `10` | TCP 连接与 TLS 握手超时,秒 | `remotePort = 0` 时由服务端分配端口,注册成功日志会显示地址。可以配置多个 `[[proxies]]`。 没有配置 CA 时,证书处理与原版 frpc 默认行为一致,可连接使用自动生成证书的 frps。配置 `trustedCaFile` 后启用证书链和服务名称校验。TLS 提供者仅绑定隧道连接,不修改 JVM 全局 TLS 配置。 ## HTTP 与 TLS 的关系 HTTP 代理链路:浏览器 HTTPS → Nginx → frps 的 HTTP 虚拟主机端口 → Java 隧道 → 本地 HTTP 服务。TCP 代理则使用各自的远端端口作为入口。 网站证书由 Nginx 处理。本地服务继续接收普通 HTTP;隧道的 TLS 用于保护客户端到 frps 的连接,独立于网站 HTTPS。 ## 实现范围 已实现 FRP v1 消息协议、token 登录、控制消息加密、TCP/HTTP 代理、TLS、Yamux、心跳、自动重连和应用内关闭。重连采用 1~30 秒退避,重新登录并注册代理;已有业务连接会结束,新连接在恢复后继续工作。 当前支持 TCP 和 HTTP 类型代理。UDP、HTTPS 类型代理、STCP/XTCP、QUIC/KCP、OIDC、代理插件、代理级压缩/加密、双向 TLS 客户端证书、健康检查、限流、请求/响应头操作及 `routeByHTTPUser` 等尚未实现。配置中出现不支持的字段会明确拒绝启动,避免静默忽略配置。 接收缓冲、消息长度和工作连接数量均设有上限。Yamux 按接收消费进度更新窗口,并根据对端窗口控制发送。 ## 验证 默认构建运行配置和协议单元测试;原版 frps 互操作测试需显式提供本机可执行文件: ```shell mvn test -Dgpg.skip=true -Dfrp.test.frps=/path/to/frps ``` 互操作测试启动独立的本地 frps 实例,使用临时配置和端口,结束后关闭。覆盖 TLS 复用、TLS 非复用与自定义首字节、普通 TCP、2 MB 二进制上传下载、16 并发请求、心跳、服务端重启重连以及关闭后本地服务可继续访问。 HTTP 互操作测试额外覆盖子域名、自定义域名、路径优先级、Host 改写、Basic Auth、未注册域名和 HTTP 代理重连。详见 [测试与验收](./docs/05-testing.md)。 Windows 若遇到 NIO 临时套接字目录相关错误,可通过 JVM 参数 `-Djdk.net.unixdomain.tmpdir=D:\tmp` 指定已存在的短目录。