redisgo-ngrok实现内网穿透的管理
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
- 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)}}
*/
修改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 }
修改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实现内网穿透的管理相关推荐
- Ngrok(内网穿透工具)使用教程详解
简介 国内Ngrok官网地址 Ngrok是什么? ngrok 是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道 ngrok 可捕获和分析所有通道上的流量,便于后期分析 ...
- Ngrok: 使用 Ngrok 实现内网穿透
Jan 10,2017 in 教程 read (14235) | 百度已收录 | Author: Leonn 目录 背景 NAT 穿透原理 一个栗子 Ngrok 准备工作 编译服务端 服务端 测试连接 ...
- 使用工具ngrok 实现内网穿透(免费)
使用工具ngrok 实现内网穿透 工具下载:ngrok下载,提取码:5555 使用:
- Ngrok 实现内网穿透教程(Ngrok 和 Sunny-Ngrok )
ngrok是什么我这边就不多介绍了,百度一找一大堆.你可以把它理解为内网穿透的工具.(简而言之就是将内网IP映射成对外可访问的域名) Ngrok使用流程如下: 从https://ngrok.com/ ...
- 废旧Android手机搭建个人服务器:ksweb搭建Web服务器+Termux、Ngrok实现内网穿透
写在前面: 本篇博客介绍利用废旧手机搭建一个服务器,可以放自己的网页搭建网站 之前闲着没事,低价买了个虚拟主机,放了自己的静态网页,搭建了个人博客引导网站,后来虚拟主机被打死,凑巧了解到相关知识,于是 ...
- 用ngrok做内网穿透
背景 很多时候,我们都有这样的需求:需要将本地正在开发的服务暴露在公网上,也就是从外网直接访问我们本机上的服务. 正常情况下,这是办不到的,因为我们的本机并没有公网 IP,我们的本机处在内网当中. N ...
- 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 ...
- ngrok实现内网穿透,让家里的笔记本也能做服务器
背景 家里淘汰了一台笔记本,windows系统装起来很卡,于是装了个linux系统.这台笔记本有2G内存,奔腾双核处理器,配置比我在阿里云上买的ECS高多了,于是想着给它利用起来.研究了一下,发现ng ...
- 微信开发-基于Ngrok的内网穿透工具-netapp
关键词: 微信开发,内网穿透,Ngrok,netapp 概述: 看到一篇博文介绍微信开发的,因为正在做这个东西,就认真看了一下,其中博文的第一章介绍了如何搭建自己的微信测试环境,为了解决微信开发中的调 ...
最新文章
- WMI技术介绍和应用——查询环境变量
- php getconfig,PHP: tidy::getConfig - Manual
- 电脑与人脑,信息与知识
- serverless 框架_研发的未来在哪里?Serverless 云开发来了!
- VTK:定向包围圆柱体用法实战
- 【codeforces】【比赛题解】#849 CF Round #431 (Div.2)
- mysql产品优化方案_mysql的优化方案
- dockerfile 安装mysql_dockerfile构建mysql镜像
- 【转】Android应用的自动升级、更新模块的实现 (2)
- MATLAB模拟声压分布,基于Matlab仿真软件构建圆形压电晶体三维模型
- 移动办公正在让电子邮件系统变得更有趣
- 怎么把程序内部坐标转为屏幕坐标_各位老大,如何把屏幕坐标转换成游戏的坐标...
- 单片机花灯开关控制器C语言代码,以51单片机为核心的LED彩灯控制器设计
- 寻找反素数python
- sidetone 、回声抑制
- vue的学习笔记(15)之Promise知识讲解
- 爬虫爬取实时新闻标题、时间及新闻内容并保存
- 解决IDEA中使用git插件提交代码乱码问题
- 论文的每一页最上方都有一条横线(word2007)
- golang 枚举 iota
热门文章
- Baxter实战——Ubuntu 14.4+ros indigo 安装Baxter Simulator与 Moveit
- 《物理光学》——光的衍射
- [科普]3.5mm耳机国标和美标
- 账号密码外泄检测,看看你已经外泄了哪些网站的账号密码
- Ardunio下的STM32串口通信
- java中怎么定义true或false_java 中的true、false、null有何不同
- 干货 | 以太坊的工作原理
- 为什么你学过Java却忘光了——记第一次助教同学见面会,java开发面试笔试题
- 关于PaddlePaddle环境安装的注意事项
- 为什么宇宙会将最大速度限制在光速?