.NET 10 Native AOT 内网穿透工具,单个可执行文件(Windows 为 lumfrp.exe,Linux/macOS 为 lumfrp),用配置里的 mode 切换服务端或客户端。
A .NET 10 Native AOT reverse-tunnel tool: one executable (lumfrp.exe on Windows, lumfrp on Linux/macOS); server or client via mode in config.
设计思路参考 frp,控制面/数据面协议与官方 frp 不兼容,不能混用官方客户端或服务端。
Inspired by frp; wire protocol is not compatible with official frp binaries.
- 单文件发布,改
mode即可切换角色 / Single binary—flipmodefor server or client - TCP 穿透:HTTP、HTTPS、RDP、SSH、流式 API、gRPC 等 / TCP relay for HTTP, HTTPS, RDP, SSH, streaming APIs, gRPC, …
- UDP 穿透:每代理一条长期 work 连接,按公网源地址多包复用(frp 式架构)/ UDP: one persistent work conn per proxy, multiplexed by public source address (frp-style architecture)
- TCP 多路复用:一条 TLS 承载控制面与多条工作流 / TCP mux: one TLS conn for control + multiple work streams
- 强制 TLS,服务端无证书时自动自签 / TLS required; server auto-generates ephemeral cert if none configured
- 客户端默认只需相同
token,不用配证书 / Client only needs the sametokenby default—no cert setup allowPorts限制客户端可映射的远端端口 /allowPortsallowlist for remote ports- 配置有合理默认值,支持 JSON 注释与尾逗号 / Sensible defaults; JSON comments and trailing commas
- 可 Native AOT 发布(
PublishAot已开启)/ Native AOT publish enabled in project (PublishAot)
当前是中继模式(流量经服务端),没有 P2P 打洞。TCP 和 UDP 都按 proxies[].type 选配,可以只开一种,也可以同时开。
Relay-only today (traffic goes through the server); no P2P hole punching. Pick TCP and/or UDP per proxy via proxies[].type.
源码里注释比较全(以中文为主),看三类标记就够用:数据流(ASCII 图)、策略(池、重连、白名单、鉴权、心跳)、字段(关键变量干什么、谁读写)。
Comments are teaching-oriented (mostly Chinese). Watch for data-flow diagrams, policy notes, and field-level explanations.
建议顺序:Program.cs → Hosting → Messages → Protocol → ServerService / ServerControlSession → ClientService → Proxies.Tcp → Proxies.Udp。
Same path: Program.cs → Hosting → Messages → Protocol → server/client services → Proxies.Tcp / Proxies.Udp.
要加新代理类型:实现 I*Proxy + Factory,在 Hosting 注册即可,一般不用动 Server/Client 主循环。
New proxy type: implement I*Proxy + factory, register in Hosting—usually no changes to the main loops.
dotnet publish src/lumfrp -c Release -r win-x64 -o artifacts/lumfrp
cd artifacts/lumfrp
# 编辑同目录 lumfrp.json(发布时会复制到输出目录)/ edit lumfrp.json (copied on publish)
lumfrp.exe
lumfrp.exe -c other.json # 指定配置 / custom config pathLinux/macOS 把 -r win-x64 换成对应 RID(如 linux-x64、osx-arm64)。
On Linux/macOS, use the matching RID instead of win-x64.
源码基于 .NET 标准库(TCP/UDP/TLS),没有绑定 Windows API,设计上可在 Windows、Linux、macOS 运行。
The code uses .NET BCL only (TCP/UDP/TLS)—no Windows-specific APIs—so it is intended to run on Windows, Linux, and macOS.
两种发布方式 / two publish modes
| 方式 Mode | 命令示例 Example | 说明 Notes |
|---|---|---|
| 依赖运行时 Framework-dependent | dotnet publish src/lumfrp -c Release -o ./out(不带 -r) |
目标机需安装 .NET 10 运行时 / requires .NET 10 runtime on target |
| Native AOT | dotnet publish … -r linux-x64 等 |
单文件、无运行时;必须在目标 OS 上编译 / self-contained; must publish on the target OS |
Native AOT 不支持跨 OS 交叉编译(例如在 Windows 上 -r linux-x64 会失败)。在 Linux 服务器上要在 Linux 里 publish,macOS 同理。
Native AOT cannot cross-compile (e.g. -r linux-x64 on Windows fails). Publish on Linux for Linux, on macOS for macOS.
各平台 RID 参考 / common RIDs
# Windows
dotnet publish src/lumfrp -c Release -r win-x64 -o ./out
# Linux (x64)
dotnet publish src/lumfrp -c Release -r linux-x64 -o ./out
# macOS (Apple Silicon)
dotnet publish src/lumfrp -c Release -r osx-arm64 -o ./out
# macOS (Intel)
dotnet publish src/lumfrp -c Release -r osx-x64 -o ./out发布后:./out/lumfrp(Unix)或 out\lumfrp.exe(Windows),同目录放好 lumfrp.json 即可。
After publish: run ./out/lumfrp (Unix) or out\lumfrp.exe (Windows) with lumfrp.json beside the binary.
使用注意 / caveats
- 当前集成测试主要在 Windows 上跑通;Linux/macOS 建议在目标环境自行
dotnet test或实测一遍。
Integration tests are run primarily on Windows; validate on Linux/macOS in your environment. - 传输层目前为 IPv4(
InterNetwork);纯 IPv6 地址暂不支持。
Transport is IPv4 today (InterNetwork); pure IPv6 endpoints are not supported yet. - Linux/macOS 监听 1024 以下端口 通常需要 root 或
cap_net_bind_service。
Binding ports below 1024 on Linux/macOS usually needs root orcap_net_bind_service.
未指定 -c 时,默认读取 与 exe 同目录 的 lumfrp.json(AppContext.BaseDirectory);模板见 src/lumfrp/lumfrp.json。
Without -c, reads lumfrp.json next to the executable (AppContext.BaseDirectory); template: src/lumfrp/lumfrp.json.
{
"mode": "server",
"auth": { "token": "your-secret" }
}{
"mode": "client",
"auth": { "token": "your-secret" },
"serverAddr": "public-ip-or-hostname",
"proxies": [
{
"name": "rdp",
"type": "tcp",
"localIp": "127.0.0.1",
"localPort": 3389,
"remotePort": 13389
},
{
"name": "dns",
"type": "udp",
"localIp": "127.0.0.1",
"localPort": 53,
"remotePort": 5353
}
]
}type 不写时默认 tcp;localIp 不写时默认 127.0.0.1。可以只配 TCP、只配 UDP,或两个都要。
type defaults to tcp; localIp defaults to 127.0.0.1. TCP only, UDP only, or both.
remotePort 别和云主机上已有端口撞车(比如系统自带的 3389)。
Keep remotePort away from ports already in use on the server (e.g. system 3389).
RDP 示例:mstsc /v:公网IP:13389 · Example: mstsc /v:PUBLIC_IP:13389
不配就是不限制;配了之后,客户端的 remotePort 必须在范围内,否则注册失败并提示原因。
Omit for no restriction; when set, remotePort must be allowed or registration fails with an error.
"allowPorts": "8000/9000"也支持 / also:
"allowPorts": "8000/9000,8030,10000-10010"
"allowPorts": ["8000/9000", "8030"]
"allowPorts": [{ "start": 8000, "end": 9000 }]"8000/9000"或"8000-9000"→ 8000–9000"8030"→ 仅 8030 / port 8030 only- 逗号分隔 → 多个区间或端口 / comma-separated ranges or ports
| 字段 Field | 默认 Default | 说明 Notes |
|---|---|---|
bindPort |
7000 | 服务端控制端口,安全组要放行 / server control port—open in firewall |
bindAddress |
0.0.0.0 |
服务端监听地址 / server bind address |
serverPort |
7000 | 客户端连服务端的端口 / client → server port |
poolCount |
5 | 客户端预建工作连接数(受服务端 maxPoolCount 限制)/ client work-conn pool (capped by server maxPoolCount) |
transport.tcpMux |
true | 控制面与工作流多路复用;可设为 false / mux control + work on one TLS conn; can disable |
transport.tls.fingerprintSha256 |
(空) | 客户端钉扎服务端证书 SHA256;配置后开启严格校验 / client cert pin; enables strict verify |
transport.tls.trustedCaFile |
(空) | 客户端自定义 CA;配置后开启严格校验 / client custom CA; enables strict verify |
transport.tls.certFile / keyFile |
(空) | 服务端固定证书(PEM 或无密码 PFX)/ server cert (PEM or passwordless PFX) |
heartbeatIntervalSeconds |
30 | 客户端 Ping 间隔 / client ping interval |
heartbeatTimeoutSeconds |
90 | 服务端踢掉僵死会话 / server session sweep timeout |
maxProxiesPerClient |
50 | 每客户端最多代理数 / max proxies per client |
maxPoolCount |
10 | 工作连接池上限 / max work-conn pool size |
TLS 运行时强制开启(transport.tls.enable / force 会被覆盖为 true)。默认仍加密,但客户端不校验证书(方便临时自签);公网部署建议开启校验以防中间人。
TLS is always on (enable / force forced to true). By default traffic is encrypted but the client does not verify the server cert (ephemeral self-signed UX); enable verification on public networks to stop MitM.
配置了 fingerprintSha256 或 trustedCaFile 后,运行时会自动关闭 allowInsecure,开始严格校验。无需再手写 allowInsecure: false。
Setting either field turns off allowInsecure automatically—no need to set allowInsecure: false yourself.
方式一:指纹钉扎 Fingerprint pin(临时自签最简单)
- 启动服务端,日志中有
fingerprint=.../ start server; copyfingerprint=from logs - 客户端写入同一指纹 / put it on the client:
"transport": {
"tls": {
"fingerprintSha256": "服务端日志里的SHA256十六进制"
}
}临时自签证书每次进程重启都会变,指纹需同步更新。长期运行请用方式二。
Ephemeral certs change every restart—update the pin, or use method 2 for production.
方式二:固定证书 + CA Fixed cert + CA(推荐生产)
服务端 Server(PEM):
"transport": {
"tls": {
"certFile": "server.crt",
"keyFile": "server.key"
}
}客户端 Client(信任签发该证书的 CA):
"transport": {
"tls": {
"trustedCaFile": "ca.crt"
}
}路径可为相对运行目录(与 exe 同目录)或绝对路径。certFile 也可为无密码的 PFX(此时可不配 keyFile)。
Paths may be relative to the working/exe directory or absolute. certFile can also be a passwordless PFX (omit keyFile).
示例注释见 src/lumfrp/lumfrp.json。
Commented examples: src/lumfrp/lumfrp.json.
配置错了会打印带错误码和文件路径的提示块。
Config errors print a block with error code and file path.
dotnet run --project src/lumfrp
dotnet test集成测试在本机 loopback 拉起真实 Server+Client,默认 TLS + Mux,覆盖 TCP 透传、HTTP/SSE、UDP 多包与多用户、TCP+UDP 共存等(另有 tcpMux: false 用例)。
Integration tests use real server+client on loopback, TLS + mux by default; also includes a tcpMux: false case.