使用Docker搭建Ngrok服务器实现内网穿透
简介
ngrok是通向本地的安全隧道。主要可以实现下面几种需要:
- 把本地的或者局域网内的web服务,暴露到一个公网ip或域名下
- 把本地的或者局域网内的tcp端口,映射到一个公网ip的端口下
举例:
- 需要要在本地调试微信公众号程序,但微信服务器的报文只能发到指定域名,这个时候,可以用ngrok把本地的web程序映射到指定域名。所有微信服务器的报文发到指定域名后,ngrok会把它转发到本地web程序。
- 公司局域网内有台linux服务器,因为一某些原因,你需要从家里登录它,但你又没有公司路由的权限,无法做路由的端口映射。这个时候,要把服务器的ssh端口,用ngrok映射vps的某个端口下,回家之后直接登录vps,ssh映射的端口,就可以登录。
基本要求
- 一台有公网ip的vps
- 一个域名
操作步骤
我是直接拿别的写的dockerfile用的,这是地址
安装docker
1 |
|
构建镜象
1 |
|
这里需要一些时间下来镜象
sed -i '1cFROM golang:1.8.3' Dockerfile
这里是把第一行替换成FROM golang:1.8.3
因为原来的FROM golang:1.7.1-alpine
会造成编译出来的文件无法在Ubuntu上执行。
见之前写的一篇文章记一次文件无法执行的查错过程
设置域名
假如你有 xxx.com 这个域名。
你拿出ngrok.xxx.com这个子域去做映射
需要在 dns 服务商那里把
为ngrok.xxx.com增加一条A记录,指向vps的ip。
并为*.ngrok.xxx.com
增加一条A记录,也指向vps的ip。
运行镜象
1 |
|
这里把容器内的端口直接按源来的映射出来了,可以实际需要要修改。
运行后,会要等一段时间,因为要编译客户端。
运行客户端
稍后会在/data/ngrok/bin/
目录下生成客户端程序
每个平台的版本都有。
以windows64位来说,在windows_amd64
目录下。
拷贝到自己的windows电脑上。
新建配置文件t.config
1 |
|
放在和ngrok.exe相面的目录,并打开命令行窗口,并运行
1 |
|
如果成功的话,会显示
1 |
|
这样外网访问http://example.ngrok.xxx.com, 就会映射到本地的8080端中web服务器。
如果运行:
1 |
|
就会把本的22端口映射到服务器上一个随机端口。
原理
本质上也是一种隧道技术。分服务器端和客户端。
客户端发起连接(用到上面的4443端口)。
服务端接到连接的参数,另发起一个隧道。
将接收到exmaple域名的数据,加密转发到客户端。
客户端再转到指定端口
注意事项
在运行docker之后,会有一段时间cpu使用率很高,是在编译go中的内容。
因为ngrok有心跳机制,每次心跳均会产生日志,所以以docker方式运行,会产生很多日志。
实测试中,大概每个星期会产生100M的日志文件。
查年docker日志文件位置sudo docker inspect <id> | grep LogPath
查看大小sudo ls -lh /var/lib/docker/containers/<id>/<id>-json.log
常见错误
启动客户端后,发现连接失败。
检查域名映射有没有问题(nslookup)
检查那三个端口有没有在服务器上打开(telnet )
检查服务端日志Failed to read message: read tcp 172.17.0.2:4443->119.xxx.xxx.49:51214: read: connection reset by peer
检查服务器证书是不是正确的
进入/data/ngrok目录,找到device.csr文件
运行openssl req -noout -text -in device.csr
检查Subject: CN
是否为刚才设置的域名。
检查配置文件中的域名与端口有没有配置错误。
再把ngrok拷贝到linux下时,还可能会遇到这样的问题ngrok: No such file or directory
扩展用法
服务器上的80端口和443端口上很宝贵的,如果被ngrok点用的话,别的服务就使用不了。
解决这个问题,可能在运行镜像的时候,去掉80与443端口的映射,直接用nginx转发到相应的端口。
参考
https://ngrok.com/
https://hteen.cn/docker/docker-ngrok.html
https://imququ.com/post/self-hosted-ngrokd.html