-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
213 lines (191 loc) · 7.54 KB
/
Program.cs
File metadata and controls
213 lines (191 loc) · 7.54 KB
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
using System.Diagnostics;
using System.Management.Automation;
using System.Reflection;
using System.Text;
using Serilog;
using Serilog.Events;
namespace AutoBlockIP
{
internal class Program
{
private static readonly int threshold = 3;
private static readonly string[] whiteList = new string[] { "kuoann" };
private static readonly string[] blackList = new string[] { "administrator", "admin", "guest" };
private static readonly string firewallRuleName = "AutoBlockIP";
private static readonly string appName = Assembly.GetExecutingAssembly().GetName().Name;
private static readonly int trackMinutes = 10;
private static void Main(string[] args)
{
Serilog.Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console(outputTemplate: "{Timestamp:HH:mm:ss} [{Level:u3}]{Message}{NewLine}{Exception}")
.WriteTo.Seq("http://localhost:1315", restrictedToMinimumLevel: LogEventLevel.Information, bufferBaseFilename: @$"Logs\Seq-{appName}")
.CreateLogger();
try
{
Log.SetPrefix("[BlockIP] ");
Log.Warning("Start 🟢");
var blockIps = GetBlockIps();
if (blockIps.Count > 0)
{
var blockedIps = GetBlockedIps();
var finalBlockIps = new HashSet<string>(blockedIps);
finalBlockIps.UnionWith(blockIps);
var newBlockIps = finalBlockIps.Except(blockedIps).ToList();
if (newBlockIps.Count > 0)
{
Log.Warning("Block {newBlockIps}", string.Join("\n", newBlockIps));
if (SetFirewall(finalBlockIps.ToArray()))
{
Log.Information($"SetFirewall...OK ({finalBlockIps.Count})\n>> {string.Join(',', finalBlockIps)}");
}
else
{
Log.Error($"SetFirewall...Fail ({finalBlockIps.Count})");
}
}
else
{
Log.Information("No New BlockIP");
}
}
else
{
Log.Information("Can't Get BlockIP");
}
}
catch (Exception ex)
{
Log.Fatal(ex, ex.Message);
}
finally
{
Log.Warning("Stop 🔴");
Serilog.Log.CloseAndFlush();
#if DEBUG
Console.ReadKey();
#endif
}
}
/// <summary>
/// Get suspicious ips from event log
/// </summary>
private static List<string> GetBlockIps()
{
var attackIps = new List<string>();
var eventLog = new EventLog("Security");
var ips = new Dictionary<string, int>();
foreach (EventLogEntry e in eventLog.Entries)
{
if (e.InstanceId == 4625 &&
e.EntryType == EventLogEntryType.FailureAudit &&
e.TimeGenerated > DateTime.Now.AddMinutes(-trackMinutes))
{
if (e.ReplacementStrings.Length >= 19)
{
var targetUserName = e.ReplacementStrings[5];
var attackIp = e.ReplacementStrings[19];
if (ValidateIPv4(attackIp))
{
if (IsWhiteList(targetUserName))
{
continue;
}
if (ips.ContainsKey(attackIp))
{
// 更新 IP 攻擊次數 > 超過 threshold 則視為需封鎖的 IP
ips[attackIp]++;
}
else if (IsBlackList(targetUserName))
{
// 黑名單 -> 無視閾值
Log.Warning("Force Block {attackIp} {targetUserName}", attackIp, targetUserName);
ips.Add(attackIp, 666);
}
else
{
ips.Add(attackIp, 1);
}
}
}
}
}
// 過濾超過閾值的攻擊 IP
return ips.Where(x => x.Value > threshold).Select(x => x.Key).ToList();
}
private static bool ValidateIPv4(string ipString)
{
if (String.IsNullOrWhiteSpace(ipString))
{
return false;
}
string[] splitValues = ipString.Split('.');
if (splitValues.Length != 4)
{
return false;
}
byte tempForParsing;
return splitValues.All(r => byte.TryParse(r, out tempForParsing));
}
private static bool IsWhiteList(string userName) =>
!string.IsNullOrWhiteSpace(userName) && whiteList.Contains(userName.Trim().ToLower());
private static bool IsBlackList(string userName) =>
string.IsNullOrWhiteSpace(userName) ||
(!string.IsNullOrWhiteSpace(userName) && blackList.Contains(userName.Trim().ToLower()));
/// <summary>
/// Get Blocked ips from firewall
/// </summary>
private static List<string> GetBlockedIps()
{
var blockedIps = new List<string>();
using (var ps = PowerShell.Create())
{
var script = $@"
Set-ExecutionPolicy RemoteSigned -Scope Process -Force;
Import-Module NetSecurity;
[string[]](Get-NetFirewallRule -DisplayName '{firewallRuleName}' | Get-NetFirewallAddressFilter).RemoteAddress;
";
ps.AddScript(script);
var results = ps.Invoke<string>();
if (ps.HadErrors)
{
foreach (var error in ps.Streams.Error)
{
Log.Error($"Error: {error}");
}
}
else
{
blockedIps.AddRange(results);
}
}
return blockedIps;
}
/// <summary>
/// Set Blocked ips into firewall
/// </summary>
private static bool SetFirewall(string[] blockIps)
{
using (var ps = PowerShell.Create())
{
var remoteAddresses = string.Join(",", blockIps.Select(ip => $"\"{ip}\""));
var script = $@"
Set-ExecutionPolicy RemoteSigned -Scope Process -Force;
Import-Module NetSecurity;
Set-NetFirewallRule -DisplayName '{firewallRuleName}' -Direction Inbound -Action Block -RemoteAddress @({remoteAddresses})
";
ps.AddScript(script);
ps.Invoke();
if (ps.HadErrors)
{
foreach (var error in ps.Streams.Error)
{
Log.Error($"Error: {error}");
}
return false;
}
}
return true;
}
}
}