尧图精选

frp内网穿透全攻略:原理、配置与安全加固实践

🕒 发布时间:2026/10/2 22:33:40 📁 来源:尧图网络
做项目最怕的不是需求复杂而是人坐在办公室服务器却在客户机房生产环境出问题只能干瞪眼。这种时候frp这种内网穿透工具就成了我工具箱里出场率最高的东西。frp全称Fast Reverse Proxy是一个开源的反向代理工具核心功能是把内网机器的端口“搬运”到一台有公网IP的服务器上让外部流量能够绕过NAT和防火墙策略通过中转服务器访问内网服务。这篇东西主要写给两类人一类是经常要出差连公司电脑、远程设置家里NAS、临时给客户演示内网页面的运维和开发者另一类是做安全方向、需要在拿到授权后做内网环境测试的同学。frp的优点很直接部署简单、一个二进制文件就能跑性能也不错还支持TCP、UDP、HTTP、HTTPS、STCP等多种代理类型基本覆盖了日常会碰到的远程访问场景。接下来我把从服务端到客户端、从基础配置到安全加固的完整过程拆开讲清楚。1. 先用大白话讲清楚frp到底解决了什么问题1.1 为什么你会遇到“内网穿透”这个需求先看一个最常见的场景。我在办公室连着一台内网Linux服务器公司的出口是一个公网IP路由器做了NAT。出差住酒店时想SSH登录这台机器直接连是连不上的因为你根本不知道流量该往哪儿走内网服务器没有公网IP路由器也不会把外部连接转给这台不相关的机器。防火墙策略在这里扮演的角色也一样本质是“默认拒绝来自不信任区域的连接”。frp的解决思路并不神秘既然外网没法直接访问内网机器那就找一台两边都能访问的公网服务器当中转。公网服务器上跑frpsfrp服务端内网机器上跑frpcfrp客户端frpc主动向frps发起连接建立起一条长连接的加密隧道。外部用户去连公网服务器的某个端口时frps把流量从这条隧道原样转发给内网机器的frpcfrpc再把流量交给本地目标端口。整个过程对流经的服务来说是透明的SSH、RDP、数据库客户端都无感知。这里有个关键点frpc发起的是“出站连接”方向是从内网到公网。大多数防火墙策略主要拦截外网主动进来的流量对出站连接的限制相对宽松这就是frp能打通访问通道的原理。有些环境出站限制也很严格那就只能配合代理或者白名单手段后面我会单独讲。1.2 frp和同类工具怎么选市面上做内网穿透的工具有不少每一类都有各自的适用场景。我把常用的列个表对比一下方便你根据自己情况选。工具原理优点缺点适合场景frp自建服务端客户端反向代理功能全、协议多、可深度定制需要一台公网服务器长期稳定的远程访问、自建穿透节点ngrok类似frp官方有SaaS服务零部署一条命令就能用免费版域名随机、速度不稳定临时演示、联调ZeroTier/TailscaleP2P虚拟组网不依赖中心服务器就能直连公司网络策略严时可能连不上多台设备组成私有网络SSH反向隧道利用OpenSSH转发功能系统自带无需额外装客户端隧道断了不会自动重连应急登录、临时开个端口我的习惯是正式环境一律用frp因为它功能最完整——支持TCP/UDP/HTTP/STCP多种模式有Dashboard面板可以看连接状态还能做端口白名单限制。ngrok适合现场给客户演示的时候临时开一个隧道演示完就关省事。如果是自己家里的几台设备要组网ZeroTier更省心但到了公司这种出口对UDP 限制比较严格的环境反而可能不如frp稳。2. 架构与核心原理一条隧道是怎么打通的2.1 frp的整体流程拆解frp的工作流程可以分成四步理解了这个流程后面排错会快很多。第一步是frpc主动连接frps。frpc启动后会根据配置文件里的serverAddr和serverPort去连接公网服务器的frps完成握手和认证。注意这里是frpc主动出站不是frps去连内网机器这是整个方案能成立的前提。第二步是frps验证身份。双方配置里的token必须一致否则连接直接被拒绝。从新版开始frp还支持TLS加密传输可以防止token和业务流量在网络传输过程中被截获。第三步是端口映射注册。frpc在配置里声明要建立哪些代理比如“把本地22端口映射到公网服务器的6222端口”frps收到请求后会在公网服务器上监听6222端口。第四步是流量转发。外部用户访问公网服务器的6222端口时frps通过已经建立的隧道把流量转发给内网机器的frpcfrpc再把流量送给本机22端口。返回路径是反过来的。整个过程中frps和frpc之间始终只有一条长连接多路业务流量在这条连接上复用传输。2.2 新版TOML配置格式和旧版INI的区别如果你以前用过frp可能记得老版本用的是ini格式的配置文件大概长这样[common] server_addr 1.2.3.4 server_port 7000从frp 0.52版本开始官方把配置格式迁移到了TOML。新格式和旧格式差异很大有两个变化最需要关注一是配置项名字从下划线风格改成了驼峰风格比如server_addr变成了serverAddr二是客户端里的代理定义从多个[proxy-xxx]小节改成了在proxies数组里用列表形式统一定义。我见过不少同学在网上找教程复制了一堆旧版配置结果新版frpc启动直接报错多半就是格式问题。现在官方release页面下载的稳定版都是TOML格式建议直接用新版。如果实在有老项目还跑在ini格式的上可以看frp官方文档里提到的自动转换逻辑但没必要纠结兼容旧版。3. 服务端frps部署与配置全流程3.1 准备工作一台有公网IP的服务器frps需要跑在一台能被公网访问的服务器上这就意味着这台服务器必须有公网IP且端口不能被云平台的“安全组策略”挡住。云服务器的安全组和系统内防火墙是两个层面的东西安全组相当于云厂商在机房网络设备上的访问控制策略系统防火墙则是操作系统层面的策略两者同时生效有一个没放行就连不上。服务器配置不用太高1核1G的入门款就能扛住不少并发连接因为frp本身只是做转发计算开销很小。带宽倒是要留意如果穿透的流量是远程桌面或者文件传输带宽决定了体验。操作系统我推荐Debian或者Ubuntu。原因很简单系统干净、默认防火墙规则少、遇到问题网上资料多。3.2 下载安装与服务端完整配置去GitHub的frp release页面找最新的linux-amd64版本注意服务器架构。绝大多数云服务器是x86架构用amd64版本没问题如果是ARM架构的服务器比如某些国产芯片或者树莓派要下arm64版本下错了会报exec format error。下载解压的命令大致如下wget https://github.com/fatedier/frp/releases/download/v0.61.0/frp_0.61.0_linux_amd64.tar.gz tar -zxvf frp_0.61.0_linux_amd64.tar.gz mv frp_0.61.0_linux_amd64 /usr/local/frp解压完的目录里有frps和frpc两个二进制文件还有对应的toml配置示例文件。服务端只用到frps和frps.toml客户端的可以不管。下面是一个生产环境可用的frps.toml完整配置bindPort 7000 auth.method token auth.token Kj8mN2pQx7Lv9Tr5Wd4Yh6Ue1Ba3Cs0 webServer.addr 0.0.0.0 webServer.port 7500 webServer.user admin webServer.password 改成你自己的强密码 transport.tls.force true allowPorts [ { start 6222, end 6299 }, { start 6338, end 6339 } ]逐项解释一下作用。bindPort是frps监听frpc连接的端口相当于frp自己的大门默认7000这个端口可以自己改但改了之后客户端配置里的serverPort要同步改。auth.token是客户端连上来时的通行证一定要设置成长随机字符串。我遇到不少部署token还是默认的12345678这种节点等于裸奔非常危险。webServer这一段是frp自带的Dashboard监控面板浏览器打开http://服务器IP:7500就能看到当前在线客户端、代理列表和流量统计。addr设置为0.0.0.0表示所有网卡都可以访问如果你只希望自己电脑能打开面板可以改成你的办公网IP。transport.tls.force为true表示强制TLS加密所有客户端必须开启TLS才能连上防止token和业务流量被中间人抓包。allowPorts段是服务端对客户端远程端口白名单的限制——客户端想占用公网服务器的哪个端口必须在这个范围内不在范围内的映射请求直接拒绝。这是个很实用的安全措施比如我把6222-6299和6338-6339放开了客户端就只能用这些端口段避免有人乱开端口把服务器搞成公网代理。3.3 用systemd把frps变成常驻服务直接运行./frps -c frps.toml可以手动启动但是关掉终端服务就停了生产环境肯定不行。Linux上把frps做成systemd服务是最标准的做法。创建服务文件/etc/systemd/system/frps.service[Unit] Descriptionfrp server service Afternetwork.target [Service] Typesimple ExecStart/usr/local/frp/frps -c /usr/local/frp/frps.toml Restarton-failure RestartSec5s [Install] WantedBymulti-user.target启动并设置开机自启systemctl daemon-reload systemctl enable frps systemctl start frps systemctl status frps注意几个细节。ExecStart里的路径必须是绝对路径写成相对路径service会启动失败。Restarton-failure表示服务异常退出时自动拉起RestartSec5s指定5秒后重试这两个参数能保证frps在服务器重启或者进程崩溃后自动恢复。查看日志用journalctl -u frps -f排查问题就靠它了。3.4 服务端防火墙和云安全组放行frps配置完成只是第一步90%的“部署完连不上”问题都出在端口没有放行。这台公网服务器上需要放行的端口有三类bindPort7000、allowPorts里定义的远程端口、Dashboard端口7500。如果你用的是CentOS或者安装了firewalld的系统放行命令是这样的firewall-cmd --permanent --add-port7000/tcp firewall-cmd --permanent --add-port6222-6299/tcp firewall-cmd --permanent --add-port6338-6339/tcp firewall-cmd --permanent --add-port7500/tcp firewall-cmd --reload跑在Debian/Ubuntu系统上如果没有另外装防火墙默认就不拦端口但要确认一下云厂商控制台里的安全组策略。以阿里云为例在ECS实例的安全组里添加入方向规则放行相应TCP端口。很多朋友本地测frps是通的换到云服务器就不行十有八九就是安全组忘放行了。这里我要特别说明一下标题里经常出现的“绕过防火墙”在真实运维场景里并不是要绕过云平台或者系统防火墙的安全策略而是通过frp隧道在不改变外网对内部网络访问策略的情况下建立一条受控的访问通道。云平台安全组和系统防火墙该放行的端口还是要放行这是正规操作和“绕过”是两个概念。我见过一些安全演练场景里团队会特意不开放相关端口用frp的隐藏端口来做隐蔽通道但那属于攻防对抗专题而且需要完整的授权不是日常运维该模仿的做法这里就不展开了。4. 客户端frpc配置与三种最常用场景4.1 基础配置认识frpc.toml的结构内网机器上下载frp的方法和服务端一样只是运行的是frpc。客户端配置文件frpc.toml的结构分为两大部分连接服务器的参数和代理列表。serverAddr 你的服务器公网IP或域名 serverPort 7000 auth.method token auth.token Kj8mN2pQx7Lv9Tr5Wd4Yh6Ue1Ba3Cs0 transport.tls.enable true proxies [ { name ssh, type tcp, localIP 127.0.0.1, localPort 22, remotePort 6222 } ]serverAddr填服务器公网IP如果服务器绑定了域名建议填域名这样服务器IP变更时客户端不用改配置。serverPort和token必须和服务端配置一致一个字符都不能差。transport.tls.enable true对应服务端的force true。proxies数组第一个元素就是一条SSH代理name是代理名称type是协议类型localIP和localPort是内网目标服务地址remotePort是公网服务器上要暴露的端口。4.2 场景一SSH远程管理内网Linux最基础也最常用的就是SSH穿透。我在内网有一台开发机IP是192.168.1.100SSH端口是默认22。frpc配置如下proxies [ { name ssh-dev, type tcp, localIP 192.168.1.100, localPort 22, remotePort 6222 } ]启动frpc后公网服务器上的6222端口就指向了内网开发机的22端口。我在外面直接执行下面的命令就能登录ssh -p 6222 user服务器公网IP等一下有个细节很多人会踩坑。如果你在内网开发机本机上跑frpc并且SSH服务监听的是0.0.0.0那么localIP写127.0.0.1就够了。但如果你和我的情况一样内网有多台机器frpc跑在一台单独的网关上要代理其他机器的SSHlocalIP必须写成目标机器的内网IP。这里的原则是localIP填frpc能访问到目标的地址能本地回环就不要写局域网IP减少不必要的网络路径。4.3 场景二RDP远程桌面访问内网Windows远程桌面是另一个高频需求。Windows的RDP服务端口是3389穿透配置如下proxies [ { name rdp-win, type tcp, localIP 192.168.1.50, localPort 3389, remotePort 6338 } ]外部Windows机器连接时打开“远程桌面连接”计算机名填公网IP:6338即可。这里有一个Windows特有的坑如果你在目标Windows机器上跑了frpc并且代理的是本机3389localIP直接填127.0.0.1没问题但如果Windows防火墙开启了“远程桌面服务”的入站限制frpc转发到本机3389的流量也可能被拦。解决办法是在Windows防火墙里放行3389端口或者放行frpc.exe程序的所有入站流量二选一。出站方向的限制也值得提一句。现在很多企业Windows防火墙的策略比较严会阻止未签名程序对外连接frpc.exe就经常被拦。现象是frpc启动后日志显示一直卡在连接服务器超时。排查方法是在防火墙的“出站规则”里新建一条允许frpc.exe连接网络放行然后重试。这一点和很多安全软件阻止某些程序出站联网是同一个道理。4.4 场景三HTTP/HTTPS域名访问内网Web服务TCP穿透解决的是SSH、RDP这类二进制协议HTTP场景用TCP也完全能通但域名访问和虚拟主机路由就搞不了。销售那边要给客户演示系统不可能让客户去访问IP:8080这种地址最好是一个干净的域名。frp的HTTP代理可以解决这个问题。先看frps.toml里需要加一个配置vhostHTTPPort 8080这个端口是frps用来接收HTTP流量的统一入口。客户端配置如下proxies [ { name web-demo, type http, localIP 127.0.0.1, localPort 8080, customDomains [demo.example.com] } ]external用户访问http://demo.example.com:8080域名解析到frp服务器IPfrps根据请求的Host头找到customDomains匹配的代理转发给内网机器的8080端口。一台frps可以承载无数个HTTP代理域名不同互不干扰。需要注意三个点域名解析必须提前做好否则外部用户找不到服务器。演示场景如果来不及申请域名也可以用xxx.frp.你的域名这种泛解析方式。如果服务端还配了HTTPS的vhostHTTPSPort需要同时准备证书和密钥文件比HTTP多几步。没有HTTPS证书时建议先跑HTTP演示归演示别耽误正事。customDomains不能随便填别人的域名这个域名必须能解析到你的frp服务器。我见过直接把客户线上域名填进去的那属于域名劫持了别碰。5. 安全加固比“能通”更重要的是“安全”5.1 默认配置下的安全隐患说句不太好听的我看到很多教程把frp配置出来能连通就结束了没人管安全。默认配置直接跑问题非常明显。token弱口令。网上很多教程的token是12345678如果你照着抄又没改任何知道你服务器IP和端口的人都能连上来。token是frp的唯一口令弱token相当于门锁是硬纸板做的。远程端口范围不限。frps默认允许客户端映射除了bindPort以外的任何端口意味着拿到token的人可以在你的公网服务器上随便开端口转发流量。轻则你的服务器变成别人的免费穿透节点重则被用来跑违规流量最后IP被封还是你背锅。流量明文传输。frp老版本默认不加密如果你的穿透链路经过运营商或者机房中间任何环节都可以抓到流量内容。尤其是穿透的数据库、远程桌面这种敏感协议明文就是裸奔。5.2 我的安全加固清单每次我在正式环境部署frp都会强制执行下面这几条缺一不可。第一token一定要用密码生成器生成至少32位的随机串不要用生日、IP、英文单词。比如可以用openssl rand -hex 16生成一个十六进制串。第二用allowPorts限定远程端口范围。我在服务端配置里只放开需要用的端口段至少避免被随意开端口中转流量。第三强制TLS加密。frps的transport.tls.force true加上frpc的transport.tls.enable true让两端流量都走TLS。frp从0.51版本开始支持TLS配置很简单效果是实实在在的。第四Dashboard不要用默认账号密码也不要暴露到公网。如果只是自己看建议webServer.addr改成127.0.0.1然后用SSH隧道访问Dashboard比把admin密码暴露在公网安全得多ssh -L 7500:127.0.0.1:7500 user公网服务器IP然后在本地浏览器打开http://127.0.0.1:7500就能看到面板。第五能用STCP就不用TCP。STCP是frp提供的点对点安全隧道模式原理是服务端只做协调和打洞不直接转发业务流量真正通信时两端用密钥做加密。这种模式下公网服务器上不需要开放远程端口外部用户需要先在客户端本地运行一个frpc并配置visitor才能访问。STCP适合两个固定节点之间需要高安全通信的场景配置稍微复杂一点但安全级别高一个档次。以SSH为例STCP服务端实际是穿透目标的机器配置如下proxies [ { name secret-ssh, type stcp, secretKey 你自己的共享密钥, localIP 127.0.0.1, localPort 22 } ]访问端的frpc配置则要声明一个visitorvisitors [ { name secret-ssh-visitor, type stcp, serverName secret-ssh, secretKey 和上面的共享密钥一致, bindAddr 127.0.0.1, bindPort 6222 } ]启动访问端frpc后本机6222端口就对应了目标内网机器的22端口然后执行ssh -p 6222 user127.0.0.1即可。整个过程公网服务器上看到的只是双方的连接握手业务数据不经过frps中转这是目前frp里安全等级最高的一种用法。5.3 关于“绕过”的正反面哪些事不能做标题里“绕过防火墙”这个说法加上“内网渗透”两个字在一些人眼里会有攻击性的联想。我得把底线讲清楚frp是工具本身没有对错关键看怎么用。有授权、有合同、有测试范围说明的渗透测试用frp做通道完全合法合规没有授权哪怕只是登录一下陌生人的内网机器也属于违法行为。实务中我这个角色最常碰到的合规场景是这些客户买了一套内网系统需要我们远程维护但客户不愿开放太多公网端口于是我们和客户约定好用frp建立一条独立隧道所有操作留日志测试完撤销映射或者出差时通过frp远程到公司电脑处理紧急工单。这类场景的核心特征是“被访问方知情且同意”。如果你发现自己所在的单位禁止使用任何穿透工具那就别用遵守单位网络管理规定同样是职业底线。6. 常见问题排查与进阶技巧6.1 外网连不上按这个顺序排查frp连不上的问题我排查过太多次了总结出一个固定顺序按这个顺序走能最快定位问题。先看frpc的日志。执行journalctl -u frpc -f看有没有报错。日志里如果出现dial tcp: connection refused说明frpc连不上frps重点检查frps是否启动、serverAddr和serverPort是否正确、服务器防火墙是否放行。如果出现login to server failed: token错误说明token配置不一致检查两端的token字符串。再看frps的日志和服务状态。systemctl status frps看进程是否存活journalctl -u frps -f看有没有accept连接记录。如果frps根本没有收到frpc的连接请求那就是网络层面被拦了多半是服务器防火墙或者云安全组没放行bindPort。然后测端口连通性。在外部机器上执行telnet 公网IP 7000能通说明网络通路没问题不通就要倒回去检查防火墙。记住一个原则从外网往内测一步步缩小范围不要上来就怀疑frp配置有问题。最后测具体的代理端口。比如SSH穿透连不上先确认frps上监听6222端口的是frps本身而不是被其他程序占用了。用ss -lntp | grep 6222查看监听的进程名应该是frps如果不是说明端口被占改一个remotePort就行。6.2 常见问题速查表问题现象可能原因解决办法frpc提示connection refusedfrps没启动或bindPort不对检查frps进程和配置frpc提示token错误两端token不一致统一两端的token配置外网能连frps但代理端口不通remotePort对应的防火墙/安全组未放行放行allowPorts对应端口SSH/RDP连接时卡住或闪断中间网络MTU或延迟问题检查两边网络TCPMux是否开启frps Dashboard无法访问webServer.addr、端口未放行确认配置和防火墙规则内网Windows上frpc不工作防火墙出站规则拦了frpc.exe给frpc.exe加出站放行规则代理正常但访问极慢服务器带宽不足或两端带宽不匹配升级带宽或压缩流量6.3 进阶稳定性调优与多客户端管理frp用了一段时间之后稳定性会成为新的关注点。有几个参数值得调。TCPMux默认是开启的多个代理复用同一条TCP连接能降低延迟、减少握手次数。但如果你的frp版本比较老遇到过某些协议在mux下表现异常的情况可以把frpc和frps都设置transport.tcpMux false关闭用独立连接传输。心跳参数也值得设置一下。frpc默认每30秒向frps发送心跳包如果在弱网环境或者经过严格防火墙的网络里心跳间隔过长会被中间网络判定为闲置连接断掉。可以把心跳缩短到10秒并开启transport.heartbeatKeepAlive相关选项新版配置里对应的是transport.heartbeatInterval和transport.heartbeatTimeout。这个参数不像其他配置那么常用但我在穿透公司内网办公系统时实测下来确实能减少莫名其妙掉线的问题。多客户端管理方面frps的Dashboard其实已经能看所有客户端的在线状态和代理列表。如果客户端数量超过几十个建议给每台机器配置不同的token这样单个token泄露不会波及其他客户端。还可以在frps前边加一层Nginx或者Caddy做TLS终结和域名路由让frps只监听内网端口进一步缩小攻击面。说实话这个组合方案有点复杂大多数场景用不到但如果你的frps要面向多个项目组提供服务建议尽早考虑隔离。最后再分享一个小技巧。frpc的配置支持环境变量替换格式是{{ .Envs.XXX }}这意味着你可以把token这类敏感信息放到环境变量里配置文件中不出现明文秘钥。比如frpc.toml里写auth.token {{ .Envs.FRP_TOKEN }}启动时先export FRP_TOKENxxxxx再运行frpc这样即使配置文件被截图或者传到群里token也不会泄露。我自己的生产环境一直用这个方案属于性价比很高的一个安全习惯。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →