内网穿透实战:从免费隧道到自建 frps
上一篇搭好的 Nextcloud 跑在开发板上,但板子在家里,只有内网 IP,出门在外就访问不到。这就需要一个能"从公网打进内网"的通道——内网穿透。
为什么需要穿透
家庭宽带普遍拿不到固定的公网 IPv4 地址,NAT 把内网设备挡在了路由器后面。想让外网访问内网服务,通常有两条路:
- 向运营商申请公网 IP(能不能给、给不给固定的,看运气);
- 内网穿透:内网设备主动向外连一台有公网 IP 的中转服务器,由它把流量转回来。
第二条第主动发起、无需改动路由器,实现也简单,所以选了它。方案用的是 frp(Fast Reverse Proxy)。
方案一:先用免费隧道跑通
一开始不想折腾自己的服务器,直接用现成的免费穿透服务 Sakura Frp。它的原理就是帮你开一条隧道:内网跑一个 frpc 客户端,连到服务商的 frps 服务器,得到一个外网地址。
好处是零成本、开箱即用,几分钟就能让网盘被外网访问。缺点也很明显:
- 节点是共享的,速度和质量受其他人影响;
- 外网地址是服务商分配的二级域名 + 随机端口,不够"自己";
- 免费额度有限,功能也受限制。
所以免费隧道适合快速验证"这条路通不通",长期稳定使用还是得上自己的服务器。
方案二:自建 frps
手里有台轻量云服务器,公网 IP 稳定,直接在上面跑 frps,把自己变成服务商。
服务端 frps 配置
frp v0.70 开始用 TOML 配置,服务端 frps.toml 大致长这样:
bindPort = 7000 # frpc 连这个端口
auth.token = "换成你的强随机token"
# 只放行需要用到的端口,避免被拿去乱映射
allowPorts = [
{ start = 80, end = 443 },
{ start = 10000, end = 19999 },
]
# 管理面板只监听本机,不外露
webServer.addr = "127.0.0.1"
webServer.port = 7500
几点安全上的考虑:
auth.token一定要设,否则任何人的 frpc 都能连上来把内网打穿;allowPorts限定可映射的端口范围,避免被拿来转发奇怪的东西;- 管理面板绑
127.0.0.1,要看的时候走 SSH 隧道。
再写个 systemd 服务让 frps 开机自启,服务端就绪。
客户端 frpc 配置
内网设备上跑 frpc,把本地服务的端口映射出去:
serverAddr = "你的服务器地址"
serverPort = 7000
auth.token = "和服务端一致"
[[proxies]]
name = "nextcloud"
type = "tcp"
localIP = "127.0.0.1"
localPort = 443
remotePort = 10443
这样访问 服务器:10443 就等于访问内网的 443 端口了。
两条路线的对比
| 免费隧道(Sakura Frp) | 自建 frps | |
|---|---|---|
| 成本 | 免费 | 需要一台云服务器 |
| 上手速度 | 几分钟 | 需要装服务、配 token |
| 速度与稳定性 | 共享节点,看运气 | 独享,取决于服务器带宽 |
| 可控性 | 受平台限制 | 完全自己掌控 |
小结
内网穿透的难点不在配置本身,而在想清楚"流量是怎么绕回来的":内网 frpc 主动向外连 frps,建立一条常驻的长连接,外网请求打到 frps 后顺着这条连接被"塞"回内网。理解了这个模型,剩下的只是配置和踩坑。
有了这条稳定的通道,后面甚至能让云服务器反过来控制家里的电脑——这就是下一篇要讲的反向 SSH 隧道。