一篇搞懂内网穿透:从 localhost 到 ngrok
在开发微信公众号、第三方支付回调、Webhook 等功能时,经常会遇到一个问题:
我们的 Spring Boot 项目明明已经启动:
http://localhost:8080
浏览器也能正常访问。
但是微信、支付宝、GitHub 等外部服务器却访问不到。
这时候就需要一个非常常见的开发工具:
内网穿透。
本文就以 ngrok 为例,用最简单的方式搞懂内网穿透到底是什么。
一、什么是内网穿透?
一句话:
内网穿透,就是让公网能够访问你本地运行的服务。
例如我们在 IDEA 中启动 Spring Boot:
localhost:8080
自己访问:
http://localhost:8080/hello
没有任何问题。
但是别人通常无法直接访问:
你的 localhost:8080
因为:
localhost
表示的是:
当前这台机器。
例如微信服务器访问:
http://localhost:8080
这里的 localhost 指的是:
微信自己的服务器
而不是你的电脑。
所以:
你的电脑
Spring Boot
↓
localhost:8080
↑
│
❌ 公网无法直接访问
│
微信服务器
这就是我们需要内网穿透的原因。
二、什么是内网?
我们平时连接家里或者公司的 Wi-Fi 后,电脑可能会获得这样的 IP:
192.168.1.10
或者:
192.168.x.x
10.x.x.x
172.16.x.x
这些通常属于私有网络地址。
例如:
互联网
│
▼
家庭路由器
│
┌───────┴───────┐
▼ ▼
电脑 手机
192.168.1.10 192.168.1.20
电脑和手机在同一个局域网中,可以互相通信。
但是互联网中的其他服务器,一般不能直接通过:
192.168.1.10:8080
找到你的电脑。
因此你的 Spring Boot:
localhost:8080
主要只能在本机或者允许访问它的局域网环境中使用。
三、为什么开发时需要内网穿透?
最典型的就是:
第三方回调。
例如开发微信公众号。
用户给公众号发送消息以后:
用户
↓
微信公众号
↓
微信服务器
↓
你的服务器
微信需要主动调用:
/wx/callback
假设你的接口是:
http://localhost:8080/wx/callback
问题就来了:
微信服务器怎么访问你电脑里的 localhost?
答案是:
访问不了。
除非你把项目部署到公网服务器。
但是开发阶段如果每修改一次代码都:
修改代码
↓
打包
↓
上传服务器
↓
重新部署
↓
测试
非常麻烦。
我们真正想实现的是:
微信服务器
↓
公网地址
↓
我的电脑
↓
localhost:8080
这就是内网穿透。
四、ngrok 是什么?
ngrok 就是一个非常常见的内网穿透工具。
它可以帮助我们把:
localhost:8080
映射成一个公网可以访问的地址。
例如:
https://xxxx.ngrok-free.app
最终形成:
公网地址
https://xxxx.ngrok-free.app
↓
ngrok
↓
本地地址
http://localhost:8080
于是别人访问:
https://xxxx.ngrok-free.app/hello
请求最终就可以到达:
http://localhost:8080/hello
这就是 ngrok 最核心的作用。
五、ngrok 是怎么工作的?
很多人第一次使用 ngrok 会产生一个误解:
ngrok 是不是把我的 Spring Boot 项目上传到公网了?
不是。
你的项目依然运行在自己的电脑上。
ngrok 只是帮你建立了一条:
公网
↓
本地电脑
之间的通信通道。
可以简单理解成:
公网用户
↓
ngrok 提供的公网地址
↓
ngrok 公网服务器
↓
已经建立好的隧道
↓
你电脑上的 ngrok 客户端
↓
localhost:8080
↓
Spring Boot
所以 ngrok 并没有把:
localhost:8080
变成真正的公网服务器。
而是提供了一个公网入口,然后把请求转发到你的电脑。
六、为什么叫“穿透”?
可以想象你的电脑藏在一堵墙后面:
互联网
│
│
❌
│
▼
内网中的电脑
公网无法直接访问。
使用 ngrok 后,相当于建立了一条隧道:
互联网
│
▼
ngrok 公网服务器
│
│ 隧道
│
▼
你的电脑
│
▼
localhost:8080
外面的请求可以通过这条“隧道”到达你的电脑。
所以叫:
内网穿透。
七、ngrok 最基本的使用流程
假设我们的 Spring Boot 项目运行在:
localhost:8080
首先确保本地项目能够正常访问:
http://localhost:8080
然后安装并配置好 ngrok。
启动 HTTP 隧道时指定本地端口:
ngrok http 8080
意思就是:
帮我创建一个公网 HTTP/HTTPS 入口,把请求转发到本机 8080 端口。
启动以后,ngrok 会提供一个公网地址,例如:
https://xxxx.ngrok-free.app
于是:
https://xxxx.ngrok-free.app
↓
localhost:8080
映射关系就建立起来了。
假设本地有接口:
http://localhost:8080/hello
那么公网就可以通过:
https://xxxx.ngrok-free.app/hello
访问。
整个流程:
浏览器 / 第三方服务器
↓
https://xxxx.ngrok-free.app/hello
↓
ngrok服务器
↓
ngrok隧道
↓
你的电脑
↓
localhost:8080
↓
/hello
↓
Spring Boot
八、放到微信公众号里怎么用?
假设我们的微信回调接口:
@PostMapping("/wx/callback")
public Object callback() {
// 处理微信回调
return null;
}
本地地址:
http://localhost:8080/wx/callback
微信服务器不能直接访问。
于是启动:
ngrok http 8080
获得公网地址:
https://xxxx.ngrok-free.app
那么微信公众号后台配置:
https://xxxx.ngrok-free.app/wx/callback
以后用户给公众号发送消息:
用户
↓
微信公众号
↓
微信服务器
↓
https://xxxx.ngrok-free.app/wx/callback
↓
ngrok
↓
你的电脑
↓
localhost:8080/wx/callback
↓
Spring Boot
这样就可以直接在本地调试微信公众号回调。
甚至可以直接在 IDEA 中打断点。
当微信服务器发起请求时:
@PostMapping("/wx/callback")
public Object callback() {
// ← 断点可以停在这里
}
这就是内网穿透在开发环境中非常实用的地方。
九、用了 ngrok,本地项目还需要启动吗?
当然需要。
这一点非常重要。
因为 ngrok 只是负责:
公网请求
↓
转发
↓
localhost:8080
真正处理请求的依然是:
Spring Boot
所以正常情况下需要同时保证:
① Spring Boot
localhost:8080
↑
│
② ngrok
公网地址 → localhost:8080
如果 Spring Boot 停了:
公网请求
↓
ngrok
↓
localhost:8080
↓
❌ 没有程序监听
请求自然失败。
如果 ngrok 停了:
公网请求
↓
❌ 找不到转发通道
外部也访问不到你的本地服务。
所以开发的时候可以简单理解为:
Spring Boot
+
ngrok
两个都需要运行。
十、内网穿透和部署服务器有什么区别?
这是初学者特别容易混淆的地方。
使用 ngrok
项目依然在:
你的电脑
运行。
结构:
公网
↓
ngrok
↓
你的电脑
↓
Spring Boot
所以:
电脑关机
IDEA停止项目
网络断开
ngrok关闭
都可能导致服务无法访问。
部署到云服务器
项目运行在:
云服务器
结构:
公网
↓
域名 / Nginx
↓
云服务器
↓
Spring Boot
这时候:
你的电脑关机
完全不会影响线上服务。
因此:
内网穿透不是部署。
更准确地说:
内网穿透只是给本地正在运行的服务临时提供一个公网访问入口。
十一、ngrok 和 Nginx 有什么区别?
两者看起来都有:
请求
↓
转发
↓
后端服务
但解决的问题不一样。
Nginx 常见场景:
用户
↓
www.example.com
↓
Nginx
↓
Spring Boot :8080
这里服务器本身通常已经能够被公网访问。
Nginx 主要负责:
反向代理
负载均衡
HTTPS
静态资源
请求转发
而 ngrok 主要解决:
我的服务藏在内网,没有公网入口怎么办?
例如:
公网
↓
ngrok
↓
你的笔记本电脑
↓
localhost:8080
所以可以简单记:
ngrok
↓
解决“公网怎么进来”
Nginx
↓
解决“请求进来以后怎么转发”
实际系统中两者甚至可以同时存在。
十二、ngrok 常见应用场景
内网穿透并不仅仅用于微信公众号。
很多第三方平台都需要主动调用你的服务器。
例如:
微信公众号回调
支付结果回调
GitHub Webhook
第三方登录回调
机器人 Webhook
短信服务回调
本地接口联调
临时 Demo 展示
这些场景都有一个共同点:
外部服务器需要主动访问你的服务。
如果你的服务还在:
localhost
就可以考虑在开发阶段使用内网穿透。
十三、使用内网穿透要注意安全
因为原来的:
localhost:8080
主要只有自己能够访问。
经过内网穿透以后:
https://xxxx.ngrok-free.app
可能可以被公网访问。
也就是说:
你的本地服务在一定程度上暴露给了互联网。
因此开发时要特别注意:
不要暴露数据库端口
不要暴露 Redis
不要暴露管理后台
不要关闭必要的鉴权
不要泄露 Token、密码等敏感信息
尤其不要为了测试方便,把:
MySQL
Redis
SSH
等敏感服务随意暴露到公网。
开发结束以后,不需要时就关闭 ngrok。
十四、一张图彻底理解 ngrok
最终只需要记住下面这张图:
公网用户 / 第三方服务器
│
│
▼
https://xxxx.ngrok-free.app
│
▼
ngrok 公网服务器
│
│
已建立的隧道
│
▼
本机 ngrok 客户端
│
▼
localhost:8080
│
▼
Spring Boot
所以:
公网地址
↓
ngrok
↓
本地端口
就是理解 ngrok 最核心的模型。
十五、总结
内网穿透听起来很复杂,其实核心非常简单。
你的 Spring Boot 原本运行在:
localhost:8080
外部服务器访问不到。
ngrok 帮你提供:
公网地址
并建立:
公网地址
↓
ngrok隧道
↓
localhost:8080
于是外部服务器就可以间接访问你的本地项目。
所以一句话总结:
内网穿透就是给内网中的本地服务提供一个公网入口;ngrok 则是一款常用的内网穿透工具,它通过公网服务器和本地客户端之间建立隧道,将公网请求转发到 localhost 等本地服务。
最后一定不要混淆:
ngrok ≠ 项目部署
ngrok 只是:
公网入口
↓
转发通道
↓
你的电脑
因此使用 ngrok 时,你的:
Spring Boot
依然需要在本地保持运行。
等真正上线以后,一般会变成:
开发阶段:
第三方服务器
↓
ngrok
↓
你的电脑
↓
Spring Boot
正式环境:
第三方服务器
↓
公网域名
↓
Nginx
↓
云服务器
↓
Spring Boot
理解这两张图,基本就把内网穿透、ngrok、本地开发和服务器部署之间的关系搞明白了。