Ngrok如果你完全不知道它是什么东西,可以在它的github项目上了解下:https://github.com/inconshreveable/ngrok

简单概括:能够将你本机的HTTP服务或TCP服务,通过部署有ngrok服务的外网伺服器暴露给外网访问,网上所说的内网穿透

之前的几个月里本人一直用官方订阅版本的ngrok,之所以用付费模式,主要因为免费模式每次都生成一个随机的二级域名,让人很不舒服,但实际几个月下来的使用情况,评估发现总体用的频率并不是很高,同时网络效果也不是很好(应该和墙有关),同时也尝试了一下国内小米球Ngrok,同样有一些不稳定因素,所以打算自己编译一个私有的Ngrok,在编译过程中发现了不少问题,重新整理一遍文档。

1. 安装go语言开发环境/Git

ngrok是利用go语言开发的,所以先要在服务器上安装go语言开发环境。

yum install golang

~/.bash_profile文件内,加入以下环境变量配置内容:

export GOPATH=$HOME/go
PATH=$PATH:$HOME/.local/bin:$HOME/bin:$GOPATH/bin

最后保证可通过go env查看是否配置成功。

安装Git方式略过,这里没有对版本有要求,我们只是利用GIt获取Ngrok源码,不用Git直接Wget github zip文件也是可以的。

3. 获取ngrok的源码

由于下面编译过程需要改官方的部分源码,同时这里也测试过官方最新的版本总是存在「remote error: bad certificate」问题(文末有描述)。这里用的是mamboer的源码基于1.7.1版本,应该有做一些变更,所以尽可能Fork一份源码至自己的Github账户。

cd /usr/local
git clone https://github.com/mamboer/ngrok.git

源码拉取下来后,看情况需要修改一个地方: 打开 src/ngrok/log/logger.go 文件 将 code.google.com/p/log4go 修改为 github.com/alecthomas/log4go 这里主要考虑 code.google.com 已经下线,其实不修改也可以。

4. 生成自签名证书

使用ngrok.com官方服务时,我们使用的是官方的SSL证书。

自建ngrokd服务,证书这里也可以用Godaddy付费证书/Let’ Encrypt免费证书,不过出于个人测试或者沙盒的要求,就不用第三方证书。所以我们需要生成自己的自签名证书,并编译一个携带该证书的ngrok客户端。

证书生成过程需要一个「基础域名」。 以ngrok官方随机生成的地址”1iedks2cv.ngrok.com”为例,其「基础域名」就是”ngrok.com”,如果你要 提供服务的地址为”example.ngrok.xxx.com”,那「基础域名」就应该 是”ngrok.xxx.com”。

我们这里以「基础域名」=”ngrok.crackedzone.com”为例,因为我将来希望建立”pay.ngrok.crackedzone.com”用于平台支付回调的穿透模式。

在此之前我们给域名”crackedzone.com”添加两条A记录:”ngrok.crackedzone.com”和”*.ngrok.crackedzone.com”,指向这台Ngrok所在的服务器ip。

同时在服务器上生成证书的命令如下:

cd ngrok
openssl genrsa -out rootCA.key 2048
openssl req -x509 -new -nodes -key rootCA.key -subj "/CN=ngrok.crackedzone.com" -days 5000 -out rootCA.pem
openssl genrsa -out device.key 2048
openssl req -new -key device.key -subj "/CN=ngrok.crackedzone.com" -out device.csr
openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days 5000

执行完以上命令,在ngrok目录下就会新生成6个文件:

-rw-rw-r-- 1 lv lv  985 Feb 24 19:04 device.crt
-rw-rw-r-- 1 lv lv  895 Feb 24 19:04 device.csr
-rw-rw-r-- 1 lv lv 1679 Feb 24 19:03 device.key
-rw-rw-r-- 1 lv lv 1675 Feb 24 19:01 rootCA.key
-rw-rw-r-- 1 lv lv 1103 Feb 24 19:03 rootCA.pem
-rw-rw-r-- 1 lv lv   17 Feb 24 19:04 rootCA.srl

ngrok 编译过程会加载 assets/client/tls, assets/server/tls 这里的证书资源文件,替换成自己生成的。

rm -f assets/client/tls/ngrokroot.crt
rm -f assets/server/tls/snakeoil.crt
rm -f assets/server/tls/snakeoil.key

cp rootCA.pem assets/client/tls/ngrokroot.crt
cp device.crt assets/server/tls/snakeoil.crt
cp device.key assets/server/tls/snakeoil.key

5. 编译客户端ngrok和服务端ngrokd

make release-server release-client

成功编译后,会在bin目录下找到ngrokd和ngrok这两个文件。

ngrok可以下载到内网的Client服务器上,存放在/usr/local/bin/ngrok

6. 服务端运行ngrokd服务

nohup /usr/local/ngrok/bin/ngrokd -domain="ngrok.crackedzone.com" -httpAddr=":80" > /tmp/ngrok.log 2>&1 &

有需要可以编写一个服务文件,同时记得开放防火墙80端口和4443端,如果证书需要包括443端口。

7. 客户端运行ngrok

创建一个配置文件: ngrok.yml

server_addr: "ngrok.crackedzone.com:4443"
trust_host_root_certs: false

tunnels:
  pay:
    remote_port: 80
    subdomain: pay
    proto:
      http: 127.0.0.1:10780

启动客户端

/usr/local/bin/ngrok -config=/root/ngrok.yml start pay

注意事项

客户端”ngrok.yml”中”server_addr”后的值必须严格与服务端-domain以及证书中的「基础域名」相同,否则Server端就会出现如下错误日志:

[02/24/20 09:55:46] [INFO] [tun:15dd7522] New connection from 27.12.33.23:3994
[02/24/20 09:55:46] [DEBG] [tun:15dd7522] Waiting to read message
[02/24/20 09:55:46] [WARN] [tun:15dd7522] Failed to read message: remote error: bad certificate
[02/24/20 09:55:46] [DEBG] [tun:15dd7522] Closing

Nginx 自动禁止爬虫IP采集

### 背景最近我们有一个公开服务提供给客户查询关键词的热度值,由于这个API做在官方网站上,自然没有用户登陆,也没有很高查询成本,所以设计上没有任何鉴权无法进行身份认定,于是就被一个爬虫开了超高并发请求,直接后端的AWS Tomcat CPU被用尽,导致无法响应。爬虫显然...… Continue reading

Redis原子性事务Lua应用

Published on June 28, 2020