• 远程桌面一直被人爆破的解决思路


    前言

    某天远程自己的电脑发现登不上了,错误信息如下:
    在这里插入图片描述
    开始也没在意,后面出现了好几次才反应过来。查看了Windows日志发现一直有人在尝试登录这台电脑,因为3389端口已经映射到了公网IP

    初步解决方法

    进入计算机管理->系统工具->本地用户和组选择被锁定的用户,右键属性就能看到
    在这里插入图片描述
    取消锁定即可

    题外话

    之前一直没有出现这种情况,但是我看日志信息这种情况已经出现好几天了,每隔几秒就有人尝试登陆。因为Windows日志右大小限制,也就是最多保留三四天的信息,那这种情况应该持续很长一段时间了。

    之前没有发现是因为Windows11 22H2才开始开启这个策略。也就是说之前的系统即使密码尝试一直错误也不会锁定账户,具体可以看:Windows 11 22H2默认启用了密码暴力穷举保护功能

    看了看我的纯数字的密码,细思极恐,吓得我马上换成了大小写数字加特殊字符的密码

    预防措施

    因为我自己也要远程连接电脑,防火墙直接锁死远程登陆也不太现实,因为是映射到公网的IP,用的也不是3389端口,改端口应该是没实际作用的。

    查看了日志发现,日志里是有远程登陆的IP的。导出日志为txt,正则提取一下IP,接着去下重,有170个IP。想着加入防火墙的黑名单,但是Windows这防火墙也不能批量编辑,只能一个一个加。

    搜了一下如何通过winapi获取日志和添加防火墙

    获取日志

    我搜到的有两种方式,powershell和WMI

    WMI我测试了不太会用,还是powershell命令方便的多。官方文档

    Get-EventLog
    Get-EventLog
       [-LogName] 
       [-ComputerName ]
       [-Newest ]
       [-After ]
       [-Before ]
       [-UserName ]
       [[-InstanceId] ]
       [-Index ]
       [-EntryType ]
       [-Source ]
       [-Message ]
       [-AsBaseObject]
       []
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    说下这里面用的到的:

    • LogName: 日志类型, 比如安全/系统等。可以通过Get-EventLog -List查看所有的类型英文名称
      在这里插入图片描述
    • Newest: 查看最近的多少条
    • After: 在什么时间之后
    • Before: 在什么时间之前
    • Index,EntryType,Source,Message,InstanceID: 这五个都是日志的字段值
    例子

    Windows命令并不区分大小写,参数也是大写小写都可以。如果参数是字符串的话,不包含特殊字符的话,可以不用引号括起来。如果包含空格等特殊字符的话需要引号括起来

    • Get-EventLog -List
      查看所有日志类型
      在这里插入图片描述

    • Get-EventLog -LogName System -Newest 10
      查看最近十条系统日志
      在这里插入图片描述

    • Get-EventLog -LogName System -Source "Microsoft-Windows*" -Newest 10
      查看最近十条Source字段以Microsoft-Windows开头的系统日志
      在这里插入图片描述

    • Get-EventLog -LogName System -EntryType "Error" -Newest 10
      查看最近十条EntryType等于Error的系统日志
      在这里插入图片描述

    • Get-EventLog -LogName Security -InstanceId 4625 -Newest 10
      查看最近十条InstanceId等于4625的安全日志。InstanceId表示的是事件类型,4625就是登录失败的类型
      在这里插入图片描述

    • Get-EventLog -LogName Security -Message *登录失败* -Newest 10
      查看最近十条,Message包含登录失败的安全日志
      在这里插入图片描述

    • Get-EventLog -LogName System -Newest 1 | Select-Object -Property *
      显示属性
      Get-EventLog -LogName System -Newest 1 | Select-Object -Property EventID,Message 只显示EventID,Message字段
      在这里插入图片描述

    • $Begin = Get-Date -Date '1/17/2019 08:00:00'
      $End = Get-Date -Date '1/17/2019 17:00:00'
      Get-EventLog -LogName System -EntryType Error -After $Begin -Before $End
      这得先定义两个时间变量,再执行第三个命令

    • Get-EventLog -LogName Security -InstanceId 4625 -Newest 1 | select -ExpandProperty message
      只显示Message字段,主要是为了显示全部,不然看到的都是…

    防火墙操作

    官方文档

    如果不清楚具体命令,可以后面跟空格+问号获取帮助信息
    在这里插入图片描述
    简单说下show delete和add这三个命令

    show的功能基本就是下图中的两个例子了

    1. netsh advfirewall firewall show rule name="allow browser" 获取指定name的防火墙规则
    2. netsh advfirewall firewall show rule name=all dir=in type=dynamic 获取防火墙入站规则中类型为dynamic的规则。这个type类型指的是什么,我在防火墙里没看到

    在这里插入图片描述

    add的帮助信息比较长,这里就截了用法。示例和补充说明可以在自己电脑上看
    在这里插入图片描述
    介绍下字段:

    • name: 防火墙规则名称,建议唯一,且不能是all
    • dir: 指的是入站和出站规则,入站是别人访问你,出站是你访问别人。举个例子,你不想让别人访问你的某些接口就可以定义入站规则禁止端口。或者是你不想某些广告的请求发出去,你就可以定于出战规则限制某些IP向外请求
    • action:定义是允许还是禁止,这个bypass应该是界面上的那个只允许安全连接。具体可以看界面添加规则
    • program: 程序的目录,用于允许或者禁止应用联网
    • service: 指定服务的名称,如果指定any,则规则只针对服务生效
    • description:描述
    • enable:是否启用规则,默认是
    • profile:这个是指网络类型,也就是界面中的配置文件(域/专用/公用)
    • localip: 这个用来限制本机的某个网卡。比如手机有两个网,禁止其中一个
    • remoteip:这个就是用来添加远程IP的。localsubnet|dns|dhcp|wins|defaultgateway这些我也不清楚有什么用。看后面的参数类型:IPv4 | IPv6 | 地址范围 | 地址列表,这个后面说明
    • localport: 略
    • remoteport: 略
    • protocol: 一般指udp还是tcp或者是any,默认any
    • interfacetype:无线/有线/ 后面还有个ras应该是拨号吧
    • 下面的就不看了,也用不到

    这里说下remoteip的规则。localip基本类似

    • ipv4:也就是指 8.8.8.8这种,还可以在后面接/24这种,具体解释看: IP 地址末尾的斜杠。通俗的讲就是下面四个对应关系
      • 10.0.0.0/24(10.0.0.1–10.0.0.254)
      • 10.0.0.0/16(10.0.0.1–10.0.255.254)
      • 10.0.0.0/8(10.0.0.1–10.255.255.254)
      • 10.0.0.0/32(10.0.0.0)
    • ipv6: 一样的用法
    • : 地址范围,比如你不想写成10.0.0.0/24就可以写10.0.0.1–10.0.0.254
    • : 可以写多个,用逗号分隔, 比如 8.8.8.8,10.0.0.0/24

    示例
    在这里插入图片描述

    delete参数基本和add的一样在这里插入图片描述

    编写软件自动提取IP和添加黑名单

    因为登录失败的IP不止这些,我禁止了一批又出现几个新的,所以我打算写个工具自动提取IP和添加到防火墙黑名单里

    这里我选择了aardio来写这个工具,理由很简单:调用powershell和cmd命令方便,容易打包成exe,没有依赖环境

    调用powershell命令
    import console;
    import dotNet.ps;
    var ps_string = "Get-EventLog -LogName Security -InstanceId 4625 | select -ExpandProperty message";
    var result = dotNet.ps(ps_string);
    console.pause(true);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    调用cmd命令
    import console;
    import process.popen;
    
    var ruleName = "BlockIPsByHelper";
    var show_ps_string = string.format("netsh advfirewall firewall show rule name=%s", ruleName);
    var prcsShow = process.popen(show_ps_string);
    var showIps = table.array();
    for line in prcsShow.lines("<远程\s*IP>|\s*\:\s*([\d./,-]+)"){  
    	if(!line || line == "") continue;
    	var s = string.split(line, ",");
    	for(i=1;#s;1){
    		table.push(showIps, s[i]);
    	}
    }
    prcsShow.close();
    console.pause(true);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    完整代码:

    import console;
    import dotNet.ps;
    import process.popen;
    
    io.open()
    
    var ruleName = "BlockIPsByHelper";
    
    var arrayCounter = function(tab){
    	var counter = {};
    	for(i=1;#tab;1){
    		var c = tab[i];
    		if(!counter[c]){
    			counter[c] = 1;
    		}else{
    			counter[c] += 1;
    		}
    	}
    	return counter;
    }
    
    
    // 通过powershell命令查询日志,获取登录失败(EventID=4625)的远程IP
    var getLoginFailEventIP = function(){
    	var ps_string = "Get-EventLog -LogName Security -InstanceId 4625 | select -ExpandProperty message";
    	var result = dotNet.ps(ps_string);
    	var ips = table.array();
    	string.search(ips, result, "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}");
    	var counter = arrayCounter(ips);
    	console.log("IP计数: ")
    	console.dump(counter);
    	var set_ips = table.array();
    	for(i=1;#ips;1){
    		var ip = ips[i];
    		var ip32 = ip+"/32";
    		if(!table.find(set_ips, ip32) and ip32 != "127.0.0.1/32" and counter[ip] > 2){
    			table.push(set_ips, ip32);
    		}
    	}
    	return set_ips;
    }
    
    
    var addFirewallRule = function(){
    	console.log("规则名称:", ruleName);
    	// 查询旧规则
    	var show_ps_string = string.format("netsh advfirewall firewall show rule name=%s", ruleName);
    	var prcsShow = process.popen(show_ps_string);
    	var showIps = table.array();
    	for line in prcsShow.lines("<远程\s*IP>|\s*\:\s*([\d./,-]+)"){  
    		if(!line || line == "") continue;
    		line = string.trim(line);
    		var s = string.split(line, ",");
    		for(i=1;#s;1){
    			table.push(showIps, s[i]);
    		}
    	}
    	prcsShow.close();
    	console.log("查询旧规则结果IP: ", '\r\n', string.join(showIps, '\r\n'));
    	// 删除旧规则
    	var delete_ps_string = string.format(`netsh advfirewall firewall delete rule name="%s"`, ruleName);
    	var prcsDelete = process.popen(delete_ps_string);
    	var result, a, b = prcsDelete.readAll();
    	console.log("删除规则结果: ", result);
    	prcsDelete.close();
    	// 查询IP
    	console.log('开始从计算机管理->系统工具->事件查看器->Windows日志 查询错误登录信息,等待时间会有点长(看日志量)!\r\n');
    	var t0 = time.tick();
    	var ips = getLoginFailEventIP();
    	console.log("获取IP完成,耗时(秒): ", (time.tick()-t0)/1000);
    	// 将showIps中的ip加入到ips
    	for(i=1;#showIps;1){
    		var ip = string.trim(showIps[i]);
    		if(!table.find(ips, ip)){
    			table.push(ips, ip);
    		}
    	}
    	// 将提取的ip保持到文件
    	string.save("\日志提取的IP.txt", string.join(ips,'\r\n'));
    	// 添加新规则
    	var remoteip = string.join(ips, ",");
    	var add_ps_string = string.format(`netsh advfirewall firewall add rule name="%s" dir=in action=block description="firewall-Helper添加的需要阻止的IP黑名单" remoteip="%s"`, ruleName, remoteip);
    	console.log("执行的netsh命令: ", add_ps_string);
    	var prcsAdd = process.popen(add_ps_string);
    	var result, a, b = prcsAdd.readAll();
    	console.log("添加规则结果: ", result);
    	prcsAdd.close();
    }
    
    
    addFirewallRule()
    
    console.pause(true);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93

    接着编译成exe,添加定时任务,每小时执行一次即可。

  • 相关阅读:
    引入gitlab仓库代码到npm包的教程
    【软考-中级】系统集成项目管理工程师-合同管理历年案例
    C++ day7
    [Android开发学iOS系列] ViewController
    统计专业人员职称评价基本标准
    mysql整库备份表结构和数据
    IDEFICS 简介: 最先进视觉语言模型的开源复现
    太炫酷,3分钟学会,视频倒放技能
    Spring Boot与Web组件,值得学习(附加记住idea快捷键)
    C语言入门(三)语句和常用的基本函数
  • 原文地址:https://blog.csdn.net/Qwertyuiop2016/article/details/127898862