有时候,我们希望外网能够访问本地 localhost 起的服务,一个比较典型的场景就是小程序开发时,希望在本地接收微信服务器的回调,怎么办呢?这里总结了内网穿透的两种方法:
- 通过软件 ngrock
- 通过 ssh 反向代理
ngrock 内网穿透
ngrock 功能很强大,使用起来也比较简单:
-
首先去官网下载,下载完成并解压之后得到了一个 ngrok 可执行文件
-
注册账号,获取 authtoken,然后运行生成配置文件
$ ./ngrok authtoken xxx
-
代理本地服务
$ ./ngrok http 3030
然后 ngrok 就会显示 http 和 https 的外网地址,访问下面这两个地址就能映射到本地 3030 端口开启的服务了。
Session Status online Account xxx (Plan: Free) Version 2.3.35 Region United States (us) Web Interface http://127.0.0.1:4040 Forwarding http://6b6e94b6d845.ngrok.io -> http://localhost:3030 Forwarding https://6b6e94b6d845.ngrok.io -> http://localhost:3030 Connections ttl opn rt1 rt5 p50 p90 0 0 0.00 0.00 0.00 0.00
由于 ngrock 的服务器在国外,有时候服务不是很稳定,而且免费版的外网地址不是固定的,每次运行软件都会变,因此比较适合用于测试环境。
ssh 反向代理
另一种方式是 ssh 反向代理,前提条件是自己要有一台云服务器。只要一句命令即可进行内网穿透,例如将本机的 3031
的端口反向代理到服务器的 9999
端口:
$ ssh -NR 9999:localhost:3031 用户名@公网主机地址 # 前台执行
$ ssh -NfR 9999:localhost:3031 用户名@公网主机地址 # 后台执行
上面的参数含义是:
-N
ssh不执行命令-f
后台执行-R
反向代理
这个时候,如果你登录到服务器,访问:http://localhost:9999
则相当于访问本地 3031 端口启动的服务。不过需要注意一下,此时代理并未暴露到公网,也就是说你在服务器访问 http://0.0.0.0:9999
的时候,是不通的。这个时候,需要修改服务器上的 sshd
的配置文件:
$ vi /etc/ssh/sshd_config
然后输入 /
进入搜索模式,再输入 GatewayPorts
定位到下面这一行,把注释取消掉并把 no 改成 yes:
#GatewayPorts no
GatewayPorts yes # 取消注释,并把no修改为yes
最后重启 sshd
:
$ service sshd restart
GatewayPorts 这个选项能够让反向代理的 ip 为公网 ip(0.0.0.0
),而不是 loopback 的 ip(127.0.0.1
),那怎么查看到底有没有开启成功呢?可以在服务器上执行下面的命令:
$ netstat -tnl | grep 9999
# 如果开启成功,会显示下面的 0.0.0.0
tcp 0 0 0.0.0.0:9999 0.0.0.0:* LISTEN
# 如果开启失败,会显示下面的 127.0.0.1
tcp 0 0 127.0.0.1:9999 0.0.0.0:* LISTEN
弄好之后,就可以让公网主机代理本地服务啦:
curl 公网主机ip:9999 # 会转发到本地3031端口