ngrok是一套反向代理、可以实现内网穿透的开源工具。
再直白一些,开发阶段,你家里的电脑上跑着一套web服务,想让好友帮你测试,但是又不想一遍一遍地把web服务发布到服务器上怎么办?用ngrok可以实现让别人从外网访问到你家里的电脑上的一个web服务。
前期准备:
- 有相对固定的公网IP的服务器;
- 有域名。
按照以下步骤安装:
1.编译ngrok
1.1 首先装必要的工具
我购买的是阿里云香港 VPS ,系统是 Ubnuntu, 所以使用如下命令:
sudo apt-get install build-essential golang mercurial git
1.2 获取 ngrok 源码
cd /usr/local
git clone https://github.com/inconshreveable/ngrok.git
cd ngrok
1.3 生成证书
生成并替换源码里默认的证书. 注意修改为自己的域名.(之后编译出来的服务端客户端会基于这个证书来加密通讯, 保证安全性)
export NGROK_DOMAIN="mydomain.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 server.key 2048
openssl req -new -key server.key -subj "/CN=$NGROK_DOMAIN" -out server.csr
openssl x509 -req -in server.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out server.crt -days 5000
在软件源代码目录下面会生成一些证书文件, 我们需要把这些文件拷贝到指定位置
cp rootCA.pem assets/client/tls/ngrokroot.crt
cp server.crt assets/server/tls/snakeoil.crt
cp server.key assets/server/tls/snakeoil.key
如果是在国内的服务器需要执行此步, 香港或者国外的服务器不需要
vim /usr/local/ngrok/src/ngrok/log/logger.go
log "github.com/keepeye/log4go"
1.4 编译服务端
make release-server
1.5 编译客户端
使用不同的编译选项来选择编译以后生成的平台
这里我主要是生成了 windows 和 Linux 的版本. 继续在原先的目录下:
#Linux平台64位系统
GOOS=linux GOARCH=amd64 make release-client
#Windows平台64位系统
GOOS=windows GOARCH=amd64 make release-client
编译选项解释:
GOOS 是指编译出来的操作系统 (windows,linux,darwin)
GOARCH 是指对应的构架 (386,amd64,arm)
Linux平台32位系统: GOOS=linux GOARCH=386
Linux平台64位系统: GOOS=linux GOARCH=amd64
Windows平台32位系统: GOOS=windows GOARCH=386
Windows平台64位系统: GOOS=windows GOARCH=amd64
MAC平台32位系统: GOOS=darwin GOARCH=386
MAC平台64位系统: GOOS=darwin GOARCH=amd64
ARM平台: GOOS=linux GOARCH=arm
如果一切正常,ngrok/bin 目录下应该有 ngrok, ngrokd 等文件。其中ngrokd是服务端, ngrok是客户端。
通过前面的步骤, 就会在 bin 目录里面生成所有的客户端文件, 客户端平台是文件夹的名字. 客户端放在对应的目录下, 当前 Linux 平台客户端在bin目录. 然后我们就可以打个包, 把所有文件下载到自己的本机了。
2 运行并测试
2.1 启动服务器端 ngrokd
首先执行VPS上的服务器端 ngrokd, 这里的 8080 指的是服务器启用 8080 端, 就是说内网穿透后的域名为xxx.mydomain.com:8080. 如果在 80 端口未作他用的情况下, 也可将 8080 端口改为 80, 这样更方便些. 而如果我们 VPS 的 80 端口被占用了, 但是我们还想用 80 端口作为服务端口, 那么可以使用 nginx 做一个 xxx.mydomain.com 的反向代理.
#执行 ngrokd
/usr/local/ngrok/bin/ngrokd -domain="mydomain.com" -httpAddr=":8080"
2.2 写客户端配置文件
在 ngrok.exe 所在目录下建立文件 ngrok.cfg, 用记事本等文本编辑器写入以下内容并保存.
#配置文件 ngrok.cfg 的内容
server_addr: "mydomain.com:4443"
trust_host_root_certs: false
2.3 映射 HTTP
假设子域名是test,则先添加泛解析 test (类型为 CNAME) 到 mydomain.com
之后打开 Windows 服务器,这里以 80 端口为例。打开命令提示符,切到 ngrok.exe 所在目录,并执行以下命令。
# 启动 ngrok 客户端
# 注意:如果不加参数 -subdomain=test,将会随机自动分配子域名。
ngrok -config=ngrok.cfg -subdomain=test 80
正常情况下,客户端上会显示以下内容,表示成功连接到服务器端。
# 客户端ngrok正常执行显示的内容
ngrok (Ctrl+C to quit)
Tunnel Status online
Version 1.7/1.7
Forwarding http://test.mydomain.com:8080 -> 127.0.0.1:80
Forwarding https://test.mydomain.com:8080 -> 127.0.0.1:80
Web Interface 127.0.0.1:4040
# Conn 0
Avg Conn Time 0.00ms
打开浏览器, 分别在地址栏中输入 http://localhost 和 http://test.mydomain.com:8080, 如果后者正常显示并且和 http://localhost 显示的内容相同, 则证明我们已经成功了.
2.4 映射TCP
# 这里以SSH连接Linux时的22端口为例
./ngrok -proto=tcp 22
映射成功的话,会显示如下内容:
# 客户端ngrok正常执行显示的内容
ngrok (Ctrl+C to quit)
Tunnel Status online
Version 1.7/1.7
Forwarding tcp://mydomain.com:49805 -> 127.0.0.1:22
Web Interface 127.0.0.1:4040
# Conn 0
Avg Conn Time 0.00ms
现在, 在 putty 等 ssh 工具中即可连接 mydomain.com. 切记端口是号 49805, 是随机分配的一个端口号, 而不是默认的 22 端口了.
Windows 的远程桌面可以将其映射到 3389 端口来实现. 同理, 如果要做 MySQL 的远程连接, 只需映射 3306 端口即可. FTP可映射21端口.
3 优化
3.1 ngrok 服务器端后台运行
nohup /usr/local/ngrok/bin/ngrokd -domain="mydomain.com" -log="ngrok.log" -httpAddr=":8080" &
3.2 nginx代理
我vps的80端口已经被nginx用了, 所以ngrok无法再使用80端口, 只能用nginx, 那么直接反向代理走起~~.
在nginx的配置文件增加:
server {
server_name test.mydomain.com;
listen 80;
keepalive_timeout 70;
proxy_set_header "Host" $host:8080;
location / {
proxy_pass_header Server;
proxy_redirect off;
proxy_pass http://test.mydomain.com:8080;
}
access_log off;
log_not_found off;
}
3.3 客户端指定tcp端口
更改配置文件内容为:
#注意,tunnels下的名字随意命名
server_addr: "mydomain.com:4443"
trust_host_root_certs: false
tunnels:
ssh:
remote_port: 35219
proto:
tcp: 22
vnc:
remote_port: 5902
proto:
tcp: 5902
dd:
remote_port: 9208
proto:
tcp: 8888
www_xly:
subdomain: xly
proto:
http: 80
客户端启动命令改为:
#选择仅启动ssh和web服务
ngrok -config=ngrok.cfg start ssh www_xly