一年前,由于一个有些可笑的原因(别问我为什么,真的),我买了个米家的摄像头,然后分享给了某个人。那个时候我在想,有没有办法随时知道谁看了监控呢?管他是某个人还是其他什么奇奇怪怪的人。
米家本身并不提供这种功能,也不像其他品牌一样在摄像头被查看的时候会有一个特殊的指示灯显示。
既然如此,那作为一名有灵性的工程师,一定能找到办法的!
简单的说,自然就要从网络上下手啦!毕竟这个东西是需要通过网络传输数据的,在其他人查看的时候一定会大量的传输数据,并且根据常识推断,极有可能是UDP,并且有可能通过UDP打洞的方式直接看到查看者的IP地址。
话不多说,说干就干,老子干网络这么多年,还不是 permit any any 通了就走!
抓包
既然要抓包,那自然也就在路由器上动手脚最好了。此时需要一个刷了padavan、OpenWRT、Merlin之类第三方固件的路由器,然后准备好tcpdump
tcpdump可以使用opkg之类的命令安装,如果你的CPU恰巧是arm的,可以用这个静态编译的。
假设摄像头的IP是192.168.7.149,然后路由器的网桥是br-lan(有些可能是br0)
tcpdump -i br-lan udp and host 192.168.7.149
此时打开手机,最好用流量来测试IP,查看摄像头,大概率会看到类似如下日志:
如果没有的话,去掉UDP试试看。再没有就看看接口和IP对不对,有些情况下抓对应的wlan01可能更好。
分析
此时右侧的那个疯狂刷屏39.xxxx就是我的手机数据流量的出口IP,中国移动的某个IP。有些时候会看到一些金山云的IP,可以直接忽略。
那么接下来问题来了
- 只有刷屏的IP才算是可能的查看记录,有什么办法揪出来吗?
- 咱也不能时时刻刻盯着tcpdump的输出啊!
令牌桶算法
只有刷屏的IP才可能是查看记录,那么如何分析统计这个“刷屏频率”?最好的办法就是令牌桶算法啦!
所谓令牌桶,就是设计一个桶,某个组件持续地往里面丢令牌(token),然后每个请求进来的时候去这里拿令牌,拿到了就执行,拿不到就只能等着了。
令牌桶通常用于限流,我们的这个恰巧是“反着来的限流”,反正只要撞了rate limit就是我们要的数据。
记得先写正则表达式过滤一下。
为了方便在路由器上运行,这事必然是要用Go来写的,毕竟交叉编译嘛
package main import ( log "github.com/sirupsen/logrus" "golang.org/x/time/rate" ) const ( bucketSize = 70 bucketRate = 35 ) var limiter = rate.NewLimiter(bucketRate, bucketSize) func main() { if limiter.Allow() { log.Infoln("Using token...") } else { log.Warnln("Potential view, sending alert now...") } }
很简单,定义了一个桶,大小是70,每秒钟产生35个令牌,说人话:每秒钟抓到35个包,刚好可以抵消令牌桶消耗;每秒抓到40个包,大概8秒会报警。至于这个35和70是怎么设计的嘛,是我从实践与经验中发现这个值最稳妥、最不容易误报。
消息通知
消息通知就很简单了,当 limiter.Allow()
不满足时,直接telegram bot就行了,这样最方便。
代码太过简单,就不说了
结果
真挺准的!俗话说知己知彼,百战不殆反正我是认输了。
也真的挺不好意思的我这玩意藏着掖着,快一年了才放出来……
参考代码
https://gist.github.com/BennyThink/c78cefa446fc492209710796ee342dec
--本评论由Telegram Bot回复~❤️