在那个只有零和一的世界里,对零的向往,终究是一的执着。

正在下载:ngrok_1.7.1.zip 使用ngrok服务进行内网穿透

准备环境

公网服务器:centos 7的vps

域名解析:解析域名xxx.xxx地址到vps

编译环境:


yum install build-essential golang mercurial git openssl

编译程序

从上面准备的编译环境可以看出,此步使用到的有c++编译器(代码的实现部分),go语言环境(猜测是与支持编译全平台包括linux、windows和mac程序有关),分布式项目管理器(项目依赖支持)和openssl(安全验证)。下面按顺序进行:

获取源码

新建一个根目录ngrok,再建子目录src,进入src,使用git命令获取源码(或者解压我附件打包的源码):


git clone https://github.com/inconshreveable/ngrok.git ngrok

生成证书

返回根目录,新建子目录cer,进入cer,执行以下脚本将指定的域名xxx.xxx绑定到新生成的证书密钥并拷贝三个文件替换源码中的证书和密钥:


NGROK_DOMAIN="xxx.xxx"
 
openssl genrsa -out base.key 4096
openssl req -new -x509 -nodes -key base.key -days 10000 -subj "/CN=$NGROK_DOMAIN" -out base.pem
openssl genrsa -out server.key 4096
openssl req -new -key server.key -subj "/CN=$NGROK_DOMAIN" -out server.csr
openssl x509 -req -in server.csr -CA base.pem -CAkey base.key -CAcreateserial -days 10000 -out server.crt
 
cp base.pem ./../src/ngrok/assets/client/tls/ngrokroot.crt
cp server.crt ./../src/ngrok/assets/server/tls/snakeoil.crt
cp server.key ./../src/ngrok/assets/server/tls/snakeoil.key

编译程序

这套程序总共需要编译两个程序,一个是将运行在vps上面的服务端程序(提供转发服务),另一个是运行在需要被穿透机器上的客户端程序。上面提到,这个项目支持生成多个系统平台的程序,此处我将指定环境变量GOOS和GOARCH编译linux和windows两个平台的程序,其中vps运行linux64位的服务端程序ngrokd,客户端运行windows32位程序ngrok.exe。

返回根目录,新建子目录bin,进入bin,再分别建立两个目录centos和win;返回根目录,进入src,然后执行以下命令进行编译并拷贝程序:


cd ngrok
GOOS=linux GOARCH=amd64 make release-server release-client
cp ./bin/ngrok* ./../../bin/centos
GOOS=windows GOARCH=386 make release-server release-client
cp ./bin/windows_386/ngrok* ./../../bin/win
#GOOS=darwin GOARCH=amd64 make release-server release-client

至此,我们需要的程序已经都准备好了,下面就可以开始将服务搭建运行起来测试了。

运行服务

服务程序ngrokd运行可以指定几个参数,-tlsKey指定服务器私钥,-tlsCrt指定服务器证书,-domain指定解析的域名(和编译前证书绑定的一致),-httpAddr和-httpsAddr分别指定代理的http和https服务使用的固定端口(提供的http或https转接服务是通过客户端指定子域来识别客户端的,而tcp转接服务则是通过服务端随机使用的端口返回给客户端生成唯一可识别的地址,因此使用http*转接服务还需要给域名添加泛解析*.xxx.xxx到vps地址),-tunnelAddr指定连接隧道的固定端口。程序运行后,本地便会开启三个端口监听连接来提供服务,等待客户端的连接。这三个端口在本地网络环境中可以访问,但是外部网络想要连接还需要解除防火墙限制,可以指定服务程序也可以指定端口进行解除。

下面返回根目录运行以下脚本启动服务并解除防火墙限制:


port1=xxx1
port2=xxx2
port3=xxx3
echo "http port = $port1"
echo "https port = $port2"
echo "tunnel port = $port3"
firewall-cmd --zone=public --add-port=$port1/tcp --permanent
firewall-cmd --zone=public --add-port=$port2/tcp --permanent
firewall-cmd --zone=public --add-port=$port3/tcp --permanent
#firewall-cmd --zone=public --remove-port=$port/tcp --permanent
firewall-cmd --complete-reload
firewall-cmd --zone=public --list-ports
ss -an |grep $port1
ss -an |grep $port2
ss -an |grep $port3
./bin/centos/ngrokd -tlsKey=./cer/server.key -tlsCrt=./cer/server.crt -domain="xxx.xxx" -httpAddr=":$port1" -httpsAddr=":$port2" -tunnelAddr=":$port3" >> start.log 2>&1 &

这样,顺利的话服务程序就正常运行,并在根目录下生成日志文件,开始记录一些连接日志。

客户端连接

其实,这里的客户端,是对于ngrok这个项目来说,前面服务器提供转发服务,现在客户端去连接服务器,要求提供转发,所以此时运行的机器可以称之为客户端。但同时,需要连接服务器提供转发服务的机器,本身就是因为自己需要对外提供服务,所以才借助这个“客户端”程序去连接提供转发服务的“服务端”程序来实现中转的,这样外面就可以通过访问服务端的指定地址去间接的访问这个“客户端”提供的服务了,因此,这个“客户端”对外面的机器来说实际上是个“服务端”,比如,一个内网里的http服务器、内网里的远程桌面服务或者一个后门木马等。

下面,在需要被穿透的内网机器上运行客户端ngrok.exe连接服务器建立隧道进行通讯测试:


ngrok.exe -proto=http -subdomain ngrok -config=ngrok.cfg 80 #转接http服务
ngrok.exe -proto=https -subdomain ngrok -config=ngrok.cfg 443 #转接https服务
ngrok.exe -proto=tcp -subdomain ngrok -config=ngrok.cfg 3389 #转接远程桌面连接服务

其中,ngrok.cfg为简单的服务器连接配置文件,其内容如下:


server_addr: xxx.xxx:xxx3
trust_host_root_certs: false

顺利运行的话就会启动一个窗口显示连接状态,连接成功后会生成一个特定的服务端地址供外部机器访问,来提供内网的服务。另外,窗口会显示一个本地web接口,浏览器访问能观察更详细的连接动态。

http服务转发

https服务转发

tcp服务转发

穿透测试

一切准备就绪之后,就可以测试穿透内网了。此时,其他内网中通过浏览器访问http://ngrok.xxx.xxx:xxx1或者https://ngrok.xxx.xxx:xxx2就能访问到本地的80或者443端口了,如果本地搭建了http和https服务,便能直接通过两个链接来访问本地的网站了。或者,在其他内网中通过windows的远程桌面连接xxx.xxx:xxx3地址,并输入本地的用户名和密码,就能够直接控制本地系统进行远程操作了。以上本人均实际测试过,这里偷个懒就不贴图来证明了,感兴趣的自己动手实践一下才是王道。另外,不想自己搭建服务的话可以直接访问ngrok的官网,注册一下使用免费的服务和客户端(稳定性和速度不敢保证),也非常容易测试效果。