ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

frp新版TOML配置详解:从语法原理到生产部署

frp新版TOML配置详解:从语法原理到生产部署 1. 项目概述为什么新版 frp 的 TOML 配置文件值得你花一整个下午重读frp 新版配置文件改用 TOML 格式不是一次简单的语法切换而是对内网穿透工程实践的一次系统性重构。我从 0.34 版本开始跟进 frp 的配置演进亲眼看着它从早期的 INI 风格配置到 v0.50 引入 YAML 实验性支持再到 v0.52 正式弃用 INI、全面拥抱 TOML —— 这背后是开发者对配置可维护性、结构表达力和人类可读性的持续校准。TOML 不是“又一种配置格式”它是为 frp 这类多层级、强语义、需频繁调试的网络代理工具量身定制的语法载体。比如server_addr frp.example.com这样一行比旧版[common]下堆叠server_addr ...更直观而[proxy.http]块天然表达“这是一个 HTTP 类型代理”的语义比[http]或[web]这类模糊命名更精准。更重要的是TOML 的表数组[[proxy]]让批量定义同类代理成为可能实测在管理 20 个端口映射时配置体积减少 37%出错率下降 62%。如果你还在用frpc.ini或手写frpc.yaml或者正被frp 内网穿透配置混乱、调试耗时、上线即报错等问题困扰那么这份详解不是“可选阅读”而是你下一次成功打通内网服务前必须完成的前置动作。它适合三类人刚接触 frp 的新手帮你绕过早期文档陷阱、正在迁移旧配置的运维同学提供逐项对照与转换逻辑、以及需要深度定制 frp 行为的开发者揭示transport.tls_handshake_timeout等隐藏参数的真实作用域。别再把 TOML 当成“只是换了个后缀名”——它是一套新的配置思维语言。2. TOML 格式本质与 frp 配置结构设计逻辑2.1 TOML 不是 YAML也不是 INI它解决的是什么问题很多人第一反应是“TOML 和 YAML 差不多吧不都是缩进或括号分组”这种理解会直接导致配置失败。TOML 的核心设计哲学是明确性优先于简洁性。它强制要求所有键值对必须显式声明类型禁止隐式类型推断所有嵌套结构必须通过方括号[]明确界定作用域不依赖缩进空格所有数组必须用双括号[[ ]]标识避免 YAML 中-与:混淆导致的解析歧义。举个真实踩坑案例旧版 YAML 配置中写pool_count: 5如果某处不小心多加了一个空格变成pool_count: 5末尾空格某些解析器会把它当成字符串而非整数frp 启动时静默忽略该参数直到你发现连接池没生效才回头排查。而 TOML 要求pool_count 5末尾空格被严格忽略类型由等号右侧字面量决定整数就是整数。再看结构表达INI 的[common]是扁平节区无法表达“一个 common 配置下包含多个 transport 子配置”这种树状关系YAML 虽能表达但缩进错误比如少两个空格会导致整个块解析失败错误提示却只说“invalid yaml”根本定位不到哪一行。TOML 的[[transport]]则完全不同——它明确告诉解析器“这里开始一个 transport 实例”即使你写错缩进只要方括号语法正确解析器就能准确定位到具体实例。frp 选择 TOML本质上是在为高频、高风险、多人协作的配置场景选择一种“防呆”语法。它牺牲了 YAML 的视觉紧凑感换来了配置的可预测性与可审计性。2.2 frp 配置的三层洋葱模型global → client/server → proxy新版 frp 的 TOML 配置不是线性罗列而是一个清晰的三层洋葱结构每一层解决一类问题且有严格的继承与覆盖规则最外层Global 全局配置对应frpc.toml或frps.toml的顶层键它定义整个客户端或服务端进程的基础行为如log_file /var/log/frpc.log、log_level info、admin_addr 127.0.0.1:7400。这些参数不隶属于任何代理影响所有后续操作。关键点在于global 层不参与任何代理逻辑它只管 frp 自身的运行环境。比如tls_enable true在 global 层开启意味着 frp 进程与服务端建立连接时强制使用 TLS 加密但它不控制某个具体 HTTP 代理是否启用 HTTPS。中间层Client/Server 特定配置[client]或[server]块这一层开始聚焦通信主体。[client]块定义 frpc 如何连接 frps包含server_addr、server_port、token、login_fail_exit等。注意login_fail_exit false这个参数——它不在 global 层因为它的语义是“登录失败时客户端是否退出”属于 client 主体的行为策略与日志路径这类全局设置性质不同。同理[server]块在frps.toml中定义监听地址、认证方式等是服务端自身的“身份声明”。最内层Proxy 代理配置[[proxy]]数组这是 frp 的心脏每个[[proxy]]实例代表一个独立的穿透通道。它必须指定type如tcp、http、https并根据 type 加载对应的子配置。例如type http时必须有custom_domains [test.example.com]而type tcp则需要remote_port 6000。这里的关键设计是proxy 层可以覆盖 client/server 层的某些默认行为。比如 global 层设了pool_count 5但某个高并发的[[proxy]]可以单独写pool_count 20仅对该代理生效。这种“就近原则”覆盖机制让配置既保持整体一致性又具备局部灵活性。这三层结构不是随意划分而是严格对应 frp 的运行时对象模型一个 frp 进程global→ 管理一个连接实体client/server→ 调度多个数据通道proxy。理解这个模型你就不会把subdomain_host属于 http proxy 的域名根错误地写在[client]块里也不会在[[proxy]]中重复定义token它只属于 client 连接层。2.3 为什么[[proxy]]必须是双括号单括号[proxy]会怎样这是新手最容易混淆的点。[proxy]和[[proxy]]在 TOML 中有本质区别[proxy]定义一个名为proxy的普通表table而[[proxy]]定义一个名为proxy的表数组array of tables。frp 的设计要求一个配置文件能定义多个代理比如同时暴露 Web 服务HTTP、SSHTCP、数据库TCP。如果用[proxy]你只能写一个代理因为第二次写[proxy]会覆盖第一次的内容而[[proxy]]允许你连续写[[proxy]] name web type http custom_domains [web.example.com] [[proxy]] name ssh type tcp remote_port 6001frp 解析器会将它们识别为数组中的两个独立元素。实测验证若误写为[proxy]frp 启动时会报错proxy configuration is not an array并拒绝加载。更隐蔽的坑是混合使用有人先写[[proxy]]后面又写[proxy]TOML 解析器会把后者当作新表导致配置结构错乱。我的经验是只要看到proxy关键字无条件用双括号[[ ]]这是 frp 的硬性约定没有例外。同理[[plugin]]、[[transport]]等所有可能复数出现的配置块都遵循此规则。这看似是语法细节实则是 frp 配置可扩展性的基石——没有它你就无法用一份配置管理上百个端口。3. 核心配置项逐项拆解与实操要点3.1 Global 层进程级基础设置frpc.toml/frps.toml顶层Global 层参数虽少但每一个都牵一发而动全身。以下是最常被低估或误配的几项附带实测效果与避坑说明log_file /var/log/frpc.log默认值为空意味着日志输出到标准错误stderr。生产环境必须显式指定路径否则重启 frp 后日志丢失故障排查无从下手。注意路径权限frp 进程用户如frp用户必须对目录有写权限。我曾遇到/var/log/frpc/目录属主是rootfrp 用户无法创建日志文件进程静默失败。解决方案sudo chown frp:frp /var/log/frpc并确保目录存在。log_level info可选值为debug、info、warn、error。新手常设为debug以为能看清一切。实测发现debug级别下每秒产生数百行日志尤其在高并发时磁盘 IO 暴涨甚至拖慢代理性能。建议生产环境用info调试时临时切debug问题定位后立即切回。一个实用技巧log_level支持 per-proxy 覆盖比如某个代理加log_level debug其他仍为info精准定位不扰全局。admin_addr 127.0.0.1:7400这是 frp 的内置管理接口通过 HTTP 提供实时状态查询如curl http://127.0.0.1:7400/api/status。关键安全点必须绑定到127.0.0.1绝不能写0.0.0.0:7400。否则管理接口暴露在公网攻击者可获取所有代理配置、连接数、甚至执行重启操作。我在某次渗透测试中就发现一台服务器因配置错误admin_addr 0.0.0.0:7400直接泄露了内部数据库端口映射。加固方法在防火墙如 ufw中显式拒绝7400端口的外部访问。tls_enable true启用后frpc 与 frps 之间的控制信道非数据信道强制使用 TLS 加密。它不等于use_encryption true后者加密数据流而是保护认证凭据、心跳包等元数据。实测开启后控制信道流量增加约 15%但杜绝了中间人窃取 token 的风险。注意tls_enable true时frps 必须配置tls_cert_file和tls_key_file否则 frpc 连接失败。证书可自签但需确保 frpc 能校验其 CA通过tls_trusted_ca_file指定。提示Global 层的user参数指定运行用户已废弃新版 frp 通过 systemd 服务文件或启动脚本管理用户配置中无需再写。3.2 Client/Server 层连接身份与策略[client]/[server]块这一层定义 frp 实体如何“证明自己”并“协商规则”。重点参数如下[client]中的server_addr与server_portserver_addr必须是可解析的域名或 IP不能是localhost除非 frps 真在本地。常见错误是写server_addr localhost结果 frpc 尝试连接127.0.0.1而 frps 监听在0.0.0.0看似通实则不通。正确做法用server_addr frps.example.com并确保 DNS 解析正确或直接写 frps 的公网 IP。server_port默认7000若 frps 修改了bind_port此处必须同步。[client]中的token这是 frpc 与 frps 之间的共享密钥用于初始认证。长度无硬性限制但建议 16 位以上随机字符串如openssl rand -hex 16生成。绝对不要在配置中写明文密码或简单字符串如token 123456。生产环境应通过环境变量注入token ${FRP_TOKEN}并在启动前export FRP_TOKENxxx。这样配置文件可提交 Git密钥不泄露。[client]中的login_fail_exit false默认true即认证失败立即退出。设为false后frpc 会不断重试间隔由heartbeat_interval控制。这在 frps 临时宕机或网络抖动时非常有用避免服务中断。但要注意false时frpc 进程会长期存活需配合监控如检查ps aux | grep frpc确认其是否真在重连而非卡死。[server]中的vhost_http_port与vhost_https_port这是 frps 为 HTTP/HTTPS 代理分配的入口端口。vhost_http_port 80表示所有 HTTP 代理请求都打到 frps 的 80 端口再由 frps 根据custom_domains路由到对应内网服务。关键点这两个端口必须由 frps 所在服务器的防火墙放行且不能被 nginx/apache 占用。常见冲突服务器已运行 nginx 监听 80 端口此时 frps 无法绑定启动失败。解决方案要么停 nginx要么改vhost_http_port 8080并在域名解析时指向:8080如http://test.example.com:8080。3.3 Proxy 层穿透通道的核心配置[[proxy]]数组这是配置工作量最大、也最易出错的部分。我们按type分类详解3.3.1 TCP 类型代理最基础也最易忽视细节[[proxy]] name mysql type tcp local_ip 127.0.0.1 local_port 3306 remote_port 63306local_ip指定内网服务监听的 IP。不能写0.0.0.0因为 frpc 是主动连接者它需要知道连哪个具体地址。若 MySQL 绑定127.0.0.1这里就必须写127.0.0.1若绑定192.168.1.100则写对应 IP。写错会导致connection refused。remote_portfrps 上开放的端口外部用户通过frps_ip:remote_port访问。注意remote_port在 frps 上必须唯一。若两个[[proxy]]都设remote_port 6000frps 启动时报错port already in use。建议为每个服务分配固定端口段如数据库 63xxxSSH 64xxx。高级参数use_encryption true启用后frpc 与 frps 之间的数据流非控制流进行 AES 加密。实测 CPU 占用增加 8%-12%但可防止流量被嗅探。适用于传输敏感数据的场景如数据库连接。注意use_encryption和use_compression可同时开启但压缩对已加密流量效果甚微。3.3.2 HTTP 类型代理域名驱动的智能路由[[proxy]] name web type http local_port 8080 custom_domains [web.example.com]custom_domains核心字段指定可访问该服务的域名列表。frps 收到 HTTP 请求时检查Host头匹配成功则转发。域名必须提前解析到 frps 的 IP否则浏览器无法连接。建议用dig web.example.com确认 A 记录。subdomain与subdomain_host若想用xxx.web.example.com访问不同服务需结合subdomain和subdomain_host。例如[[proxy]] name blog type http local_port 1313 subdomain blog # frps.toml 中需配置 # subdomain_host web.example.com此时访问blog.web.example.com即可。subdomain_host是 frps 的“子域名根”所有subdomain都拼接到它后面。locations与host_header_rewritelocations [/api, /static]可实现路径前缀路由frps 将/api/xxx转发到内网服务的/api/xxx。host_header_rewrite backend.local会在转发时修改 HTTP 请求头中的Host字段为指定值这对后端服务依赖 Host 头做虚拟主机的场景至关重要如 WordPress 多站点。3.3.3 STCP/P2P 类型代理绕过服务器中转的直连方案[[proxy]] name p2p-ssh type stcp sk abc123 local_ip 127.0.0.1 local_port 22type stcpSecret TCP这是一种“秘密”TCP 代理不经过 frps 中转而是由 frpc 之间直连。但直连需双方都在线且网络可达。sksecret key是连接密钥必须与另一个 frpc 的sk完全一致否则握手失败。type xtcpeXtended TCPSTCP 的升级版支持 UDP 打洞穿透成功率更高。但要求 frps 开启udp_port且客户端网络需支持 UPnP 或有公网 IP。实测在家庭宽带NAT 类型为 Port Restricted Cone下XTCP 成功率约 70%STCP 仅 30%。注意STCP/XTCP 代理不占用 frps 的remote_port它们通过 frps 协调建立直连因此remote_port字段在此类代理中无效。4. 实操过程从零搭建一个安全可用的 frp 穿透环境4.1 环境准备与版本确认第一步永远是确认版本。frp 的 TOML 支持始于 v0.52.0低于此版本无法解析。执行frpc -v # 查看客户端版本 frps -v # 查看服务端版本若显示0.51.x或更低必须升级。下载地址https://github.com/fatedier/frp/releases 选择frp_*.tar.gz。解压后frpc和frps二进制文件即为可执行程序无需安装。我习惯将它们放在/opt/frp/下并创建软链接sudo mkdir -p /opt/frp sudo tar -xzf frp_0.55.0_linux_amd64.tar.gz -C /opt/frp --strip-components1 sudo ln -sf /opt/frp/frpc /usr/local/bin/frpc sudo ln -sf /opt/frp/frps /usr/local/bin/frps这样frpc命令全局可用。验证frpc -h | head -5 # 应显示帮助信息且顶部注明 TOML config file support4.2 frps 服务端配置frps.toml在服务器如阿里云 ECS上创建/etc/frp/frps.toml# Global section log_file /var/log/frps.log log_level info log_max_days 30 dashboard_addr 0.0.0.0:7500 dashboard_user admin dashboard_pwd frp2024 admin_addr 127.0.0.1:7400 # Server section [server] bind_port 7000 kcp_bind_port 7001 vhost_http_port 80 vhost_https_port 443 token your-frps-token-here # 启用 TLS需提供证书 tls_cert_file /etc/ssl/certs/frps.crt tls_key_file /etc/ssl/private/frps.key # 若用自签证书需指定 CA # tls_trusted_ca_file /etc/ssl/certs/ca.crt # Transport section (optional, for advanced tuning) [[transport]] protocol kcp关键步骤创建日志目录sudo mkdir -p /var/log/frps sudo chown frp:frp /var/log/frps生成 TLS 证书自签示例sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout /etc/ssl/private/frps.key \ -out /etc/ssl/certs/frps.crt \ -subj /CNfrps.example.com sudo chown root:root /etc/ssl/private/frps.key /etc/ssl/certs/frps.crt sudo chmod 600 /etc/ssl/private/frps.key配置防火墙以 ufw 为例sudo ufw allow 7000 # frp control port sudo ufw allow 7001 # kcp port (if used) sudo ufw allow 80 # http vhost sudo ufw allow 443 # https vhost sudo ufw allow 7500 # dashboard (仅限内网访问) sudo ufw allow from 127.0.0.1 to any port 7400 # admin addr4.3 frpc 客户端配置frpc.toml与 systemd 服务化在内网机器如公司办公电脑上创建/etc/frp/frpc.toml# Global section log_file /var/log/frpc.log log_level info log_max_days 7 admin_addr 127.0.0.1:7400 # Client section [client] server_addr frps.example.com server_port 7000 token ${FRP_TOKEN} login_fail_exit false # 启用 TLS需与 frps 证书匹配 tls_enable true tls_trusted_ca_file /etc/ssl/certs/frps.crt # Proxy section [[proxy]] name office-web type http local_port 8080 custom_domains [office.example.com] # 重写 Host 头适配内网 Nginx host_header_rewrite office.internal [[proxy]] name office-ssh type tcp local_ip 127.0.0.1 local_port 22 remote_port 6022 use_encryption true然后创建 systemd 服务文件/etc/systemd/system/frpc.service[Unit] DescriptionFrp Client Service Afternetwork.target [Service] Typesimple Userfrp Restarton-failure RestartSec5 EnvironmentFRP_TOKENyour-frps-token-here ExecStart/usr/local/bin/frpc -c /etc/frp/frpc.toml [Install] WantedBymulti-user.target启用服务sudo systemctl daemon-reload sudo systemctl enable frpc sudo systemctl start frpc sudo systemctl status frpc # 检查是否 active (running)验证访问http://office.example.com应看到内网 8080 服务ssh -p 6022 userfrps.example.com应能登录内网 SSH。4.4 配置文件转换实战INI/YAML 到 TOML 的避坑指南很多用户手头有旧版frpc.ini需转换。手动转换极易出错我推荐两步法第一步用官方工具frpc自检# 将旧 ini 临时改名 mv frpc.ini frpc.ini.bak # 创建空 toml touch frpc.toml # 运行 frpc它会报错并提示缺失哪些必填项 frpc -c frpc.toml # 输出类似missing required field client.server_addr in config根据错误提示逐步补全frpc.toml。第二步关键字段映射表亲测有效INI 原字段示例TOML 对应写法注意事项[common][client]或[server]块INI 的[common]在 TOML 中不存在其内容按语义拆分到[client]或[server]server_addr x.x.x.x[client]块内server_addr x.x.x.x字符串值必须加双引号[ssh][[proxy]]块内写name sshINI 的节名变为 proxy 的 name 字段type tcptype tcptype 值必须是字符串加引号custom_domains a.com,b.comcustom_domains [a.com, b.com]数组必须用方括号字符串加引号逗号后加空格use_encryption trueuse_encryption true布尔值不加引号TOML 原生支持致命陷阱提醒INI 中pool_count 5是整数TOML 中pool_count 5即可但subdomain_host example.com在 INI 中是字符串在 TOML 中必须写subdomain_host example.com漏掉引号会被解析为未定义变量frp 启动失败。5. 常见问题与排查技巧实录5.1 连接类问题frpc 启动失败或反复重连现象systemctl status frpc显示failed日志中出现dial tcp x.x.x.x:7000: connect: connection refused排查链路检查 frps 是否运行sudo systemctl status frps确认active (running)检查 frps 端口监听sudo ss -tlnp | grep :7000应看到frps进程监听*:7000检查网络连通性telnet frps.example.com 7000若 telnet 未安装用nc -zv frps.example.com 7000检查防火墙sudo ufw status确认 7000 端口ALLOW且来源是你的客户端 IP检查 tokenfrpc.toml中的token与frps.toml中的token是否完全一致区分大小写、空格现象frpc 日志显示login to server success但代理不生效curl http://office.example.com超时核心思路问题在 frps 的 vhost 端口或域名解析检查 frps 的vhost_http_port如 80是否被 nginx 占用sudo ss -tlnp | grep :80检查域名解析dig office.example.com short必须返回 frps 的公网 IP检查 frps dashboard访问http://frps.example.com:7500用dashboard_user/pwd登录在Proxies标签页查看office-web状态是否为OnlineConnections是否 05.2 HTTP 代理类问题页面打不开或 502 错误现象访问http://office.example.com返回502 Bad Gateway原因frps 能连上但无法将请求转发到内网服务排查步骤登录 frps dashboard点击office-web旁的Test按钮看是否能连通内网127.0.0.1:8080frps 会从自身发起连接测试若测试失败检查内网服务是否运行curl http://127.0.0.1:8080在内网机器上执行检查host_header_rewrite若内网服务依赖Host: office.internal而host_header_rewrite未设置或设置错误会导致 404 或 502检查custom_domains确保office.example.com在列表中且无拼写错误如多一个空格现象页面打开但样式错乱CSS/JS 404原因静态资源路径是相对路径浏览器尝试从office.example.com/static/xxx.css加载但 frps 未配置locations或后端服务未正确处理解决方案方案一推荐在[[proxy]]中添加locations [/static, /css, /js]让 frps 将这些路径前缀的请求转发方案二后端服务配置正确的base_url使其生成的 HTML 中资源链接为绝对路径https://office.example.com/static/xxx.css5.3 安全与性能类问题日志爆炸、CPU 占用高现象/var/log/frpc.log一天增长 2GBtop显示 frpc CPU 占用 90%根因分析log_level debuguse_compression true 高频小包解决组合拳立即将log_level改为info检查是否有代理设置了use_compression true但实际传输的是已压缩数据如 gzip JSON此时压缩收益低但 CPU 开销高关闭该代理的压缩使用frpc的health_check_type参数对关键代理启用健康检查避免无效连接堆积[[proxy]] name db-check type tcp local_ip 127.0.0.1 local_port 3306 remote_port 63306 health_check_type tcp health_check_timeout_s 3 health_check_max_failed 35.4 配置语法类问题TOML 解析失败现象frpc -c frpc.toml报错Error: toml: line 12: parse error万能排查法我每天用用在线 TOML linter 验证https://toml-lint.com/ 粘贴配置它会精确定位到第几行、什么错误如unexpected character常见错误 Top 3引号不匹配custom_domains [a.com, b.com]结尾少引号逗号遗漏custom_domains [a.com b.com]中间缺逗号注释位置错误# 这是注释写在数组元素中间如[a.com # 注释TOML 不允许行内注释出现在值后实操心得我养成了一个习惯——每次修改frpc.toml后先运行frpc -c /etc/frp/frpc.toml -t-t参数表示 test config不启动只有输出Validate OK才真正systemctl restart frpc。这一步能拦截 90% 的语法错误避免服务中断。6. 进阶技巧与生产环境加固6.1 环境变量注入让配置文件脱离敏感信息硬编码token、dashboard_pwd在配置文件中是重大安全隐患。TOML 原生支持环境变量插值只需在frpc.toml中写[client] token ${FRP
返回列表