内网穿透的两种方法

1,294 阅读2分钟

有时候,我们希望外网能够访问本地 localhost 起的服务,一个比较典型的场景就是小程序开发时,希望在本地接收微信服务器的回调,怎么办呢?这里总结了内网穿透的两种方法:

  1. 通过软件 ngrock
  2. 通过 ssh 反向代理

ngrock 内网穿透

ngrock 功能很强大,使用起来也比较简单:

  1. 首先去官网下载,下载完成并解压之后得到了一个 ngrok 可执行文件

  2. 注册账号,获取 authtoken,然后运行生成配置文件

    $ ./ngrok authtoken xxx
    
  3. 代理本地服务

    $ ./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 用户名@公网主机地址 # 后台执行

上面的参数含义是:

  1. -N ssh不执行命令
  2. -f 后台执行
  3. -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端口