通过 telegram bot 监控设备的远程登录情况
之前我先后白嫖了 azure 的 windows server,以及做了 zerotier 用于远控,但前者我提过 3389 端口老是被撞,后者要通过密码和 zerotier 网域两重保险,应该够安全了,但毕竟是把我的主用设备暴露出去,还得更安全一点才行。
我听说有些脚本可以登录时从 telegram bot 通知所有者,找了一下,ssh 的和 rdp 的都有,那就一起上了。
工具:
- SSH PAM module - Telegram Alert on connect and disconnect, with IP exceptions.
- ihatemodels/rdp-telegram-messenger: Get instant telegram message when a new rdp connection is established
前期准备
参考:Telegram Bot 控制 Aria2 下载并自动上传到 Google Drive、OneDrive - P3TERX ZONE
创建 bot,获取 bot token
访问 telegram bot 管理 bot @botfather,通过三个步骤就能获得一个 bot:
- 输入
/newbot
,会询问你 bot 起什么昵称(即 tg 窗口左上角的名字),按自己喜好起就行。 - 回车后,会询问你 bot 想起一个什么用户名。以后可以通过用户名来直接找到这个 bot。需要以 Bot 或者 _bot 结尾,同时不可以和已有的 bot 名字冲突,所以这里要起复杂一点。
- 然后就能从机器人的回答中获得一串字体颜色为黄色的长长一串 token 了。 顺便回答里面
You will find it at
后面的蓝色链接可以直接通向创建的机器人,先过去/start
一下,以免待会还要回来找。监测几个 ssh/rdp 就要建立几个 bot,可以建一个,做完建立提醒步骤后再建,也可以先一次建一堆(因为我看 botfather 这边有批量建立的功能,不过我没用过)。
获取 userid
进入刚刚获取的其中一个 bot,随便输点东西。
然后在浏览器中访问 https://api.telegram.org/bot<bot_token>/getUpdates
,不同的 bot,bot token 不一样,别填错了。
不出意料的话,result 中 id 后面跟的数字就是账号的 userid。userid 每个 telegram 账号唯一,获取过一次就不用再获取了。
如果 result 为空,证明离上次和 bot 互动时间相隔太久,重新去 bot 里再输点东西就好。
获取 chatid
参考:Telegram Bot - how to get a group chat id? - Stack Overflow
仅 rdp 登录提醒需要(因为我找到的 rdp 提醒脚本只能在群内提醒,没法在 bot 里面直接提醒)。
把相应 bot 拉入群中。
在群中发一句
1
/my_id @my_bot
访问
https://api.telegram.org/bot<bot_token>/getUpdates
,在 chat 这个代码块的 id,就是 chatid(带个负号的很显眼)
chatid 每个群唯一,所以也获取一次,然后把所有 rdp 监测 bot 拉到同一个群中就好了。就是建群还需要好友配合这点比较烦(实在不行办个小号呗)。
linux ssh 登录提醒
从参考文章 1 中下载或者复制粘贴源码得到
telegram-alert.sh
修改其中的
1
2
3
4
5
6# Your USERID or Channel ID to display alert and key, create a new bot with @BotFather on Telegram
# Ask to @IDBot for your id (/getid)
USERID="********"
# Create a new bot with @BotFather and start a new discussion with it
KEY="*********:***********************************"
URL="https://api.telegram.org/bot${KEY}/sendMessage"key 就是 bot token,把我们前期准备获取的两个值填进去。
把
telegram-alert.sh
放到被检测机usr/local/bin
里,加权限1
chmod +x /usr/local/bin/telegram-alert.sh
在
/etc/pam.d/sshd
新增session optional pam_exec.so type=open_session seteuid /usr/local/bin/telegram-alert.sh
1
echo "session optional pam_exec.so type=open_session seteuid /usr/local/bin/telegram-alert.sh" >> /etc/pam.d/sshd
(可选)重启 sshd
1
service sshd restart
如果是开启 SELinux 的系统(如 centos),参考文章后面还有两部,我用的是 debian 就不写上来了。
rdp 登录提醒
从参考文章 1 中下载或者复制粘贴源码得到
rdp-telegram.ps1
修改其中的
1
2$botToken = 'ADD UR TOKEN HERE'
$chatID = 'ADD UR CHAT ID HERE'把我们前期准备获取的两个值填进去。
把
rdp-telegram.ps1
放到被检测机里一个好找的地方,我就直接放到我的 user 目录下了C:\Users\zbttl
。按下 win 键,敲入「事件查看器」并打开
找到应用程序和服务日志 -> Microsoft -> Windows -> TerminalServices-RemoteConnectionManager。
新一点的系统,比如 win10,登录过 rdp 的话在 Admin 这项里面会有 20521 这项代表已登录成功的日志
旧一些的,比如 windows server 2012 可能就没有。不过旧系统在 operational 这里会有类似 1149 的记录,同样是代表登录成功。
哪个都可以,参考文章中提到的是前一个,然后我发现前一个如果用微软商店的第三方 rdp(名字就叫远程桌面,系统自带的远程桌面遇到屏幕分辨率不一样的情况会拉跨),日志中没提示,所以自行选择。
右键其中一个包含上面提到的这两种其中一种的记录选择「将任务附加到此事件」。在打开的窗口中,创建基本任务的名字随便取,然后一路下一步来到「启动程序」这一项。程序或脚本,填入 POWERSHELL;添加参数(可选)填入
rdp-telegram.ps1
所在路径(记得打引号),对我来说那就是"C:\Users\zbttl\rdp-telegram.ps1"
完成后,再次按下 win 键,搜索任务计划程序,打开,在任务计划程序库 -> 事件查看器任务处,就能看到我们刚刚创建的任务。选择那个任务,点右侧的属性,在弹出的窗口中看到常规 -> 安全选项,勾选「使用最高权限运行」。
不进行这一步的话,待会在 telegram 群虽然会弹通知,但通知中各项属性的值都是空:
如果显示操作参数错误的话,把上面「只在用户登录时运行」改为「不管用户是否登录都要运行」,然后输入本机账号密码即可。
另外还建议在设置 -> 如果此任务已运行,改为「停止现有实例」或者「并行运行新实例」,以免网络原因导致前面的任务运行不成功一直卡着。
因为被监控机在国内,要给 telegram 发东西的话,你懂得,记得还得是全局代理才行。
补充
两个问题:
- 开 rdp 的时候能看见一个 cmd 框框弹出。万一攻击者看到这个框框眼疾手快关掉了,程序没跑完那通知不就过不来了。
- 我不赞成时时刻刻开着全局代理。
解决方法:
参考
在 rdp-telegram.ps1
同目录下新建一个 rdp.js
文件。文件内容类似于:
1 | var wshShell = new ActiveXObject("WScript.Shell"); |
用火绒的,把这个文件加到火绒的信任区里(这都能被当成病毒文件可还行)。
修改计划任务。回到上面第七步,找到操作,双击启动程序项,程序与脚本修改为 wscript
,添加参数修改为 rdp.js
地址,如 "C:\Users\zbttl\rdp.js"
。
修改 rdp-telegram.ps1
,加入两行
1 | [system.net.webrequest]::defaultwebproxy = new-object system.net.webproxy('[代理地址]') |
代理地址这里,格式为 http://127.0.0.1:7890
这样。
即可。
(这样设置和全局代理也不冲突,不用担心 loopback)
(21.4.2 更新) vps 上的 windows server 中无需关心代理问题,也不需要进计划任务中开启管理员模式运行。不过又出现了限制网址访问的问题。具体来说是这样,开 ie 浏览网页的时候经常就会弹这个网页不在信任列表中,是否加入信任列表并访问。对于我们的 ps1 脚本来说,就需要把其中的 *.telegram.org
加入信任列表中,否则就连不上 api 发不出讯息。