Popular blog tags

Ngrok内网:穿透原理解读(Intranet Penetration)、常见穿透工具、开源内网穿透项目

Published

内网穿透工具的现状

1.收费的内网穿透工具

目前市面上提供类似服务的有花生壳、TeamView、GoToMyCloud等等,但天下没有免费的午餐,要使用第三方的公网服务器就必须为第三方付费,并且这些服务器都有各种各样的限制。

此外,由于数据包会流经第三方,因此对数据安全也是一大隐患。

2.开源的内网穿透工具项目

 

内网穿透原理的原理

很多时候,我们都有这样的需求:

需要将本地正在开发的服务暴露在公网上,也就是从外网直接访问我们本机上的服务。正常情况下,这是办不到的,因为我们的本机并没有公网IP,我们的本机处在内网当中。 这里需要顺手提及一个知识:NAT穿透。我们的机器一般都在路由器的内网当中,IP地址基本上都是192.168.x.x系列,我们并没有公网IP,那么如何访问外网呢?

 

内网穿透-Intranet Penetration

远程桌面控制软件Teamviewer背后的原理

具体流程是这样的。我们需要一个有公网IP的服务器C,然后从本地A向C访问,和C握手、建立稳定的信道。在外网的设备B向C发送请求,C通过刚才建立的稳定信道将请求转发给A。A收到请求后将响应发给C,C再将响应返给B。这样B就能访问到内网A的资源了。

 

我们打开浏览器访问Google,Google与我们主机之间如何通信?

假设我们主机IP为192.168.0.100,路由器LAN IP为192.168.0.1,WAN IP为211.22.145.234(这是一个公网IP),Google服务器IP为74.125.204.101。详细通信流程如下。

主机构建HTTP请求数据包,目标IP为74.125.204.101,目标端口80,源IP为192.168.0.100,源端口随机生成,假定为5000。

主机检查目标IP地址,发现不在一个网段,数据包丢给默认网关(192.168.0.1)。

路由器LAN口收到数据包,构建NAT映射,随机生成端口,假定为5500,这样映射就是 :

5500 -> 192.168.0.100:5000。

WAN口收到的数据包,如果目标端口是5500,则转发给内网IP为192.168.0.100的机器的5000端口。 路由器修改数据包的源端口为5500,源IP地址为211.22.145.234,使用WAN口将数据包发送出去。

Google服务器收到请求,构建响应HTTP数据包,目标IP地址211.22.145.234,目标端口为5500。

路由器WAN口收到数据包,目标端口为5500,查询NAT表,发现对应的机器是192.168.0.100:5000,所以修改目标IP为192.168.0.100,目标端口为5000。并通过LAN口发送给主机。

主机接收到数据包,完成这一次通信。

从上面可以看出,内网机器能够和外网通信,全靠拥有公网IP的路由器做交通枢纽。路由器通过查询NAT表,来确定数据包该发送给内网哪台机器。所以内网多台机器都可以通过这一台路由器和外网进行通信。这极大的节省了宝贵的公网IP资源。 NAT表项是在内网主动和外网通信的过程中构建的,如果外网主动访问内网,那么自然没有表项,也就访问不到。

如果想要从外网访问内网,根据上面的原理我们可以有两种做法。

首先,我们可以手动添加NAT表项。大部分路由器里面都有这个设置项。我的NETGEAR路由器的设置页面如图所示。

另一种办法,是找一个公网服务器做中介。比如服务器A。流程如下。 开发主机和服务器A构建一条连接 用户访问服务器A 服务器A联系开发主机获取内容 服务器A将获取到的内容发送给用户 通过上面的流程,就实现了用户访问到了我们内网的内容。

那么帮助我们实现这个功能的程序就是Ngrok。通过在服务器上安装Ngrok,我们就可以和本地主机构建一条隧道。来让外网用户访问本地主机的内容。

以下是安装Ngrok的详细步骤。

首先,下载代码。

git clone https://github.com/inconshreveable/ngrok.git ngrokcd ngrokcopy code

第二步,生成我们自己的证书。我们首先要想好一个基础域名(NGROK_BASE_DOMAIN)。比如我选择tunnel.cjting.me,那么我之后就会使用*.tunnel.cjting.me来访问相应的本地服务。

openssl genrsa -out base.key 2048openssl req -new -x509 -nodes -key base.key -days 10000 -subj "/CN=[NGROK_BASE_DOMAIN]" -out base.pemopenssl genrsa -out server.key 2048openssl req -new -key server.key -subj "/CN=[NGROK_BASE_DOMAIN]" -out server.csropenssl x509 -req -in server.csr -CA base.pem -CAkey base.key -CAcreateserial -days 10000 -out server.crtcopy code

第三步,拷贝证书文件,然后编译相应的客户端和服务器程序。

cp base.pem assets/client/tls/ngrokroot.crtGOOS=linux make release-linux #

服务器是linux,我们需要交叉编译make release-client # 客户端运行在我们自己的机器上copy code

第四步,将相应的文件传送到服务器上,并启动服务器程序。服务器程序需要第二部生成的server.crt和server.key。 mkdir releasecp bin/linux_amd64/ngrokd release/cp server.crt server.key release/scp -r release/ root@[host]:~/ngrokssh root@[host]cd ~/ngrok./ngrokd -tlsKey=server.key -tlsCrt=server.crt -domain="[NGROK_BASE_DOMAIN]" -httpAddr=":80" -httpsAddr=":443"copy code

第五步,配置域名解析。解析[NGROK_BASE_DOMAIN]以及*.[NGROK_BASE_DOMAIN]地址到服务器上。我使用的是DNSPOD,截图如下。

最后一步,配置客户端,启动客户端程序。

客户端的默认配置文件位置是$HOME/.ngrok,填入以下配置。 server_addr: [NGROK_BASE_DOMAIN]:4443trust_host_root_certs: falsecopy code 然后启动客户端。 ./ngrok -subdomain test 8080copy code 客户端会转发本地8080端口的服务到test.[NGROK_BASE_DOMAIN]上。以我为例,只要我访问test.tunnel.cjting.me,就可以看到开发主机上8080端口的内容。实现了外网访问内容的目标。

最后提一点:客户端和服务器连接是需要验证证书的。只有我们同时编译的客户端和服务器才能连接上。在新的电脑上重新编译客户端去连接一个已部署的服务器,是无法连接的。因此建议存档一份客户端程序。

 

一些反向代理服务同类产品 


远程连接内网机器的桌面服务是最常见的需求,有时候我们希望做的是自己的机器上跑一些服务能够从外网访问,比如demo,博客,甚至私有云等等。

 Ngrok and Cloudflared. Does ZeroTier/Tailscale

TeamViewer和向日葵大家可能都知道,我说一些不一样的。

A tunnel is a secure connection between your localhost and the internet. Here is a quick list of tunneling services available

Some popular services include:

Ngrok
Localtunnel
Telbit
Localhost.run
Cloudflare tunnel

 

ngrok - comes with a free tier that allows for up to 4 tunnels and 40 connections per minute.


tunnelto.dev - tunnelto is an open-source software that is available on GitHub with no vendor lock-in. However, if you don't want to do the setup yourself, there is a $2 option for up to 50 dedicated custom subdomains <yourapp>.tunnelto.dev


localtunnel - localtunnel is another open-source MIT licensed project that lets you expose your localhost for easy testing and sharing. All you have to do is install it and run npx localhost --port 8000.


Cloudflare - Cloudflare is a cloud hosting service that provides a content delivery network and DDoS mitigation. In addition to this, Cloudflare also provides a free tunnel service that we will be using to demonstrate how to use tunnels.


There are also a number of paid options:

 pagekite, Forward and Burrow.io.

 

no-IP

https://www.noip.com/

国外的no-IP解析,每年三百多大洋,评论不错,纯英文的界面,使用谷歌翻译还是很流畅的。


frp


开源界最流行的反向代理之一,frp全称FaskReverseProxy,它的目标是做最快速可靠的反向代理,用GO语言实现,在Github上正在快速迭代中。安装和配置都非常简单,只需要几个命令就可以完成。frp支持的客户端非常丰富,树莓派,路由器,安卓手机等等,可玩性很高。

frp服务可以让你本地的web项目提供给外网访问,特别适合向别人展示你本机的web demo 以及调试一些远程的API (比如微信公众号,企业号的开发)。

FRP还可以轻松代理TCP,HTTPS,SSH等等协议,你需要有一台具有公网IP的机器,最好加一个域名。

 


ngrok


曾经是开源界反向代理软件的老大,到2.0以后选择闭源,最后开源的版本2016年后就没有再更新,止于1.7。基于C语言实现,配置略复杂,不过据说灵活性和稳定性超好。

ngrok也可以代理常见的各种协议,自己搭建只能用早期的开源版本。或者选择商业公司提供的收费服务,国内外可以搜到很多提供NGROK服务的网站,可不可靠不太敢说,但真的很多。

这里列举一些知乎推荐过的,你也可以通过ngrok这个关键字搜索到很多。

ZeroTier

这是个很牛的技术,它能虚拟出一个虚拟局域网络,所有位于这个虚拟局域网之内的设备都能像位于一个物理局域网之中那样自由的互相访问了 。因为毕竟是国外的技术,服务器在国外,有时候虚拟出来的局域网各节点不能直连.

Tailscale

 

natapp.cn
小米球
Sunny-Ngrok
echosite

 

dog-tunnel
翻译过来就是狗洞吧,国人做的,基于GO语言开发,在GitHub上活跃度还不错,有1k+的星星,有兴趣可以试一下。

 


serveo.net


无需注册,无需配置,只需要 ssh 就行,没有客户端,支持多端口映射,支持自定义子域名,只要一行代码。

ssh -R 80:localhost:3000 http://serveo.net
我试了一下,临时用一下真的很棒!

nat123和花生壳,一步一步诱导你付费,协议,端口,流量,速度,域名每个细节都要收费.

nat123

http://www.nat123.com/

花生壳

 

想从外网访问内网服务的4 种方式

没有公网 IP,所以想从外网访问内网服务,目前已经实践了 3 种方式,而第 4 种则是我们今天准备实践的

第一种是基于 Zerotier、Tailscale 等第三方 VPN 软件。

优点是不需要有自己的公网服务器,安装简单,但是缺点是需要在访问的机器上安装客户端软件,在打洞失败的时候,需要通过公共服务器中转,会导致速度的下降;

外网访问群晖的新方案Tailscale


第二种是基于 frp、nps 、ngrok 等内网穿透软件。

优点就不说了,缺点是需要有一台具有公网 IP 的服务器来安装 Server 端软件;

轻量级内网穿透代理服务器nps试用


第三种是混合了第一种和第二种的混搭,比如 AnyLink。

因此也同时具备了 1 和 2 的缺点
企业级远程办公vpn软件AnyLink


第四种就是 Cloudflared。

优点是不再需要用到有公网 IP 的 VPS 搭建服务,因为我们可以使用 Cloudflare 平台提供的 Cloudflare Tunnels,不仅如此,还可以不需要反向代理,不需要备案就可以使用 80 和 443 端口,也再不需要自己申请 SSL 证书,而且这一切都是免费的
什么是 Cloudflared

 

内网穿透开源项目

 

SpringHgui/FastTunnel 开源c#

FastTunnel是一款高性能跨平台开源c#内网穿透工具,使用它可以实现在公网上访问您的内网服务。

https://github.com/SpringHgui/FastTunnel

FastTunnel blog:https://www.cnblogs.com/mq0036/p/15029706.html

使用 FastTunnel 做内网穿透远程计算机步骤:https://mp.weixin.qq.com/s/w594zXv4IUHrvP0JOYys0Q

Wireboy.Socket.P2PSocket 开源c#

P2P内网穿透,开源c#,实现【公司】-【家】远程控制

https://github.com/bobowire/Wireboy.Socket.P2PSocket

 

使用.NET 开发的 开源端口映射工具

https://github.com/yangan666/SuperNAT

https://github.com/SpringHgui/FastTunnel

https://github.com/hemaju/Wireboy.Socket.P2PSocket

https://github.com/xljiulang/HttpMouse 

 

nps    go语言

https://gitee.com/mirrors/nps/tree/master/client

nps

 

 

 

.