最近疫情虽有好转趋势,仍不可放松,很多企业不得不减少人员密度,或者直接在家远程办公。
可是某些行业由于保密性,如果不能保证远程办公时数据的安全,远程办公也就无法实现。
最近测试了jumpserver和teleport这两款开源堡垒机系统,能够用一个有公网IP的linux机器做堡垒,通过网页登录连接中转ssh或者rdp远程桌面,同时他们的权限分配、运维管理、操作记录等等也都很完善。
如果只是运维人员通过ssh连接其实还好,可是中国大多数人还是使用windows进行工作。而windows的rdp远程图像质量不佳,还会消耗大量带宽,一旦使用人数较多,难免有卡顿和马赛克问题。
不过在这非常时期,也能作为一个备选的方案。
不过对于注重数据安全的企业来说,只是禁用rdp远程的上传下载和剪贴板等功能,并不能保证数据安全,仍然存在通过截图或拍照的方式导致内部数据泄露的问题。
因此,我开始研究通过python添加屏幕水印的功能,检测RDP连接开启就显示屏幕水印,如果在公司办公则不需要显示。
水印本身通过tkinter库来制作,参考了Python 实现计算机屏幕水印一文。
import tkinter, win32api, win32con, pywintypes #生成重复文字,可更改间距 def get_replicate_text(text): i,space,str1,str2 = 0,70,"","" while (i <= 5): str1 = str1 + text + " "space i = i + 1 str2 = " "space + str1 + "\n\n\n\n" str1 = str1 + "\n\n\n\n" str1 = (str1 + str2) * 5 return str1 mytext = get_replicate_text('watermark') #水印重复文字设置 root = tkinter.Tk() width = win32api.GetSystemMetrics(0) height = win32api.GetSystemMetrics(1) root.overrideredirect(True) #隐藏显示框 root.geometry("+0+0") #设置窗口位置或大小 root.lift() #置顶层 root.attributes("-alpha",0.6) #全局透明度,用来设置水印文字透明 root.wm_attributes("-topmost", True) #始终置顶层 root.wm_attributes("-disabled", True) #禁止鼠标等与水印窗口交互 root.wm_attributes("-transparentcolor", "white")#白色背景透明 hWindow = pywintypes.HANDLE(int(root.frame(), 16)) exStyle = win32con.WS_EX_COMPOSITED | win32con.WS_EX_LAYERED | win32con.WS_EX_NOACTIVATE | win32con.WS_EX_TOPMOST | win32con.WS_EX_TRANSPARENT win32api.SetWindowLong(hWindow, win32con.GWL_EXSTYLE, exStyle) label = tkinter.Label(text=mytext,compound = 'left',font=('Times New Roman','15'), fg='#d5d5d5', bg='white') label.pack() #显示
而判定当前账号是否是远程登录的方法是windows本身的quser命令,如果当前登录用户的会话名为rdp-tcp的话,就证明当前用户是通过RDP远程登录的,从而开启水印。
而只是能够自动开启水印显然是不够的,因为即使此服务在后台开机自启,仍然存在被人发现和关闭的风险,比如taskkill命令,或者在开始菜单中注销用户并在彻底注销前取消,后台水印进程都会被关闭。
因此有必要做成中心化的server/client服务,每个水印服务client启动时通过socket连接到server服务,在用户每次登陆(显示水印)、退出(关闭水印)时发送信息到server。
当某个socket连接断开时,就代表水印服务client被关闭,此时可以选择发送警告邮件到运维人员的邮箱,或者直接远程重启client服务,或者直接将该机器上的远程用户注销登录等。
下面先说说一对多的socket连接命令,首先是server端:
from socket import * from threading import Thread address = "127.0.0.1" port = 5432 buffsize = 1024 Msock = socket(AF_INET,SOCK_STREAM) Msock.bind((address,port)) Msock.listen(24) #set max connect 24 conn_list = [] #save connecting connect conn_dt = {} def tcplink(sock,addr): while True: try: #accept message and save recvData = sock.recv(buffsize).decode("utf-8") print(recvData,addr) if not recvData: break except: #when break,remove connect sock.close() print(addr,"offline") _index = conn_list.index(addr) conn_dt.pop(addr) conn_list.pop(_index) break def recs(): while True: clientsock,clientaddress = Msock.accept() if clientaddress not in conn_list: conn_list.append(clientaddress) conn_dt[clientaddress] = clientsock print("connect from:",clientaddress) #start thread t = Thread(target=tcplink,args=(clientsock,clientaddress)) t.start() if __name__ == __"main"__: recs()
然后是client端:
from socket import * def run(): ip = "127.0.0.1" port = "5432" buffsize = 1024 conn = socket(AF_INET,SOCK_STREAM) conn.connect((ip,port)) conn.send("hello,bitch") if __name__ == __"main"__: run()
如上,因为是一对多的模式,所以server端需要通过多线程创建并保持连接,client端主线程为水印,也需要单独一个线程连接server通信。
当用户登录、退出、或者client服务被关闭时,server端可以发送邮件通知运维人员,邮件发送部分代码如下:
from email.header import Header from email.mime.text import MIMEText from email.utils import parseaddr,formataddr import smtplib acccount = "yumefx@yumefx.com" password = "123456" #部分邮箱(例如qq邮箱)这里需要填写授权码,在邮箱客户端设置那里可以生成 toMailAddrs = ["admin@yumefx.com","develope@yumefx.com"] smtpServer = "smtp.yumefx.com" def formatAddress(s): name,addr = parseaddr(s) return formataddr((Header(name,"utf-8").encode(),addr)) def sendmail(title,text): server = smtplib.SMTP(smtpServer,25) #25是默认的smtp端口,有可能不同 server.set_debuglevel(1) server.login(acccount,password) msg = MIMEText(text,"plain","utf-8") msg["Form"] = formatAddress("Watermark Service<%s>" %acccount) msg["Subject"] = Header(title,"utf-8").encode() for ta in toMailAddrs: msg["To"] = formatAddress("SiteGroup<%s>" % ta) server.sendmail(acccount,ta,msg.as_string()) server.quit() sendmail("warning","watermark offline")
如果某个socket连接断开,那么可以由server运行下面的cmd命令重启client服务
wmic /node:192.168.1.10 /user:administrator /password:123456 process where name="watermark.exe" call terminate wmic /node:192.168.1.10 /user:administrator /password:123456 process call create "watermark.exe"
熟悉的wmic命令对吧,快去复习wmic命令详解及应用。
为什么是exe不是py,当然要打包好再用啊。pyinstaller-py脚本打包成exe。
至于怎么把这几块功能结合起来,请去全世界最大的直男交友平台github查看。
中国总是被他们最勇敢的人保护得很好。
《论中国》——基辛格
评论
613173 243850Thank you for your extremely great information and respond to you. I require to verify with you here. Which isnt 1 thing I often do! I get pleasure from reading a publish that can make folks think. Moreover, thanks for allowing me to remark! 997102
39612 674936Most reliable human being messages, nicely toasts. are already provided gradually during the entire wedding celebration and therefore are anticipated to be extremely laid back, humorous and as well as new all at once. finest man speech 970048
499181 35183Oh my goodness! an excellent write-up dude. Thank you However Im experiencing difficulty with ur rss . Do not know why Cannot register for it. Could there be any person obtaining identical rss difficulty? Anybody who knows kindly respond. Thnkx 349624
983087 888042I just couldnt depart your web site prior to suggesting that I extremely enjoyed the regular info an individual supply for your visitors? Is gonna be back regularly so that you can inspect new posts 55329