Skip to content

Commit

Permalink
Tweak smarter mail log, other misc fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
jjxtra committed Jun 15, 2019
1 parent c945fef commit 3dfa0e9
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 89 deletions.
43 changes: 29 additions & 14 deletions Core/IPBanDB.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,16 @@ public IPBanDBTransaction(string connString)
{
DBConnection = new SqliteConnection(connString);
DBConnection.Open();
using (SqliteCommand command = DBConnection.CreateCommand())
{
command.CommandText = "PRAGMA auto_vacuum = INCREMENTAL;";
command.ExecuteNonQuery();
}
using (SqliteCommand command = DBConnection.CreateCommand())
{
command.CommandText = "PRAGMA journal_mode = WAL;";
command.ExecuteNonQuery();
}
DBTransaction = DBConnection.BeginTransaction(transactionLevel);
}

Expand Down Expand Up @@ -130,10 +140,6 @@ public void Rollback()
public const string FileName = "ipban.sqlite";

private const System.Data.IsolationLevel transactionLevel = System.Data.IsolationLevel.Serializable;

// note that an ip that has a block count may not yet be in the ipAddressesAndBanDate dictionary
// for locking, always use ipAddressesAndBanDate
private readonly string dbPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, FileName);
private readonly string connString;

private int ExecuteNonQuery(string cmdText, params object[] param)
Expand All @@ -147,7 +153,7 @@ private int ExecuteNonQuery(SqliteConnection conn, SqliteTransaction tran, strin
if (conn == null)
{
conn = new SqliteConnection(connString);
conn.Open();
OpenConnection(conn);
closeConn = true;
}
try
Expand All @@ -174,10 +180,10 @@ private int ExecuteNonQuery(SqliteConnection conn, SqliteTransaction tran, strin

private T ExecuteScalar<T>(string cmdText, params object[] param)
{
using (SqliteConnection connection = new SqliteConnection(connString))
using (SqliteConnection conn = new SqliteConnection(connString))
{
connection.Open();
using (SqliteCommand command = connection.CreateCommand())
OpenConnection(conn);
using (SqliteCommand command = conn.CreateCommand())
{
command.CommandText = cmdText;
for (int i = 0; i < param.Length; i++)
Expand All @@ -195,7 +201,7 @@ private SqliteDataReader ExecuteReader(string query, SqliteConnection conn, Sqli
if (conn == null)
{
conn = new SqliteConnection(connString);
conn.Open();
OpenConnection(conn);
closeConnection = true;
}
SqliteCommand command = conn.CreateCommand();
Expand All @@ -208,6 +214,13 @@ private SqliteDataReader ExecuteReader(string query, SqliteConnection conn, Sqli
return command.ExecuteReader((closeConnection ? System.Data.CommandBehavior.CloseConnection : System.Data.CommandBehavior.Default));
}

private void OpenConnection(SqliteConnection conn)
{
conn.Open();
ExecuteNonQuery(conn, null, "PRAGMA auto_vacuum = INCREMENTAL;");
ExecuteNonQuery(conn, null, "PRAGMA journal_mode = WAL;");
}

private IPAddressEntry ParseIPAddressEntry(SqliteDataReader reader)
{
string ipAddress = reader.GetString(0);
Expand Down Expand Up @@ -245,6 +258,7 @@ ON CONFLICT(IPAddress)

private void Initialize()
{
IPBanLog.Info("Initializing IPBan database at {0}", connString);
SQLitePCL.Batteries.Init();
ExecuteNonQuery("PRAGMA auto_vacuum = INCREMENTAL;");
ExecuteNonQuery("PRAGMA journal_mode = WAL;");
Expand All @@ -268,8 +282,9 @@ private void Initialize()
/// <summary>
/// Constructor
/// </summary>
public IPBanDB()
public IPBanDB(string dbPath = null)
{
dbPath = (string.IsNullOrWhiteSpace(dbPath) ? Path.Combine(AppDomain.CurrentDomain.BaseDirectory, FileName) : dbPath);
connString = "Data Source=" + dbPath;
Initialize();
}
Expand Down Expand Up @@ -466,7 +481,7 @@ public int SetBannedIPAddresses(IEnumerable<KeyValuePair<string, DateTime>> ipAd
int count = 0;
using (SqliteConnection conn = new SqliteConnection(connString))
{
conn.Open();
OpenConnection(conn);
using (SqliteTransaction tran = conn.BeginTransaction(transactionLevel))
{
foreach (KeyValuePair<string, DateTime> ipAddress in ipAddresses)
Expand Down Expand Up @@ -494,7 +509,7 @@ public int SetIPAddressesState(IEnumerable<string> ipAddresses, IPAddressState s
SqliteConnection conn = (ipDBTransaction?.DBConnection ?? new SqliteConnection(connString));
if (commit)
{
conn.Open();
OpenConnection(conn);
}
SqliteTransaction tran = (ipDBTransaction?.DBTransaction ?? conn.BeginTransaction(transactionLevel));
int stateInt = (int)state;
Expand Down Expand Up @@ -537,7 +552,7 @@ public IEnumerable<IPBanFirewallIPAddressDelta> EnumerateIPAddressesDelta(bool c
{
using (SqliteConnection conn = new SqliteConnection(connString))
{
conn.Open();
OpenConnection(conn);
using (SqliteTransaction tran = conn.BeginTransaction(transactionLevel))
{
using (SqliteDataReader reader = ExecuteReader("SELECT IPAddressText, State FROM IPAddresses WHERE State IN (1, 2) ORDER BY IPAddressText", conn, tran))
Expand Down Expand Up @@ -629,7 +644,7 @@ public int DeleteIPAddresses(IEnumerable<string> ipAddresses)

using (SqliteConnection conn = new SqliteConnection(connString))
{
conn.Open();
OpenConnection(conn);
using (SqliteTransaction tran = conn.BeginTransaction(transactionLevel))
{
foreach (string ipAddress in ipAddresses)
Expand Down
105 changes: 56 additions & 49 deletions Core/IPBanFirewallUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,70 +103,77 @@ public static bool TryNormalizeIPAddress(this string ipAddress, out string norma
/// <returns>Firewall</returns>
public static IIPBanFirewall CreateFirewall(IReadOnlyDictionary<string, string> osAndFirewall, string rulePrefix = null, IIPBanFirewall existing = null)
{
bool foundFirewallType = false;
int priority = int.MinValue;
Type firewallType = typeof(IIPBanFirewall);
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies().ToArray();
Type[] types = assemblies.SelectMany(a => a.GetTypes()).ToArray();
var q =
from fwType in types
where fwType.IsPublic &&
fwType != firewallType &&
firewallType.IsAssignableFrom(fwType) &&
fwType.GetCustomAttribute<RequiredOperatingSystemAttribute>() != null &&
fwType.GetCustomAttribute<RequiredOperatingSystemAttribute>().IsValid
select new { FirewallType = fwType, OS = fwType.GetCustomAttribute<RequiredOperatingSystemAttribute>(), Name = fwType.GetCustomAttribute<CustomNameAttribute>() };
var array = q.ToArray();
foreach (var result in array)
try
{
// look up the requested firewall by os name
bool matchPriority = priority < result.OS.Priority;
if (matchPriority)
bool foundFirewallType = false;
int priority = int.MinValue;
Type firewallType = typeof(IIPBanFirewall);
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies().ToArray();
Type[] types = assemblies.SelectMany(a => a.GetTypes()).ToArray();
var q =
from fwType in types
where fwType.IsPublic &&
fwType != firewallType &&
firewallType.IsAssignableFrom(fwType) &&
fwType.GetCustomAttribute<RequiredOperatingSystemAttribute>() != null &&
fwType.GetCustomAttribute<RequiredOperatingSystemAttribute>().IsValid
select new { FirewallType = fwType, OS = fwType.GetCustomAttribute<RequiredOperatingSystemAttribute>(), Name = fwType.GetCustomAttribute<CustomNameAttribute>() };
var array = q.ToArray();
foreach (var result in array)
{
bool matchName = true;
if (osAndFirewall != null && osAndFirewall.Count != 0 &&
(osAndFirewall.TryGetValue(IPBanOS.Name, out string firewallToUse) || osAndFirewall.TryGetValue("*", out firewallToUse)))
{
matchName = result.Name.Name.Equals(firewallToUse, StringComparison.OrdinalIgnoreCase);
}
if (matchName)
// look up the requested firewall by os name
bool matchPriority = priority < result.OS.Priority;
if (matchPriority)
{
// if IsAvailable method is provided, attempt to call
MethodInfo available = result.FirewallType.GetMethod("IsAvailable", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
if (available != null)
bool matchName = true;
if (osAndFirewall != null && osAndFirewall.Count != 0 &&
(osAndFirewall.TryGetValue(IPBanOS.Name, out string firewallToUse) || osAndFirewall.TryGetValue("*", out firewallToUse)))
{
try
matchName = result.Name.Name.Equals(firewallToUse, StringComparison.OrdinalIgnoreCase);
}
if (matchName)
{
// if IsAvailable method is provided, attempt to call
MethodInfo available = result.FirewallType.GetMethod("IsAvailable", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
if (available != null)
{
if (!Convert.ToBoolean(available.Invoke(null, null)))
try
{
if (!Convert.ToBoolean(available.Invoke(null, null)))
{
continue;
}
}
catch
{
continue;
}
}
catch
{
continue;
}
firewallType = result.FirewallType;
priority = result.OS.Priority;
foundFirewallType = true;
}
firewallType = result.FirewallType;
priority = result.OS.Priority;
foundFirewallType = true;
}
}
if (firewallType == null)
{
throw new ArgumentException("Firewall is null, at least one type should implement IIPBanFirewall");
}
else if (osAndFirewall.Count != 0 && !foundFirewallType)
{
string typeString = string.Join(',', osAndFirewall.Select(kv => kv.Key + ":" + kv.Value));
throw new ArgumentException("Unable to find firewalls of types: " + typeString + ", osname: " + IPBanOS.Name);
}
if (existing != null && existing.GetType().Equals(firewallType))
{
return existing;
}
return Activator.CreateInstance(firewallType, new object[] { rulePrefix }) as IIPBanFirewall;
}
if (firewallType == null)
{
throw new ArgumentException("Firewall is null, at least one type should implement IIPBanFirewall");
}
else if (osAndFirewall.Count != 0 && !foundFirewallType)
{
string typeString = string.Join(',', osAndFirewall.Select(kv => kv.Key + ":" + kv.Value));
throw new ArgumentException("Unable to find firewalls of types: " + typeString + ", osname: " + IPBanOS.Name);
}
if (existing != null && existing.GetType().Equals(firewallType))
catch (Exception ex)
{
return existing;
throw new ArgumentException("Unable to create firewall, please double check your Firewall configuration property", ex);
}
return Activator.CreateInstance(firewallType, new object[] { rulePrefix }) as IIPBanFirewall;
}

/// <summary>
Expand Down
5 changes: 5 additions & 0 deletions Core/IPBanMemoryFirewall.cs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,11 @@ private string ScrubRuleNamePrefix(string ruleNamePrefix)
return (RulePrefix + (ruleNamePrefix ?? string.Empty)).Trim('_');
}

public IPBanMemoryFirewall(string rulePrefix = null)
{
RulePrefix = (string.IsNullOrWhiteSpace(rulePrefix) ? RulePrefix : rulePrefix);
}

public void Update()
{
}
Expand Down
41 changes: 25 additions & 16 deletions Core/IPBanService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,12 @@ private class IPAddressPendingEvent
private System.Timers.Timer cycleTimer;
private bool firewallNeedsBlockedIPAddressesUpdate;
private bool gotStartUrl;
private IPBanDB ipDB;

// batch failed logins every cycle
private readonly List<IPAddressPendingEvent> pendingFailedLogins = new List<IPAddressPendingEvent>();
private readonly List<IPAddressPendingEvent> pendingSuccessfulLogins = new List<IPAddressPendingEvent>();
private readonly List<IPAddressLogEvent> pendingLogEvents = new List<IPAddressLogEvent>();

// note that an ip that has a block count may not yet be in the ipAddressesAndBanDate dictionary
// for locking, always use ipAddressesAndBanDate
private readonly IPBanDB ipDB;

private readonly object configLock = new object();
private readonly HashSet<IUpdater> updaters = new HashSet<IUpdater>();
private readonly HashSet<IPBanLogFileScanner> logFilesToParse = new HashSet<IPBanLogFileScanner>();
Expand Down Expand Up @@ -908,7 +904,10 @@ private void ProcessPendingLogEvents()
IPBanLog.Error(ex);
}
ExecuteExternalProcessForBannedIPAddresses(bannedIPs);
UnblockIPAddresses(unbannedIPs);
if (unbannedIPs.Count != 0)
{
UnblockIPAddresses(unbannedIPs);
}
}

/// <summary>
Expand All @@ -918,7 +917,6 @@ protected IPBanService()
{
OSName = IPBanOS.Name + (string.IsNullOrWhiteSpace(IPBanOS.FriendlyName) ? string.Empty : " (" + IPBanOS.FriendlyName + ")");
OSVersion = IPBanOS.Version;
ipDB = new IPBanDB();
}

/// <summary>
Expand Down Expand Up @@ -1121,7 +1119,7 @@ public void Dispose()
{
file.Dispose();
}
ipDB.Dispose();
ipDB?.Dispose();
IPBanLog.Warn("Stopped IPBan service");
}
catch
Expand All @@ -1140,7 +1138,8 @@ public void Start()
return;
}

if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
ipDB = new IPBanDB(DatabasePath);
if (UseWindowsEventViewer && RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
// attach Windows event viewer to the service
EventViewer = new IPBanWindowsEventViewer(this);
Expand Down Expand Up @@ -1422,30 +1421,35 @@ public static void DisposeIPBanTestService(IPBanService service)
/// </summary>
public IPBanConfig Config { get; private set; }

/// <summary>
/// Version of the software
/// </summary>
public string Version { get; set; } = Assembly.GetEntryAssembly().GetName().Version.ToString();

/// <summary>
/// Local ip address
/// </summary>
public string LocalIPAddressString { get; private set; }
public string LocalIPAddressString { get; set; }

/// <summary>
/// Remote ip address
/// </summary>
public string RemoteIPAddressString { get; private set; }
public string RemoteIPAddressString { get; set; }

/// <summary>
/// Fully qualified domain name
/// </summary>
public string FQDN { get; private set; }
public string FQDN { get; set; }

/// <summary>
/// Version of the software
/// Machine guid, null/empty for none
/// </summary>
public string Version { get; private set; } = Assembly.GetEntryAssembly().GetName().Version.ToString();
public string MachineGuid { get; set; }

/// <summary>
/// Machine guid, null/empty for none
/// Override the sqlite database path, leave null for default
/// </summary>
public string MachineGuid { get; set; }
public string DatabasePath { get; set; }

/// <summary>
/// External delegate to allow external config, whitelist, blacklist, etc.
Expand Down Expand Up @@ -1482,6 +1486,11 @@ public static void DisposeIPBanTestService(IPBanService service)
/// </summary>
public IPBanWindowsEventViewer EventViewer { get; private set; }

/// <summary>
/// Whether to link up to the Windows event viewer on Start
/// </summary>
public bool UseWindowsEventViewer { get; set; } = true;

/// <summary>
/// Log files to parse
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion IPBan.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
<PackageReference Include="Microsoft.Packaging.Tools.Trimming" Version="1.1.0-preview1-26619-01" />
<PackageReference Include="Microsoft.Windows.Compatibility" Version="2.1.1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="NLog" Version="4.6.4" />
<PackageReference Include="NLog" Version="4.6.5" />
</ItemGroup>

<ItemGroup>
Expand Down
Loading

0 comments on commit 3dfa0e9

Please sign in to comment.