← 返回文章列表

自建内网穿透:frp 从 ini 迁到 TOML 的配置笔记

场景很常见:家里或办公室有一台跑着内部服务的机器,需要在外面访问;但它没有公网 IP, 路由器也不在自己手里。买一台最便宜的云服务器做中转,用 frp 打通,是最省事的方案。

这套东西我用了很久,中间因为升级版本翻过一次车——配置文件格式从 ini 改成了 TOML, 旧配置直接启动失败。趁这次迁移把整份配置重新捋了一遍,记下来省得下次再查。

一、结构:两端各一个进程

frp 由两部分组成:frps 跑在有公网 IP 的服务器上,frpc 跑在内网机器上。 frpc 主动向 frps 建立长连接,把内网端口"映射"到服务器上,外部访问服务器端口就等于访问内网服务。 NAT 和防火墙的问题就此绕过——因为它从来不需要外部主动连进来。

外部用户 → (公网 IP:8080) → frps → 加密隧道 → frpc → (内网 127.0.0.1:8000)

二、新旧配置格式对照

v0.52 之后 frp 用 TOML 取代了 ini。老配置长这样:

# frpc.ini(旧格式,已废弃)
[common]
server_addr = 1.2.3.4
server_port = 7000
token = your_token

[web]
type = tcp
local_ip = 127.0.0.1
local_port = 8000
remote_port = 8080

新格式把"公共段"和"代理段"拆成了两处:公共配置写在文件顶层, 每个代理用一个 [[proxies]] 数组项表示。

# frpc.toml
serverAddr = "1.2.3.4"
serverPort = 7000
auth.method = "token"
auth.token = "your_token"
log.level = "info"

[[proxies]]
name = "web"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8000
remotePort = 8080

服务端同样变了。老版本是 [common] 里写 bind_port, 现在是顶层字段:

# frps.toml
bindPort = 7000
auth.method = "token"
auth.token = "your_token"

# 面板:只监听本地,通过 SSH 隧道访问,不要直接暴露公网
webServer.addr = "127.0.0.1"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "change_me"

迁移时最常见的报错是 parse config error。八成是还在用 ini 语法—— 注意 TOML 里字符串必须带引号,localPort = 8000 不能写成 "8000"(虽然能解析,但类型不对会报警告)。

三、端口规划:别随手挑

端口冲突是最容易浪费时间的问题。我现在固定一套规划,写进注释里:

端口用途暴露范围
7000frps 控制端口公网(限制来源 IP 更好)
7500frps 管理面板仅本地 127.0.0.1
8080映射出去的内网 Web 服务公网
6000SSH 映射(应急用)公网,建议改非默认端口

云服务器还有一层安全组,端口开了服务还得在控制台放行,这一步经常被忘。 判断方法很简单:服务器上 ss -lntp | grep 8080 有监听、本地 curl 127.0.0.1:8080 通, 但从外面连不上,那基本就是安全组的问题。

四、鉴权与加密:别裸奔

公网上的 frps 控制端口会被扫描。至少做三件事:

  • 开 token 鉴权。 就是上面配置里的 auth.token,两端必须一致。用长随机串,别用 123456。
  • 限制控制端口来源。 如果内网出口 IP 固定,直接在安全组里只放行那个 IP。
  • Web 服务套 HTTPS。 frp 只做端口转发,不负责加密业务流量。让 Nginx 在前面终止 TLS,或者用 frp 自带的 https 类型代理。

还有一个容易忽略的点:管理面板千万不要暴露在公网。默认账号密码 + 公网可达 = 别人能看到你所有隧道的状态。 我把它绑在 127.0.0.1,需要时用 SSH 端口转发过去看。

五、开机自启:systemd 比 nohup 靠谱

用 nohup ./frpc -c frpc.toml & 启动的进程,机器一重启就没了,而且挂了没人拉起来。 写个 systemd 单元,省心得多:

# /etc/systemd/system/frpc.service
[Unit]
Description=frp client
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/usr/local/bin/frpc -c /etc/frp/frpc.toml
Restart=always
RestartSec=5
LimitNOFILE=1048576

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now frpc
systemctl status frpc --no-pager

Server=always 加 RestartSec=5 是关键:网络抖动导致隧道断开时,进程会自己回来。 服务端同样处理,把 frpc 换成 frps 即可。

六、排错顺序

连不上时按这个顺序查,基本能在五分钟内定位:

  1. frps 有没有起来:systemctl status frps,看日志里有没有 start frps success。
  2. frpc 有没有连上:frpc 日志出现 login to server success 才算通,出现 connect to server error 就是网络或端口问题。
  3. 隧道有没有建起来:日志里每个代理会打印 start proxy success,没有就说明 remotePort 被占用或权限不足。
  4. 安全组放行了吗:云控制台单独检查,这一步最容易漏。
  5. 内网服务本身活着吗:在 frpc 那台机器上 curl 127.0.0.1:8000,先确认本地通。

这五步覆盖了我遇到过的所有情况。绝大多数"连不上"不是 frp 的问题,而是安全组或者内网服务本身挂了。

七、小结

frp 是个典型的"配置对了就永远不操心"的工具。真正需要花心思的不是它的功能,而是三件事: 端口规划要留文档、token 要随机、管理面板不要暴露。前两件是给自己省事,最后一件是给自己省麻烦。

另外,升级前务必备份旧配置并看一眼 changelog。我那次翻车就是因为直接 apt upgrade 完重启, 结果服务起不来,半夜在服务器上翻文档。现在我的习惯是:升级前 cp frpc.ini frpc.ini.bak, 并且先在测试机上跑一遍。