Centos搭建Ngrok实现内网穿透

前言

首先说一下,什么是内网穿透?我举个栗子,比如你在本地搭建的网站,想让局域网外的人访问,该怎么实现?这里有个很多人都熟知的工具:花生壳。最开早我用的是向日葵+花生壳,一个实现远程连接;一个实现内网穿透;在后来自己买了阿里云服务器,感觉不用了很可惜,正好最近需要回家,要在家远程访问我的服务器。后来在网上查到有ngrok这样的神器。在这里记录一下自己的折腾之路。

安装环境

一台云服务器,一个域名,并且域名泛解析解析到云服务器,此处我用的服务器的操作系统为CentOS7(amd64)

安装gcc和git(用于下载ngrok源码)

1
2
yum install gcc -y
yum install git -y

安装go语言环境

1
yum install -y mercurial git bzr subversion golang golang-pkg-windows-amd64 golang-pkg-windows-386

检查环境安装

1
2
git --version //( >= 1.7 )
go version

在服务器上搭建Ngrok服务

下载ngrok源码

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

生成证书

1
cd ngrok

aiotwe.com这里修改为自己的域名

1
2
3
4
5
6
7
8
9
10
11
export NGROK_DOMAIN="aiotwe.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

将新生成的证书替换,执行下面命令后 “y” 回车 一行一行执行代码!

1
2
3
4
5
cp rootCA.pem assets/client/tls/ngrokroot.crt

cp device.crt assets/server/tls/snakeoil.crt

cp device.key assets/server/tls/snakeoil.key

编译生成ngrokd(服务端),生成在ngrok/bin/目录中,名字为ngrokd

1
GOOS=linux GOARCH=amd64 make release-server

编译生成ngrok(windows客户端),生成在ngrok/bin/windows_amd64/目录中,名字为ngrok

1
GOOS=windows GOARCH=amd64 make release-client

编译生成ngrok(Linux客户端),生成在ngrok/bin/目录中,名字为ngrok

1
GOOS=linux GOARCH=amd64 make release-client

开启远程服务

这里的远程服务指的是我们的有公网IP的服务器。

  • httpAddr # http端口(通过外网IP或域名加上这个端口进行http访问内网)
  • httpsAddr # 同http,只是这个是https
  • tunnelAddr #隧道端口,内网和外网建立的隧道端口,默认为4443(客户端配置连接的端口)

因为我的服务器本身有自己的Nginx所以占用了80端口,为了不冲突,这里使用了9000端口访问内网的http服务。

1
2
3
cd ngrok
sudo ./bin/ngrokd -domain="aiotwe.com" -httpAddr=":9000" -httpsAddr=":4430" -tunnelAddr=":8083" &
netstat -tpln|grep ngrokd #查看进程端口状态

这里并没有配置通过外网的什么端口连接内网的ssh。这个应该和客户端配置文件有关吧。

这里的端口号与config文件对应,视情况而定

1
2
3
4
5
[10:40:40 CST 2019/08/01] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [registry] [tun] No affinity cache specified
[10:40:40 CST 2019/08/01] [INFO] (ngrok/log.Info:112) Listening for public http connections on [::]:9000
[10:40:40 CST 2019/08/01] [INFO] (ngrok/log.Info:112) Listening for public https connections on [::]:4430
[10:40:40 CST 2019/08/01] [INFO] (ngrok/log.Info:112) Listening for control and proxy connections on [::]:8083
[10:40:40 CST 2019/08/01] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [metrics] Reporting every 30 seconds

显示此为成功开启

注意:一定要根据自己的实际情况在服务器后台安全组规则中开启或删除(我因为相对应的服务器安全组没开,卡了好久,希望可以帮助到大家)。例如我们这里的9000端口、4430端口和8083端口都要在安全组规则中开启。

我的安全组规则配置如下(2222端口、52222端口是为了访问内网ftp、ssh和远程桌面服务,在下面有介绍):

本地windows使用

本地windows配置

用winscp将ngrok/bin/windows_amd64/里的文件下载到本地Windows下,如D:\ngrok

D:\ngrok中新建文件,改名为ngrok.cfg
文件中输入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
server_addr: "aiotwe.com:8083"
trust_host_root_certs: false
tunnels:
http:
subdomain: "www"
proto:
http: "80"
https:
subdomain: "www"
proto:
https: "443"
ssh:
remote_port: 2222
proto:
tcp: "22"
mstsc:
remote_port: 52222
proto:
tcp: "192.168.123.35:3389"

注意要使用ssh端口,远程2222端口在安全规则中也要开启

开启windows客户机服务

这里的客户端就是指另外一台电脑,这一台电脑可以链接到服务器的电脑上,客户端常常是我们内网的电脑,这个就是ngrok实现的最大意义,可以和在公网的服务器通信之后,再直接访问内网电脑提供的服务,实现内网穿透。

在Windows中D:\ngrok新建文件 改名 start.bat

输入:

1
ngrok -config=ngrok.cfg start http https ssh mstsc

直接双击运行

表示成功,不成功的话看看自己的开启端口是否与config文件中对应,或查看服务器的远程端口是否在安全组中打开

!!!这很重要!!!

本地Linux使用

本地linux配置

用sftp工具将ngrok/bin/里的ngrok文件下载到本地Windows下,如/home/zdaiot/software/ngrok

/home/zdaiot/software/ngrok中新建文件,改名为ngrok.cfg
文件中输入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
server_addr: "aiotwe.com:8083"
trust_host_root_certs: false
tunnels:
http:
subdomain: "www"
proto:
http: "80"
https:
subdomain: "www"
proto:
https: "443"
ssh:
remote_port: 2222
proto:
tcp: "22"
mstsc:
remote_port: 52222
proto:
tcp: "192.168.123.187:3389"

注意要使用ssh端口,远程2222在安全规则中也要开启

这里解释一下配置文件的含义,配置文件为yaml语法,所有缩进需要使用空格。server_addr: "aiotwe.com:8083"表示使用8083端口实现客户端和服务端的交互。

1
2
3
4
http:
subdomain: "www"
proto:
http: "80"

这个含义表示使用外网的9000端口(服务器端httpAddr参数)访问内网80端口的http服务,且访问内网http服务时,域名为subdomain+domain+外网端口,另外我们这里subdomainwww,服务器端domain参数值为aiotwe.com,则我们想访问内网的http服务时,需要使用www.aiotwe.com:9000

1
2
3
4
ssh:
remote_port: 2222
proto:
tcp: "22"

这个含义为使用使用外网的2222端口访问内网的ssh服务或者sftp服务,例如,我们本地的用户名为zdaiot,那么在开启客户机服务后,可以使用ssh -p 2222 zdaiot@aiotwe.com访问内网的ssh服务,使用sftp -P 2222 zdaiot@aiotwe.com就可以访问内网的sftp服务。

1
2
3
4
mstsc:
remote_port: 52222
proto:
tcp: "192.168.123.35:3389"

这个含义为使用外网的52222端口访问内网的远程桌面服务。这个在下面有介绍。

另外,因为经常在Linux下跑程序,所以可以将tensorboard映射出去,用来观察程序的运行情况。将上述http端口从80改为tensorboard的6006端口即可。如下所示:

1
2
3
4
http:
subdomain: "www"
proto:
http: "6006"

这样,在我们跑程序的时候,使用类似于tensorboard --logdir=2019-08-01T11-39-22这样的指令开启tensorboard网页。然后在其他电脑上就可以使用http://www.aiotwe.com:9000访问tensorboard了。

开启Linux客户机服务

这里的客户端就是指另外一台电脑,这一台电脑可以链接到服务器的电脑上,客户端常常是我们内网的电脑,这个就是ngrok实现的最大意义,可以和在公网的服务器通信之后,再直接访问内网电脑提供的服务,实现内网穿透。

输入:

1
2
cd /home/zdaiot/software/ngrok
./ngrok -config=ngrok.cfg start http https ssh mstsc

另外,还有一个简单的写法,

1
2
cd /home/zdaiot/software/ngrok
./ngrok -config=ngrok.cfg start-all

表示成功,不成功的话看看自己的开启端口是否与config文件中对应,或查看服务器的远程端口是否在安全组中打开

!!!这很重要!!!

Linux远程桌面搭建

现在我们的需求是客户端为Linux系统,想通过另外一台电脑远程控制该客户机。操作如下:

在客户机上,安装xrdp

1
sudo apt-get -y install xfce4 xrdp vnc4server

配置xfce4桌面会话文件

1
2
echo xfce4-session>.xsession
cat .xsession

查看xrdp端口

1
2
cd  /etc/xrdp/
gedit xdrp.ini

如下图,发现使用的是3389端口。正好对应客户机的tcp: "192.168.123.187:3389"配置。

在另外一台装有windows的电脑,运行cmd,输入mstsc,输入远程链接aiotwe.com:52222,用户名zdaiot,点击连接。如下所示

即可连接到linux客户机。

服务器Ngrok开机自启

新建一个 /usr/local/ngrok/start.sh 文件并填入以下内容。

1
/usr/local/ngrok/bin/ngrokd -domain="aiotwe.com"   -httpAddr=":9000" -httpsAddr=":4430" -tunnelAddr=":8083" &

我的ngrok软件放置到了/usr/local目录

给权限:

1
chmod 755 /usr/local/ngrok/start.sh

新建ngrok启动脚本文件

1
sudo vi /etc/init.d/ngrok

文件内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/sh
#chkconfig:2345 70 30
#description:ngrok

ngrok_path=/usr/local/ngrok
case "$1" in
start)
echo "start ngrok service.."
sh ${ngrok_path}/start.sh
;;
*)
exit 1
;;
esac

提示 : 运行sudo vi /etc/init.d/ngrok之后 !!直接按键盘I进入编辑模式,然后复制下面内容 然后 “esc” “:” “wq” “!” “回车”意思是保存退出!

给ngrok脚本文件权限

1
2
cd /etc/init.d
chmod 755 ngrok

添加启动服务 ngrok

1
chkconfig --add ngrok

测试服务是否能启动成功

1
service ngrok start

查看自启动的服务 是否有 nrgok !!

1
chkconfig

执行这个代码如果出现后面的就OK了!! ngrok 0:off 1:off 2:on 3:on 4:on 5:on 6:off

服务器ngrok的服务端开机自动启动成功了!!!

客户端Ngrok开机自启

/home/zdaiot/software/ngrok目录,新建start.sh文件。在该文件中填入下面信息:

1
/home/zdaiot/software/ngrok/ngrok -config=/home/zdaiot/software/ngrok/ngrok.cfg start-all

添加可执行权限:

1
2
cd /home/zdaiot/software/ngrok
chmod +x start.sh

然后在/etc/init.d/目录下,新建mysetup.sh文件,填入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/sh
### BEGIN INIT INFO
# Provides: land.sh
# Required-start: $local_fs $remote_fs $network $syslog
# Required-Stop: $local_fs $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts the svnd.sh daemon
# Description: starts svnd.sh using start-stop-daemon
### END INIT INFO

#任务脚本
#进入要执行脚本目录
cd /home/zdaiot/software/ngrok
#取得root权限,'123'为密码,不用加引号,'ls'无实际作用
echo 123|sudo -S ls
#执行脚本./start.sh,sudo -S需要加上
sudo -S /home/zdaiot/software/ngrok/start.sh
#任务脚本

修改权限

1
sudo chmod 755 /etc/init.d/mysetup.sh

设置启动顺序

1
2
cd /etc/init.d
sudo update-rc.d mysetup.sh defaults 95

其中数字95是脚本启动的顺序号,按照自己的需要相应修改即可。在你有多个启动脚本,而它们之间又有先后启动的依赖关系时你就知道这个数字的具体作用了。

卸载启动脚本

1
2
cd /etc/init.d
sudo update-rc.d -f mysetup.sh remove

参考

Centos搭建Ngrok实现内网穿透
ngrok配置过程
更改xrdp,设置一个端口
怎么用运行命令mstsc连接到远程计算机
Ubuntu 安装远程桌面
ngrok 开机启动设置
Ubuntu开机启动脚本

------ 本文结束------
坚持原创技术分享,您的支持将鼓励我继续创作!

欢迎关注我的其它发布渠道