// Spludlow Software // Copyright © Samuel P. Ludlow 2020 All Rights Reserved // Distributed under the terms of the GNU General Public License version 3 // Distributed WITHOUT ANY WARRANTY; without implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE // https://www.spludlow.co.uk/LICENCE.TXT // The Spludlow logo is a registered trademark of Samuel P. Ludlow and may not be used without permission // v1.14 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using NetFwTypeLib; // C:\Windows\System32\FirewallAPI.dll using System.IO; using System.Data; namespace Spludlow.Net { /// /// Some methods for setting an IP block list in Windows Firewall needs runing as admin (Make the CallText on the Spludlow Call page and run with Spludlow-Process.exe) /// Also method for getting Audit Failure IPs out of the Security Event Log /// public class Firewall { private static string _BlockRuleName = "Spludlow IP Block"; /// /// Configure Windows Firewall to block all incoming connections from specified IP /// Creates rule if not exists (first time) /// Takes care of duplicates and sorts the list /// public static void BlockIP(string ipAddress) { BlockIP(new string[] { ipAddress }); } public static void BlockIP(string[] ipAddresses) { INetFwPolicy2 policy = (INetFwPolicy2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2")); INetFwRule2 rule = GetRule(policy, _BlockRuleName); if (rule == null) { rule = (INetFwRule2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FWRule")); rule.Name = _BlockRuleName; rule.Description = ""; rule.Action = NET_FW_ACTION_.NET_FW_ACTION_BLOCK; rule.Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN; rule.Enabled = true; List ips = new List(ipAddresses); ips.Sort(); rule.RemoteAddresses = MakeAddresses(ips); policy.Rules.Add(rule); } else { List ips = RemoteAddresses(rule); foreach (string ip in ipAddresses) { if (ips.Contains(ip) == false) ips.Add(ip); } ips.Sort(); rule.RemoteAddresses = MakeAddresses(ips); } } public static string[] ListBlockedIP() { INetFwPolicy2 policy = (INetFwPolicy2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2")); INetFwRule2 rule = GetRule(policy, _BlockRuleName); if (rule == null) return new string[0]; return RemoteAddresses(rule).ToArray(); } private static INetFwRule2 GetRule(INetFwPolicy2 policy, string name) { try { return (INetFwRule2)policy.Rules.Item(_BlockRuleName); } catch (FileNotFoundException) { return null; } } private static List RemoteAddresses(INetFwRule2 rule) { List ips = new List(); string[] parts = Spludlow.Text.Split(rule.RemoteAddresses, ',', true, false); foreach (string part in parts) { string ip = part.Substring(0, part.IndexOf("/")); if (ips.Contains(ip) == false) ips.Add(ip); } ips.Sort(); return ips; } private static string MakeAddresses(List ips) { StringBuilder remote = new StringBuilder(); foreach (string ip in ips) { if (remote.Length > 0) remote.Append(","); remote.Append(ip); remote.Append("/255.255.255.255"); } return remote.ToString(); } /// /// Run this against an XML Event Log export then check the Report in Spludlow Logs to get IP list /// public static void ReportSecurityEventLogIPs(string xmlFilename, bool reportCountry) { DataTable table = ProcessEventLogsExport(xmlFilename); DataTable resultTable = Spludlow.Data.TextTable.ReadText(new string[] { "Event_Id SystemTime System_EventID TargetUserName IpAddress", "Int32 DateTime String String String", }); foreach (DataRow row in table.Rows) { string eventId = (string)row["System_EventID"]; if (eventId != "4625") continue; string ip = (string)row["IpAddress"]; if (ip == "-") continue; resultTable.ImportRow(row); } resultTable = Spludlow.Data.ADO.CountOccurrence(resultTable, "IpAddress"); if (reportCountry == true) { resultTable.Columns.Add("Country", typeof(string)); foreach (DataRow row in resultTable.Rows) row["Country"] = Spludlow.Net.IpWhoIs.CountryCode((string)row["IpAddress"]); } Spludlow.Log.Report("ProcessEventLogsExport", resultTable); } /// /// Put the exported XML into a single table /// public static DataTable ProcessEventLogsExport(string xmlFilename) { // Process into tables DataSet dataSet = Spludlow.Data.XML.ConvertRelational(xmlFilename, "Events"); // Result Table DataTable table = new DataTable(); table.Columns.Add("Event_Id", typeof(int)); table.Columns.Add("SystemTime", typeof(DateTime)); // Add all system columns foreach (DataColumn column in dataSet.Tables["System"].Columns) { if (column.ColumnName.EndsWith("_Id") == false) table.Columns.Add("System_" + column.ColumnName, column.DataType); } // Add all data name columns HashSet dataColumns = new HashSet(); foreach (DataRow row in dataSet.Tables["Data"].Rows) { string name = (string)row["Name"]; if (dataColumns.Contains(name) == false) dataColumns.Add(name); } foreach (string name in dataColumns) table.Columns.Add(name, typeof(string)); // Each event foreach (DataRow EventRow in dataSet.Tables["Event"].Rows) { int Event_Id = (int)EventRow["Event_Id"]; // Find resolver ID DataRow EventDataRow = FindRow(dataSet.Tables["EventData"], "Event_Id = " + Event_Id, true); if (EventDataRow == null) continue; int EventData_Id = (int)EventDataRow["EventData_Id"]; // New Result row DataRow row = table.NewRow(); row["Event_Id"] = Event_Id; // Add info from System table DataRow SystemRow = FindRow(dataSet.Tables["System"], "Event_Id = " + Event_Id, false); foreach (DataColumn column in dataSet.Tables["System"].Columns) { if (table.Columns.Contains("System_" + column.ColumnName) == true) row["System_" + column.ColumnName] = SystemRow[column.ColumnName]; } int System_Id = (int)SystemRow["System_Id"]; // Get the time DataRow TimeCreatedRow = FindRow(dataSet.Tables["TimeCreated"], "System_Id = " + System_Id, false); row["SystemTime"] = DateTime.Parse((string)TimeCreatedRow["SystemTime"]); // Add the data foreach (DataRow DataRow in dataSet.Tables["Data"].Select("EventData_Id = " + EventData_Id)) { if (DataRow.IsNull("DataValue") == false) row[(string)DataRow["Name"]] = (string)DataRow["DataValue"]; } table.Rows.Add(row); } return table; } private static DataRow FindRow(DataTable table, string filter, bool dontThrow) { DataRow[] rows = table.Select(filter); if (rows.Length == 1) return rows[0]; if (dontThrow == true && rows.Length == 0) return null; throw new ApplicationException("FindRow did not find one row: " + table.TableName + ", " + filter + ", " + rows.Length); } } }