用户
 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,登录网站

Nginx配合ngrok实现内网穿透

天下雪 2017-1-18 00:16

作者:senola,来自原文地址最近和微信公众号杠上了。和微信打过交道的叉子们肯定都见过微信这个配置。微信开发需要有一个公网IP,而我们绝大部分都用的公司的内网,所以每次都得自己在本地模拟微信请求(可以用), ...

作者:senola,来自原文地址

最近和微信公众号杠上了。和微信打过交道的叉子们肯定都见过微信这个配置。微信开发需要有一个公网IP,而我们绝大部分都用的公司的内网,所以每次都得自己在本地模拟微信请求(可以用[postman]),然后提交代码至服务器验证。一旦遇到错误需要重新发布,给调试代码带来极大不便,效率甚低。。。所以很多时候我的心情是这样的:

带着些许期待,遨游了一下google,于是就认识了它---[ngrok]。百度百科解释如下:

ngrok 是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道。  
ngrok 可捕获和分析所有通道上的流量,便于后期分析和重放  

顾名思义,「ngrok」这个东东就是一个反向代理,让本地运行的服务可以被外网访问。

一个令人悲伤的消息是 ngrok v2.x 官方已经闭源,那就意味着要收费了。不过,还好ngrok v1.x 是开源的,代码托管在github上。虽然「ngrok v1.x」已经不再开发和维护了,但是不影响其发挥作用。值得我们可以在自己服务器上折腾一番。

如果嫌自己搭建麻烦,可以使用国内的免费服务,如 http://ngrok.2bdata.com/, 感谢哪些无私贡献服务器的人~

但是~ 但是~ 作为一个爱折腾,爱捣鼓的码农,自给自足才是最大的乐趣。所以,在疯狂的折腾一天后,终于搞定了。。。不禁流下了幸福的汗水。。。

本次测试的「linux」版本是 Centos6

Bash
Linux 2.6.32-042stab113.21 #1 SMP Wed Mar 23 11:05:25 MSK 2016 x86_64 x86_64 x86_64 GNU/Linux  

域名解析

我的域名DNS是在阿里云解析的,增加两条A记录只想服务器IP地址如下。DNS解析速度很快,一般修改后立马生效。

GO环境搭建

首页,我们要知道「ngrok」是用「go」语言写的,所以需要先安装「go」环境,安装「go」最新版本,采用源码安装,最新版本是「1.7.1」,注意:「1.4」以下版本会有编译问题,没有亲测,不敢尝试。

Bash
mkdir /usr/go # 创建go目录  
cd /usr/go #切换目录  
wget https://storage.googleapis.com/golang/go1.7.1.linux-amd64.tar.gz  
tar -xzvf go1.7.1.linux-amd64.tar.gz #解压文件  

设置环境变量

Bash
#根据自己不同目录自行调整
echo 'export GOROOT=/usr/go/go' >> /etc/profile.d/go.sh  
echo 'export PATH=$PATH:$GOROOT/bin' >> /etc/profile.d/go.sh  
echo 'export GOPATH=$HOME/go' >> /etc/profile.d/go.sh  
source /etc/profile #重现加载还将变量  

注意,「GOPATH」如果设置不正确会出现找不到「package」错误。如果出现错误,可以将「GOPATH」值设置成「ngrok」根目录(具体原因没有仔究),更改后记得输入 source /etc/profile 命令更新环境变量。

检测是否安装成功

Bash
go version #go version go1.7.1 linux/amd64  

git环境搭建

在编译「ngrok」的时候,出现了卡在下载某个东西的时候,找了好多资料才发现原来是「git」版本过低,版本必须 >=1.7.9.5方能正常编译。这个坑我踩了。唉~

Bash
gopkg.in/inconshreveable/go-update.v0 (download)  

「git」安装及升级具体可参照官方文档:git 升级

以上依赖环境顺利安装好以后,就可以开始今天的主菜了。

下载「ngrok」源码

Bash
mkdir /usr/  
git clone https://github.com/inconshreveable/ngrok.git ngrok  #clone 源代码  
cd ngrok  

生成证书

ngrok.twindy.org 为列子

Bash
mkdir /usr/ngrok/cert #创建保存证书目录  
openssl genrsa -out rootCA.key 2048  
openssl req -x509 -new -nodes -key rootCA.key -subj "/CN=ngrok.twindy.org" -days 5000 -out rootCA.pem  
openssl genrsa -out device.key 2048  
openssl req -new -key device.key -subj "/CN=ngrok.twindy.org" -out device.csr  
openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days 5000  

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

ls /usr/ngrok/cert # 文件列表  
device.crt device.csr device.key rootCA.key rootCA.pem rootCA.srl  

「ngrok」通过「bindata」将「ngrok」源码目录下的「assets」目录(资源文件)打包到可执行文件(「ngrokd」和「ngrok」)中去,assets/client/tls 和 assets/server/tls 下分别存放着用于「ngrok」和「ngrokd」的默认证书文件,我们需要将它们替换成我们自己生成的:(因此这一步务必放在编译可执行文件之前)

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

编译「ngrokd」和「ngrok」

注意,参数里可以设置操作系统位数、类型。傻傻的我,居然为了编译「window」版本,在「window」下又搭了一套环境重新编译。 无限笨~

Bash
make clean #clean  
# 如果是32位系统,GOARCH=386; 如果是64为系统,GOARCH=amd64
# 如果要编译linux,GOOS=linux;如果要编译window,GOOS=windows
GOOS=linux GOARCH=amd64 make release-server release-client #liunx 、64bit  

顺利的话,可以正常编译,在bin下面可以看到「ngrokd」和「ngrok」,其中「ngrokd」是服务端执行程序,「ngrok」是客户端执行程序。

查看 「ngrokd」参数

Bash
ngrokd -h #查看参数说明  
-domain string Domain where the tunnels are hosted (default "ngrok.com")
-httpAddr string Public address for HTTP connections, empty string to disable (default ":80")
-httpsAddr string Public address listening for HTTPS connections, emptry string to disable (default ":443")
-log string Write log messages to this file. 'stdout' and 'none' have special meanings (default "stdout")
-log-level string The level of messages to log. One of: DEBUG, INFO, WARNING, ERROR (default "DEBUG")
-tlsCrt string Path to a TLS certificate file
-tlsKey string Path to a TLS key file
-tunnelAddr string Public address listening for ngrok client (default ":4443")

启动「ngrokd」服务端

注意: http和https端口可以自己指定,这里不采用80端口,是因为其他程序已经占用了,端口转发在上面nginx已经配置完成

Bash
# domain填写刚才生成证书时填写的域名
# bin/ngrokd -domain="ngrok.twindy.org" -httpAddr=":8002" -httpsAddr=":8003"

# 如果想要后台启动,执行以下命令  
nohup bin/ngrokd -domain="ngrok.twindy.org" -httpAddr=":8002" -httpsAddr=":8003"   > /dev/null 2>&1 &

# 如果想要开机启动,执行以下命令
vim /etc/rc.d/rc.local  
# 添加以下内容,具体内容请根据自己情况自行调整
{your-ngrok-dir}/bin/ngrokd -domain="ngrok.twindy.org" -httpAddr=":8002"  -httpsAddr=":8003"  > /var/log/ngrok.log &

「ngrok」客户端连接

已下在「window」上测试「ngrok」客户端连接。

将生成的「ngrok.exe」下载至本地d:/ngrok/ngrok.exe,新建配置文件d:/ngrok/ngrok.cfg:

Bash
server_addr: "ngrok.twindy.org:4443"  
trust_host_root_certs: false  
tunnels:  
  example:
   subdomain: "example" #定义服务器分配域名前缀
   proto:
    http: 8000 #映射端口,不加ip默认本机
    https: 80
  web:
   subdomain: "web" #定义服务器分配域名前缀
   proto:
    http: 192.168.1.100:80 #映射端口,可以通过加ip为内网任意一台映射
    https: 192.168.1.100:80
  web1:
    hostname: "ngrok.your-domain.com"
    proto:
      http: 80
  web2:
    hostname: "your-domain.com"
    proto:
      http: 80
  ssh:
   remote_port: 50001 #服务器分配tcp转发端口,如果不填写此项则由服务器分配
   proto:
    tcp: 22 #映射本地的22端口
  ssh1: #将由服务器分配端口
    proto:
      tcp: 21

启动「ngrok」客户端

Bash
cd d:\ngrok  
ngrok -config=ngrok.cfg -subdomain weixin 8080

# 或者
ngrok -config ngrok.cfg start example

# 如果出现问题连接不上,想在本地查看日志,可加上log参数
ngrok -log ngrok.log -config ngrok.cfg start example  

如果没有错误,则会出现以下结果:

Bash
Tunnel Status                 reconnecting  
Version                       1.7/1.7  
Forwarding                    http://example.ngrok.twindy.org:8002 -> 127.0.0.1:8000  
Forwarding                    https://example.ngrok2.twindy.org:8002 -> 127.0.0.1:8000  
Web Interface                 127.0.0.1:4040  
# Conn                        9
Avg Conn Time                 114.23ms  

到这里,内网已经成功穿透。但是,事情还还有结束!!!!

微信开发中的api地址,是不认80以外的端口的,也就是说虽然

http://example.ngrok.twindy.org:8002  

外网已经可以访问本地服务,但是微信不认识。而我们又不能在「ngrokd」用80端口启动。因为80端口已经被「nginx」占用

Bash
bin/ngrokd -domain="ngrok.twindy.org" -httpAddr=":80"  

怎么办?怎么办??

既然「nginx」占用了80端口,那么就在「nginx」上做文章。只要绑定example.ngrok.twindy.org 并将所有请求转发到8002端口即可。在服务器中新建/etc/nginx/conf.d/ngrock.twindy.org.conf文件,添加以下内容:

upstream ngrok {  
    server 127.0.0.1:8002; # 此处端口要跟 启动服务端ngrok时指定的端口一致
    keepalive 64;
}
server {  
    listen       80;
    server_name  *.ngrok.twindy.org;
    #charset koi8-r;
    access_log  /var/log/nginx/log/ngrok.twindy.org.access.log  main;
    location / {
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host  $http_host:8002; #此处端口要跟 启动服务端ngrok 时指定的端口一致
            proxy_set_header X-Nginx-Proxy true;
            proxy_set_header Connection "";
            proxy_pass      http://ngrok;
    }
}

重新加载「nginx」

Bash
nginx -s reload  

此外,「ngrok」+ 「nginx」+「Docker」也可以完美实现,由于对Docker」不了解没有去折腾 参考地址:搭建自己的 Ngrok 服务器, 并与 Nginx 并存

至此,「ngrok」内网穿透成功实现。幸福的汗水。。。

总结:

  • 今天遇到坑太多,还好之前自学过「nginx」,虽然折腾了一天最终还是成功了,满满的成就感。
  • coding无止境。

鲜花
鲜花
鸡蛋
鸡蛋
分享至 : QQ空间
收藏
原作者: senola 来自: 原文地址

相关阅读