Redis

场景和需求: 在使用ngrok的时候,我们需要对ngrok的所有连接进行管理,可以理解为对连接上来的用户进行管理。ngrok的原始目的是实现内网穿透,可以从外网访问内网的机器(如树莓派),那么问题来了,如果有100台树莓派,我们如何知道?所以需要在ngrokd服务器上记录下每一台树莓派的ip地址和端口。

目的

在ngrokd服务端记录所有的连接。

方案

记录所有的方式有很多种,可以写入到文件当中、也可以写入到数据库中(如sqlite、mysql,MongoDB,Redis等)。有这么多的方式可以实现我们的目的,当然需要根据你的业务场景选择一种较为合适的。这里我们选用redis,因为redis 是一个NoSql,not only sql,redis不仅仅是一个数据库,redis还是一个发布/订阅的系统。发布/订阅系统可以方便日后与企业级的平台进行交互融合。有了发布/订阅系统,就可以类似微信一样,可以实时的知道有谁连接上了ngrokd服务器。

Redis使用

Redis教程资源在网上一大堆的资料。在本项目中只会用到常用的几个而已。可以通过本项目举一反三了解redis的特性。

修改步骤:

  • 增加ivgredis.go
  • 修改src/ngrok/msg/conn.go
  • 修改src/ngrok/server/tunnel.go
  1. ivgredis.go文件如下
package ivgredis
//package mainimport ("time"log "github.com/alecthomas/log4go""github.com/gomodule/redigo/redis"
)var redisClient *redis.Poolfunc GetConnFromPool() redis.Conn {if redisClient != nil {goto end}redisClient = &redis.Pool{//连接方法Dial: func() (redis.Conn, error) {c, err := redis.Dial("tcp", "127.0.0.1:6379")if err != nil {return nil, err}c.Do("SELECT", 0)return c, nil},//DialContext:     nil,//TestOnBorrow:    nil,//最大的空闲连接数,表示即使没有redis连接时依然可以保持N个空闲的连接,而不被清除,随时处于待命状态。MaxIdle: 1,//最大的激活连接数,表示同时最多有N个连接MaxActive: 10,//最大的空闲连接等待时间,超过此时间后,空闲连接将被关闭IdleTimeout: 180 * time.Second,//Wait:            false,//MaxConnLifetime: 0,}
end:c := redisClient.Get()// defer c.Close()return c
}func IsSetMemberExist(key string, member string) bool {c1 := GetConnFromPool()exists, err := redis.Bool(c1.Do("SISMEMBER", key, member))defer c1.Close()if err != nil {log.Debug("%v", err)return false} else {return exists}
}func AddSetMember(key string, member string) (num int64, err error) {// var str string = {"Type":"NewTunnel","Payload":{"ReqId":"7ead4dedaecaf989","Url":"tcp://ng.ubuntu.local:8022","Protocol":"tcp","Error":""}}c1 := GetConnFromPool()num, err = redis.Int64(c1.Do("SADD", key, member))defer c1.Close()return num, err
}func GetSetMembers(key string) (results1 []string, err error) {c1 := GetConnFromPool()results1, err = redis.Strings(c1.Do("SMEMBERS", key))defer c1.Close()return results1, err
}// SREM KEY MEMBER1..MEMBERN
func DelSetMember(key string, member string) (results1 int64, err error) {log.Debug("del %s", member)c1 := GetConnFromPool()results1, err = redis.Int64(c1.Do("SREM", key, member))log.Debug(results1)defer c1.Close()return results1, err
}
func PublishConnNgrokClien(channel string, message string) (num int, err error) {c1 := GetConnFromPool()defer c1.Close()return redis.Int(c1.Do("PUBLISH", channel, message))
}/*
func main() {var ip1 stringip1 = "ivg-12-34-56.vkingman.cn"exists := isSetMemberExist("ngrok_client", ip1)log.Debug(exists)val1, err := addSetMember("ngrok_client", ip1)if err != nil {log.Debug("%v", err)} else {log.Debug("add %d members", val1)}results1, err := getSetMembers("ngrok_client")if err != nil {log.Debug("set err")fmt.Println(err)} else {log.Debug("SMEMBERS ok")log.Debug(results1)}results2, err := delSetMember("ngrok_client", ip1)if err != nil {log.Debug("%v", err)} else {log.Debug("del %d member", results2)}}
*/
  1. 修改src/ngrok/msg/conn.go的WriteMsg函数

    func WriteMsg(c conn.Conn, msg interface{}) (err error) {var (ret int)buffer, err := Pack(msg)if err != nil {return}c.Debug("Writing message: %s", string(buffer))err = binary.Write(c, binary.LittleEndian, int64(len(buffer)))if err != nil {return}if _, err = c.Write(buffer); err != nil {return}ret = strings.Index(string(buffer), "NewTunnel")if ret > 0 {log.Error("liubaolong----------------> %s", string(buffer))bExist := ivgredis.IsSetMemberExist("ngrok_client", string(buffer))if !bExist {/* add */t := &IvgNewTunnel{}err = json.Unmarshal(buffer, &t)log.Debug(" %v", t.Payload.Url)ivgredis.AddSetMember("ngrok_client", t.Payload.Url)_, err = ivgredis.PublishConnNgrokClien("ngrok_client.connect", t.Payload.Url)if err != nil {log.Debug("%v", err)}}}return nil
    }
    
  2. 修改src/ngrok/server/tunnel.go的Shutdown函数

func (t *Tunnel) Shutdown() {t.Info("liubaolong--190---> Shutting down, %s", t.url)ret, _ := ivgredis.DelSetMember("ngrok_client", t.url)if ret > 0 {log.Debug("del %s", t.url)_, err := ivgredis.PublishConnNgrokClien("ngrok_client.disconnet", t.url)if err != nil {log.Debug("%v", err)}}// mark that we're shutting downatomic.StoreInt32(&t.closing, 1)// if we have a public listener (this is a raw TCP tunnel), shut it downif t.listener != nil {t.listener.Close()}// remove ourselves from the tunnel registrytunnelRegistry.Del(t.url)// let the control connection know we're shutting down// currently, only the control connection shuts down tunnels,// so it doesn't need to know about it// t.ctl.stoptunnel <- tmetrics.CloseTunnel(t)
}

go import 需要注意

首字母小写时,为包内使用,包外无法引用到。

redisgo-ngrok实现内网穿透的管理相关推荐

  1. Ngrok(内网穿透工具)使用教程详解

    简介 国内Ngrok官网地址 Ngrok是什么? ngrok 是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道 ngrok 可捕获和分析所有通道上的流量,便于后期分析 ...

  2. Ngrok: 使用 Ngrok 实现内网穿透

    Jan 10,2017 in 教程 read (14235) | 百度已收录 | Author: Leonn 目录 背景 NAT 穿透原理 一个栗子 Ngrok 准备工作 编译服务端 服务端 测试连接 ...

  3. 使用工具ngrok 实现内网穿透(免费)

    使用工具ngrok 实现内网穿透 工具下载:ngrok下载,提取码:5555 使用:

  4. Ngrok 实现内网穿透教程(Ngrok 和 Sunny-Ngrok )

    ngrok是什么我这边就不多介绍了,百度一找一大堆.你可以把它理解为内网穿透的工具.(简而言之就是将内网IP映射成对外可访问的域名) Ngrok使用流程如下: 从https://ngrok.com/ ...

  5. 废旧Android手机搭建个人服务器:ksweb搭建Web服务器+Termux、Ngrok实现内网穿透

    写在前面: 本篇博客介绍利用废旧手机搭建一个服务器,可以放自己的网页搭建网站 之前闲着没事,低价买了个虚拟主机,放了自己的静态网页,搭建了个人博客引导网站,后来虚拟主机被打死,凑巧了解到相关知识,于是 ...

  6. 用ngrok做内网穿透

    背景 很多时候,我们都有这样的需求:需要将本地正在开发的服务暴露在公网上,也就是从外网直接访问我们本机上的服务. 正常情况下,这是办不到的,因为我们的本机并没有公网 IP,我们的本机处在内网当中. N ...

  7. CentOS7下使用ngrok搭建内网穿透服务器

    目录 1.简介 1 2. 必要条件 2 2.1.ngrok服务器 2 2.2.域名 2 2.3.ngrok客户端 2 3. 安装依赖包 2 4. 安装golang 2 5. 下载ngrok源码 3 6 ...

  8. ngrok实现内网穿透,让家里的笔记本也能做服务器

    背景 家里淘汰了一台笔记本,windows系统装起来很卡,于是装了个linux系统.这台笔记本有2G内存,奔腾双核处理器,配置比我在阿里云上买的ECS高多了,于是想着给它利用起来.研究了一下,发现ng ...

  9. 微信开发-基于Ngrok的内网穿透工具-netapp

    关键词: 微信开发,内网穿透,Ngrok,netapp 概述: 看到一篇博文介绍微信开发的,因为正在做这个东西,就认真看了一下,其中博文的第一章介绍了如何搭建自己的微信测试环境,为了解决微信开发中的调 ...

最新文章

  1. WMI技术介绍和应用——查询环境变量
  2. php getconfig,PHP: tidy::getConfig - Manual
  3. 电脑与人脑,信息与知识
  4. serverless 框架_研发的未来在哪里?Serverless 云开发来了!
  5. VTK:定向包围圆柱体用法实战
  6. 【codeforces】【比赛题解】#849 CF Round #431 (Div.2)
  7. mysql产品优化方案_mysql的优化方案
  8. dockerfile 安装mysql_dockerfile构建mysql镜像
  9. 【转】Android应用的自动升级、更新模块的实现 (2)
  10. MATLAB模拟声压分布,基于Matlab仿真软件构建圆形压电晶体三维模型
  11. 移动办公正在让电子邮件系统变得更有趣
  12. 怎么把程序内部坐标转为屏幕坐标_各位老大,如何把屏幕坐标转换成游戏的坐标...
  13. 单片机花灯开关控制器C语言代码,以51单片机为核心的LED彩灯控制器设计
  14. 寻找反素数python
  15. sidetone 、回声抑制
  16. vue的学习笔记(15)之Promise知识讲解
  17. 爬虫爬取实时新闻标题、时间及新闻内容并保存
  18. 解决IDEA中使用git插件提交代码乱码问题
  19. 论文的每一页最上方都有一条横线(word2007)
  20. golang 枚举 iota

热门文章

  1. Baxter实战——Ubuntu 14.4+ros indigo 安装Baxter Simulator与 Moveit
  2. 《物理光学》——光的衍射
  3. [科普]3.5mm耳机国标和美标
  4. 账号密码外泄检测,看看你已经外泄了哪些网站的账号密码
  5. Ardunio下的STM32串口通信
  6. java中怎么定义true或false_java 中的true、false、null有何不同
  7. 干货 | 以太坊的工作原理
  8. 为什么你学过Java却忘光了——记第一次助教同学见面会,java开发面试笔试题
  9. 关于PaddlePaddle环境安装的注意事项
  10. 为什么宇宙会将最大速度限制在光速?