☰
frp 内网穿透配置指南与常见错误排查全解析
2026/10/1 18:49:00 网站建设 项目流程

frp 应该算是我日常折腾服务器时用得最频繁的内网穿透工具,没有之一。它的用途非常直接:一台机器在内网里,没有公网地址,外部网络访问不到,那就用另一台有公网地址的服务器做中转,把内网端口“映射”出去,让外部网络能通过公网服务器访问到内网服务。frp 配置看着不复杂,核心就两个配置文件,一个跑在有公网地址的服务器上,一个跑在内网机器上,但真正花时间的地方几乎都在常见错误排查上——token 对不上、端口被占用、安全组没放行、systemd 起不来、日志里反复出现 EOF 或 connection refused。这篇文章我把 frp 配置和 frp 常见错误放在一起梳理一遍,既能当新手快速上手的文档,也能当排查问题时的参考手册。

1. 先把 frp 的原理和应用场景讲清楚

1.1 frp 到底解决的是一个什么问题

frp 解决的本质上是一个“内网可达性”的问题。假设你在办公室有一台开发机,家里还有一台 NAS,它们只有内网地址,外面的人从公网直接访问不到;而你恰好有一台带公网地址的云服务器,这时候 frp 就能在两者之间搭一条专用的转发通道。外人访问公网服务器的某个端口时,数据会被原样送到你家或者办公室的内网机器上,看起来就像这台内网机器直接暴露在了公网上。

说白了,frp 就是把“公网服务器”当成一个接待前台,所有从外部进来的请求先到达前台,前台再根据登记信息把请求转给真正干活的“内网服务”。这个过程对内网服务是完全透明的,它不会感知到访问流量绕了这么一圈。

理解了这个模型,后面配置和排错就顺了。你会发现很多常见错误其实都是“前台”和“内网服务”之间信息不一致导致的,比如登记地址写错、口令对不上、端口被别的服务抢占了。

1.2 frps 与 frpc 的角色分工

frp 有两个核心角色,名字比较像,但职责完全不同。

frps 是服务端,跑在有公网地址的那台机器上。它负责监听一个固定端口,接受来自客户端的注册请求,也接受来自外部网络的访问请求,然后按配置把流量转到对应的内网目标。

frpc 是客户端,跑在你需要被访问的内网机器上。它主动去连接 frps,把自己本地的某个端口“登记”到服务端,登记完成后,只要服务端的对应端口收到访问,流量就会被转到 frpc 这边的本地服务。

这里最关键的一点是:连接永远是内网机器主动发起的。即便内网机器没有公网地址、处在 NAT 后面,只要它能正常访问外网,就能通过 frpc 把通道建立起来,然后实现外部网络对内部服务的访问。这也是 frp 这类工具适用面广的原因,不需要在路由器上做端口映射,也不需要内网机器真的拥有公网 IP。

1.3 哪些场景适合用 frp

从应用场景看,frp 适合做的工作不外乎这几类:

  • 远程 SSH 登录内网服务器,比如在家里连公司内网的开发机。
  • 把本地正在开发的 Web 接口暴露出去,给前端、测试同学联调用。
  • 在外访问家里的 NAS、路由器管理页面或个人网盘。
  • 通过 stcp 这类方式做点对点加密通信,只在两端建立临时访问关系,不把服务直接暴露到公网。

需要提醒的是,frp 更适合临时的、小型的、个人或小团队的使用场景。如果你要做高可用,或者入口要扛大规模流量,建议还是考虑更成熟的负载均衡体系。frp 的定位始终是轻量通道工具,不是流量分发系统,超出了它的边界反而容易把自己坑进去。

2. 开始配置前需要准备哪些基础条件

2.1 一台有公网地址的服务器怎么确认

frp 服务端必须有一台能被外网直接访问的机器,最常见的就是云服务器。你首先要确认这台服务器的公网地址是真实、可用的。

可以通过ip addr看网卡地址,也可以执行curl ifconfig.me查看出口 IP,然后跟云厂商控制台显示的公网 IP 做对比。如果两者不一致,说明机器可能处在云平台内部 NAT 后面,访问还是要看控制台那个公网地址。

另外,提前在纸上记一下后面会用到的端口:frps 接收 frpc 连接的端口(我习惯用 7000)、控制面板端口(比如 7500)、要映射出去的 remotePort(比如 16022)。这样配置时不至于一团乱麻。

2.2 下载安装包与选择合适架构

frp 的发布包放在 GitHub Releases 页面,文件命名一般是frp_版本号_系统_架构.tar.gz。

  • Linux x86 服务器,下载linux_amd64的包。
  • 树莓派或 ARM 开发板,下载linux_arm64或linux_arm。
  • mac 本地下调试,下载darwin_amd64或darwin_arm64。

下载前先用uname -m确认架构,x86_64 对应 amd64,aarch64 对应 arm64,别不看架构就直接解压跑,否则很可能遇到Exec format error这种启动失败。

2.3 frp 目录结构和配置文件初识

解压之后你会看到 frps、frpc、以及带.toml后缀的配置模板文件。这里要特别提醒一点:frp 在较新的版本里已经统一使用 TOML 配置格式,默认读取frps.toml和frpc.toml。网上很多老教程还在用frps.ini、frpc.ini,那些内容看看思路就好,直接抄配置在新版本上很可能会解析失败。

我习惯把二进制和配置都放到固定目录,方便后面用 systemd 管理:

mkdir -p /opt/frp tar -xzf frp_0.61.1_linux_amd64.tar.gz -C /opt/frp --strip-components=1 cd /opt/frp ls -l

正常情况下能看到frps、frpc和对应的.toml文件。目录路径后面写 systemd service 时要保持一致,不要一会儿用/root/frp,一会儿用/opt/frp。

3. 服务端 frps 配置实操

3.1 最小可运行配置

先编辑服务端配置/opt/frp/frps.toml,写一个最小可用版本:

bindPort = 7000 auth.method = "token" auth.token = "改成你自己的复杂随机字符串"

bindPort是 frp 服务端用来接收 frpc 连接的端口,可以按需要调整,但后面客户端必须保持一致。auth.token是两端握手的口令,建议用随机生成的长字符串,不要用123456这种一眼能猜出来的弱口令。

这个配置其实已经能跑起来,但实际使用中我会直接把控制面板一起打开,方便观察连接状态。

3.2 控制面板与端口规划

控制面板是 frp 自带的 Web 状态页,能看到当前有哪些客户端在线、哪些通道正在工作。配置长这样:

bindPort = 7000 auth.method = "token" auth.token = "改成你自己的复杂随机字符串" webServer.addr = "0.0.0.0" webServer.port = 7500 webServer.user = "admin" webServer.password = "请改成强密码"

控制面板端口没有特殊要求,只要不和 bindPort 冲突即可。需要注意的是,面板带登录口令,默认账号密码一定要改,尤其是当webServer.addr配成0.0.0.0的时候,外部网络也能访问到面板。

我自己实际使用时会把这个端口加来源 IP 限制,只允许办公网络 IP 访问,不给公网裸奔的机会。

3.3 用 systemd 把 frps 做成常驻服务

直接用./frps -c frps.toml前台启动只适合调试。真正要长时间跑,我建议放到 systemd 里管理,这样服务器重启后能自动拉起,进程意外退出也会按策略重启。

创建一个 systemd 服务文件:

cat > /etc/systemd/system/frps.service <<'EOF' [Unit] Description=frp server After=network.target [Service] Type=simple ExecStart=/opt/frp/frps -c /opt/frp/frps.toml Restart=on-failure RestartSec=5s [Install] WantedBy=multi-user.target EOF

然后执行:

systemctl daemon-reload systemctl enable --now frps systemctl status frps

看到active (running)就说明服务端已经起来了。后面改配置后记得执行systemctl restart frps。

4. 客户端 frpc 配置实操

4.1 最常用的 TCP 端口映射配置

假设我想在内网机器上把本机的 22 端口映射到公网服务器的 16022 端口,frpc.toml可以这样写:

serverAddr = "你的服务器公网IP" serverPort = 7000 auth.method = "token" auth.token = "和 frps.toml 保持一致" [[proxies]] name = "ssh" type = "tcp" localIP = "127.0.0.1" localPort = 22 remotePort = 16022

字段解释一下:

  • serverAddr和serverPort:frps 的地址和连接端口,端口必须和frps.toml的bindPort一致。
  • [[proxies]]:定义一个转发条目,name可以自己取,但不能和同一客户端下其他条目重名。
  • type:转发类型,TCP 转发就写tcp。
  • localIP和localPort:内网实际服务的地址和端口。如果服务就在本机,写127.0.0.1没问题;如果 frpc 要转发同一局域网里另一台机器的服务,这里要写那台机器的内网 IP。
  • remotePort:frps 对外提供服务要使用的端口,这个端口要保证在公网服务器上没有被其他服务占用。

启动客户端:

./frpc -c frpc.toml

启动后,在任意一台有公网访问能力的机器上执行ssh user@服务器公网IP -p 16022,就能登录到内网机器。

注意:remotePort不能用服务器上已占用的端口,否则绑定时会直接失败。如果服务器是云厂商的,16022 这个端口还必须在安全组里放行,否则外部流量到不了 frps。

4.2 其他常用转发类型:UDP、HTTP、STCP

UDP 转发和 TCP 差别不大,把type改成udp,其余逻辑一样。适合做 DNS 调试、NTP 同步这类场景的外网访问。

HTTP 转发则更适合有域名的情况。frps 上需要开启vhostHTTPPort,frpc 里配置type = "http"和customDomains = ["app.example.com"],服务端收到 HTTP 请求后会按照域名把流量转发到对应的内网服务。这样做的好处是不需要为每个 Web 服务分配独立端口,一个 HTTP 端口加不同域名就能承载多个内网站点。

STCP 不一样,它不直接暴露对外端口,而是通过 frps 做信令交换,由两个 frpc 之间建立点对点加密通道。适合想对外安全提供服务又不想让端口直接暴露在公网上的场景,配置上也多一层 visitor 概念。

我第一次用 frp 的时候,直接先从最简单的 TCP 转发开始,跑通之后再尝试 HTTP、STCP。建议你也按这个顺序来,不然一堆配置项堆在一起出问题时,根本不知道从哪里排查起。

4.3 客户端日志与启动验证

frpc 前台启动后,正常情况下日志里会出现类似start proxy success的字样,并打印出当前映射的地址信息。如果看到login to server failed,那就是和第 6 章的常见错误对上了。

客户端同样推荐用 systemd 管理,避免重启服务器之后 frpc 没有自动拉起来。配置文件路径和启动命令换成 frpc 对应版本即可。

5. 配置完成后的联调与网络放行

5.1 从零开始的启动顺序

frp 的启动顺序其实没有强依赖,frpc 先启动也能等 frps 恢复后自动连上,但我习惯先确保 frps 服务端起来并监听端口,再启动 frpc,这样日志比较干净,方便定位问题。

真正需要重点检查的反而是配置一致性:服务端bindPort和客户端serverPort是否一致,两边 token 是否完全一致,remotePort是否冲突。顺序对了但配置对不上,一样连不通。

5.2 验证内外网是否真正打通

验证分三步走:

  1. 在服务器上执行ss -lntp | grep 16022,确认 frps 已经在监听对应端口。
  2. 打开 frps 控制面板,在浏览器访问http://服务器公网IP:7500,登录后看到客户端在线、通道状态正常。
  3. 在另一台外部机器上执行telnet 服务器公网IP 16022,或者直接用业务命令验证,比如 SSH 端口就直接ssh -p 16022 user@服务器公网IP。

如果服务器本机访问端口是通的,但外部不通,那问题八成出在网络放行这一环。

5.3 防火墙与云平台安全组注意事项

服务器自带的防火墙(比如 firewalld 或 ufw)和云平台的安全组是两个独立环节,任何一个挡着都会失败。

常见现象是:frpc 日志显示连接成功,控制面板也显示在线,但外部访问超时。这种情况十有八九是安全组或服务器防火墙没放行 remotePort。排查时可以先用curl -v或者telnet从外部访问,再看是超时还是拒绝,超时大概率是安全组丢包,拒绝则可能是端口没监听。

开放防火墙端口示例:

firewall-cmd --permanent --add-port=7000/tcp firewall-cmd --permanent --add-port=7500/tcp firewall-cmd --permanent --add-port=16022/tcp firewall-cmd --reload

如果用的是 ufw:

ufw allow 7000/tcp ufw allow 7500/tcp ufw allow 16022/tcp

云平台安全组的操作不在命令行里,每家的控制台位置不同,但思路一样:找到安全组规则,添加入方向的对应端口放行规则。我经常看到有人改了 frp 配置半天,最后发现只是安全组漏了一条规则,特别浪费时间。

6. frp 常见错误排查实战

6.1 配置文件解析错误导致启动失败

现象:启动 frps 或 frpc 时直接报invalid config或者load config error。

排查思路:

  • 先确认配置文件后缀是.toml,新版本已经不推荐使用旧的.ini后缀。
  • 再看字段名是否按 TOML 规范写,比如serverAddr是驼峰写法,不是旧版的server_addr。
  • 检查是否有中文引号、中文冒号混在配置文件里。这个问题常见于在 Windows 编辑器中复制内容再粘贴到 Linux 的场景。
  • 较新版本提供了配置校验命令,强烈建议启动前先跑一遍:
./frpc verify -c frpc.toml

服务端对应使用./frps verify -c frps.toml。校验能通过,再谈其他排错。

6.2 token 认证失败与 401 报错

现象:客户端日志出现login to server failed: 401或者auth error。

原因几乎都是两端 token 不一致。先对比frpc.toml和frps.toml的 token 是否完全一样,注意不要有空格、不要用中文引号。如果服务端开了auth.method = "token",而客户端没有写这个字段,也可能导致认证异常。

我遇到过最气人的情况是,token 复制的时候从日志里多复制了一个换行符进去,肉眼完全看不出来,但两边就是握不上。所以建议token 写成无空格、无换行的纯字符串。

6.3 bind 端口被占用的问题

现象:frps 启动时日志出现port already used,或者服务起不来。

排查时先在服务器上执行:

ss -lntp | grep 7000

如果看到其他进程占了 7000 端口,要么换端口,要么把占用进程处理掉。另一种常见情况是配置了多个代理,但把多个remotePort配成了一样的值,导致后定义的代理无法绑定。日志里通常会有类似proxy name duplicated或者端口绑定的报错,看到后挨个检查每个转发条目的remotePort即可。

6.4 客户端已经连上,但外部始终访问不了

这是实际使用中频率最高的一个问题。

分三步排查:

  1. 在服务器本机执行telnet 127.0.0.1 16022或curl 127.0.0.1:16022,看端口是否在监听。如果本机都连不通,说明 frps 没有成功监听,或者转发通道没有注册成功。
  2. 如果本机能通,但外部机器不行,去检查安全组和服务器防火墙。
  3. 如果外部能连到端口,但连接后马上就断,去看后端内网服务的localIP和localPort填得对不对,内网服务本身有没有在监听。

还有一种隐蔽情况:服务器公网 IP 写错了。尤其是云服务器有内网 IP 和公网 IP 两个地址,frpc 的serverAddr必须填公网 IP,填了内网 IP 只会导致外部通道永远建立不起来。

6.5 EOF、timeout、connection refused 分别代表什么

日志里出现这些关键字,含义完全不同:

  • EOF:连接被对方正常或异常关闭。常见于 token 不正确,服务端主动断掉握手;也可能是服务端重启导致旧连接没被清理,客户端重连后恢复。
  • timeout:网络不通或端口被丢包。重点检查安全组、防火墙、frps 的bindPort是否监听。
  • connection refused:端口没有监听。常见于remotePort被占用,或者 frps 还没有起来。

看到这些关键词不用慌,先把它对应到具体嫌疑点,再逐项排除。

6.6 常见错误速查表

把上面这些问题整理成一张表格,遇到问题先对着表格查,能省不少时间:

现象可能原因优先排查动作
启动报 invalid configTOML 格式或字段名写错执行frpc verify -c frpc.toml
日志出现 401token 不一致对比两端 token 是否完全一致
bind 端口失败端口被其他服务占用执行ss -lntp查看端口占用
客户端在线但外部不能访问安全组或防火墙未放行检查云平台安全组和本机防火墙
连接后立刻断开 / EOFtoken 错误或服务端拒绝查看 frps 端日志
timeout网络不通或端口被丢包检查公网 IP、防火墙、安全组
connection refused端口未监听确认 frps 是否正常运行,端口是否被占

6.7 几个容易被忽略的低级错误

最后再单独列出几个我见过很多次的低级错误:

  • 用中文双引号写配置文件,导致 TOML 解析失败。
  • 手动复制 token 时,把日志里的省略号或者换行符一起复制进去。
  • frpc 连接公网服务器时,IP 填成了云服务器内网 IP。
  • 修改配置文件后忘记重启 frp 服务,还在用旧配置跑。

这些错误排查起来不难,但容易在忙乱中反复踩。我的习惯是每次改完配置,先执行一遍verify,再重启服务,最后看日志确认状态。

7. 一些提升使用体验的小细节

7.1 版本选择与升级思路

不要盲目追最新版,也不要用太老的版本。frp 迭代速度很快,部分版本之间协议或配置格式有调整,升级前一定先备份现有配置,再替换二进制文件,升级后在本地环境先跑通再更新线上。

版本太老的问题主要是新特性没有,协议兼容也可能出问题;版本太新的问题则是社区资料还不充分,遇到问题能搜到的案例少。一般我会选择最近半年内发布的功能相对完整的版本。

7.2 日志策略与磁盘占用

frp 如果通过 systemd 管理,日志默认会进入 journald。长时间运行后,日志量不可小觑,尤其是有大量连接请求和控制面板刷新的情况。

可以用下面的命令查看服务日志:

journalctl -u frps -n 50 --no-pager journalctl -u frpc -f

如果担心日志占用过多磁盘,可以在 frps 的 systemd service 里加日志清理相关配置,或者定期用journalctl --vacuum-size=200M限制日志体积。简单场景下,我通常只保留最新的一部分日志,重点是能看到最近几次启动和报错信息。

7.3 关于 token 和安全习惯

frp 的 token 本质上是两端握手时的口令,务必用高强度随机字符串,不要把 token 提交到代码仓库、不要写在公开笔记里。

控制面板的账号密码也一定要改默认值,不要用默认的admin。如果服务器只给固定来源使用,尽量在防火墙层面限制来源 IP。

从个人习惯来说,我会把服务端 systemd 服务、防火墙放行命令、配置文件模板整理成一套固定流程,换新机器的时候直接复用。frpc 每新增一个转发通道都会在配置里加注释,说明这个通道是给哪个服务用的、对应内网端口是什么。这样配置多了之后不会混乱,排查问题的时候也知道每一个条目当初为什么加。

最后再分享一个小技巧:遇到 frp 连不上、访问异常这类问题,先别急着改配置,先把 frps 和 frpc 两端的日志同时打开,对比看是在握手阶段就断了,还是握手成功后转发阶段才出问题。这样做能直接砍掉一大半排查路径,比盲试配置高效得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询