通过ngrok实现内网穿透

ngrok和ssh-tunnel做的事有点像,ngrok专注于将一个本地服务器暴露到公网。

它的工作原理是首先有一个公网的ngrok服务器,然后在内网需要暴露的机器上通过ngrok客户端建立tunnel来暴露指定端口。

国内有一些免费的ngrok服务器,也可以自己搭建,这里我自己搭建。

搭建ngrok服务器

参考:https://zhuanlan.zhihu.com/p/149968878

下载源码

1
2
git clone https://github.com/inconshreveable/ngrok.git
cd ngrok

生成证书

1
2
3
4
5
6
7
cd keys
export NGROK_DOMAIN="ngrok.kyo86.com"
openssl genrsa -out rootCA.key 2048
openssl req -x509 -new -nodes -key rootCA.key -subj "/CN=$NGROK_DOMAIN" -days 5000 -out rootCA.pem
openssl genrsa -out device.key 2048
openssl req -new -key device.key -subj "/CN=$NGROK_DOMAIN" -out device.csr
openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days 5000

替换证书

1
2
3
4
cp rootCA.pem ../assets/client/tls/ngrokroot.crt
cp device.crt ../assets/server/tls/snakeoil.crt
cp device.key ../assets/server/tls/snakeoil.key
cd ..

编译linux服务端

1
2
set GOOS=linux GOARCH=amd64
make release-server

编译linux客户端

1
2
set GOOS=linux GOARCH=amd64
make release-client

注意:因为客户端和服务器在编译时都使用了证书,所以他们是一一对应的,就是说ngrok客户端并不是通用的,不能用来连接其他的ngrok服务器。

启动服务器端

1
./bin/ngrokd -domain=ngrok.kyo86.com -tlsKey=./keys/device.key -tlsCrt=./keys/device.crt -httpAddr=:30080 -httpsAddr=:30443

服务器端默认使用4443端口,所以需确保防火墙允许4443端口访问

在客户端建立端口映射

创建配置文件ngrok.cfg

1
2
server_addr: "ngrok.kyo86.com:4443"
trust_host_root_certs: false

暴露服务器有两种方式:

一是在运行服务器时指定的http和https端口通过子域名的方式来暴露web服务

二是通过随机端口来暴露指定的tcp端口

暴露WEB服务

把本地的8080(http)端口映射到通过 http://jupyter.ngrok.kyo86.com:30080 访问

1
./ngrok -config=ngrok.cfg -subdomain=jupyter -proto=http 8080

访问子域名需要指定泛域名解析,即 *.ngrok.kyo86.com 的解析。

如果不指定-proto默认就是http+https

暴露TCP端口

把本地的22(tcp)端口映射到 ngrok.kyo86.com上的一个随机端口

1
./ngrok -config=ngrok.cfg -proto=tcp 22