如何让外网访问内网服务器
公司内网跑着一台 GitLab,何让我在家想 clone 代码,外网结果连不上。访问服务这事儿困扰了我很久,内网直到我把几种方案都试了一遍,何让才算搞清楚里面的外网门道。
先说最直接的访问服务做法:在路由器上做端口映射。把公网 IP 的内网某个端口(比如 2222)转发到内网服务器的 22 端口,外网就能 SSH 进来了。何让听起来简单,外网但坑不少。访问服务大部分家庭宽带根本没有固定公网 IP,内网运营商给你的何让是 NAT 后面的地址,路由器上看到的外网 "公网 IP" 和实际出口 IP 不是一回事。电信偶尔还能打电话要一个动态公网 IP,访问服务移动和联通基本别想。就算拿到了公网 IP,把 SSH 端口直接暴露出去,每天日志里几千条暴力破解尝试是常态。
后来我换了个思路,用 frp 做内网穿透。原理不复杂:一台有公网 IP 的 VPS 跑 frps(服务端),内网服务器跑 frpc(客户端),frpc 主动连出去建立隧道,外网访问 VPS 的某个端口就等于访问内网服务。这个方案的好处是不需要动路由器,内网也不用有公网 IP。配置文件大概长这样:
# frpc.ini [common] server_addr = your_vps_ip server_port = 7000 [ssh] type = tcp local_ip = 127.0.0.1 local_port = 22 remote_port = 6000 跑起来之后,ssh -p 6000 your_vps_ip 就能连到内网那台机器。VPS 最便宜的也就几美元一个月,带宽够用。缺点是流量绕了一圈 VPS,延迟会高一些。我实测从家连公司,延迟从直连的 5ms 变成了 40ms 左右,日常操作感觉不出来,但传大文件就有点难受。
如果你不想自己维护 VPS,Tailscale 和 ZeroTier 这类组网工具值得试试。它们基于 WireGuard 或自研协议,把不同网络的设备拉进一个虚拟局域网。装好客户端,登录同一账号,每台设备分配一个 100.x.x.x 的地址,互相直接访问。我现在的做法是:公司服务器和家里 NAS 都装了 Tailscale,在外面用手机也能直接访问 NAS 上的文件,不需要任何端口映射。免费版支持 100 台设备,个人用完全够。
还有个容易被忽略的方案:Cloudflare Tunnel。在服务器上装一个 cloudflared 进程,它会主动建立到 Cloudflare 边缘节点的隧道。然后你在 Cloudflare 后台配一个域名指向这个隧道,外网就能通过域名访问内网服务。不需要公网 IP,不需要开端口,还自带 HTTPS。我拿它暴露过一个内网的 Grafana 面板,配置过程大概十分钟。唯一的问题是 Cloudflare 在国内的访问速度不太稳定,有时候快有时候慢。
选哪个方案,取决于你的具体场景。临时用几天,frp 最快。长期稳定使用、设备不多,Tailscale 最省心。有域名、想顺便解决 HTTPS 证书问题,Cloudflare Tunnel 更合适。至于直接端口映射——除非你有固定公网 IP 并且能接受安全风险,否则不建议。
对了,不管用哪种方案,内网服务本身的安全加固别偷懒。SSH 禁用密码登录、改用密钥;Web 服务加上认证;能限制来源 IP 就限制。穿透工具只是把门打开,门后面的锁还得自己装。