mirror of
https://git.teknik.io/Teknikode/Teknik.git
synced 2023-08-02 14:16:22 +02:00
Added IP and Referrer blacklists.
This commit is contained in:
parent
8827992935
commit
bea394cbaf
0
Teknik/App_Data/ipBlacklist.txt
Normal file
0
Teknik/App_Data/ipBlacklist.txt
Normal file
1
Teknik/App_Data/referrerBlacklist.txt
Normal file
1
Teknik/App_Data/referrerBlacklist.txt
Normal file
@ -0,0 +1 @@
|
||||
xn--cckl0itdpc9763ahlyc.tv
|
178
Teknik/Modules/BlacklistModule.cs
Normal file
178
Teknik/Modules/BlacklistModule.cs
Normal file
@ -0,0 +1,178 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.Web;
|
||||
using System.Web.Caching;
|
||||
using System.Web.Helpers;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using Teknik.Areas.Error.Controllers;
|
||||
using Teknik.Configuration;
|
||||
|
||||
namespace Teknik.Modules
|
||||
{
|
||||
public class BlacklistModule : IHttpModule
|
||||
{
|
||||
|
||||
private EventHandler onBeginRequest;
|
||||
|
||||
public BlacklistModule()
|
||||
{
|
||||
onBeginRequest = new EventHandler(this.HandleBeginRequest);
|
||||
}
|
||||
|
||||
void IHttpModule.Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
void IHttpModule.Init(HttpApplication context)
|
||||
{
|
||||
context.BeginRequest += onBeginRequest;
|
||||
}
|
||||
|
||||
#region Referrer Info
|
||||
private const string BLOCKEDREFERRERKEY = "BlockedReferrer";
|
||||
private static string referrerFileName = null;
|
||||
private static object referrerFileNameObj = new object();
|
||||
|
||||
public static string GetReferrerFilePath()
|
||||
{
|
||||
if (referrerFileName != null)
|
||||
return referrerFileName;
|
||||
lock (referrerFileNameObj)
|
||||
{
|
||||
if (referrerFileName == null)
|
||||
{
|
||||
Config config = Config.Load();
|
||||
referrerFileName = config.ReferrerBlacklistFile;
|
||||
}
|
||||
}
|
||||
|
||||
return referrerFileName;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IP Info
|
||||
private const string BLOCKEDIPKEY = "BlockedIP";
|
||||
private static string ipFileName = null;
|
||||
private static object ipFileNameObj = new object();
|
||||
|
||||
public static string GetIPFilePath()
|
||||
{
|
||||
if (ipFileName != null)
|
||||
return ipFileName;
|
||||
lock (ipFileNameObj)
|
||||
{
|
||||
if (ipFileName == null)
|
||||
{
|
||||
Config config = Config.Load();
|
||||
ipFileName = config.IPBlacklistFile;
|
||||
}
|
||||
}
|
||||
|
||||
return ipFileName;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public static StringDictionary GetFileData(HttpContext context, string key, Func<string> fn)
|
||||
{
|
||||
StringDictionary data = (StringDictionary)context.Cache[key];
|
||||
if (data == null)
|
||||
{
|
||||
string filePath = fn();
|
||||
data = GetFileLines(filePath);
|
||||
context.Cache.Insert(key, data, new CacheDependency(filePath));
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public static StringDictionary GetFileLines(string configPath)
|
||||
{
|
||||
StringDictionary retval = new StringDictionary();
|
||||
if (File.Exists(configPath))
|
||||
{
|
||||
using (StreamReader sr = new StreamReader(configPath))
|
||||
{
|
||||
String line;
|
||||
while ((line = sr.ReadLine()) != null)
|
||||
{
|
||||
line = line.Trim();
|
||||
if (line.Length != 0)
|
||||
{
|
||||
retval.Add(line, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
private void HandleBeginRequest(object sender, EventArgs evargs)
|
||||
{
|
||||
HttpApplication app = sender as HttpApplication;
|
||||
|
||||
if (app != null)
|
||||
{
|
||||
bool blocked = false;
|
||||
string blockReason = string.Empty;
|
||||
|
||||
#region Detect Blacklisted IPs
|
||||
if (!blocked)
|
||||
{
|
||||
string IPAddr = app.Context.Request.ServerVariables["REMOTE_ADDR"];
|
||||
if (!string.IsNullOrEmpty(IPAddr))
|
||||
{
|
||||
StringDictionary badIPs = GetFileData(app.Context, BLOCKEDIPKEY, GetIPFilePath);
|
||||
|
||||
blocked |= (badIPs != null && badIPs.ContainsKey(IPAddr));
|
||||
blockReason = $"This IP address ({IPAddr}) has been blacklisted. If you feel this is in error, please contact support@teknik.io for assistance.";
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Detect Blacklisted Referrers
|
||||
if (!blocked)
|
||||
{
|
||||
string referrer = app.Context.Request.UrlReferrer?.Host;
|
||||
if (!string.IsNullOrEmpty(referrer))
|
||||
{
|
||||
StringDictionary badReferrers = GetFileData(app.Context, BLOCKEDREFERRERKEY, GetReferrerFilePath);
|
||||
|
||||
blocked |= (badReferrers != null && badReferrers.ContainsKey(referrer));
|
||||
blockReason = $"This referrer ({referrer}) has been blacklisted. If you feel this is in error, please contact support@teknik.io for assistance.";
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
if (blocked)
|
||||
{
|
||||
// Clear the response
|
||||
app.Context.Response.Clear();
|
||||
|
||||
RouteData routeData = new RouteData();
|
||||
routeData.DataTokens.Add("namespaces", new[] { typeof(ErrorController).Namespace });
|
||||
routeData.DataTokens.Add("area", "Error");
|
||||
routeData.Values.Add("controller", "Error");
|
||||
routeData.Values.Add("scheme", "https");
|
||||
routeData.Values.Add("action", "Http403");
|
||||
|
||||
// Clear the error on server.
|
||||
app.Context.Server.ClearError();
|
||||
|
||||
// Avoid IIS7 getting in the middle
|
||||
app.Context.Response.TrySkipIisCustomErrors = true;
|
||||
|
||||
string jsonResult = Json.Encode(new { error = new { type = "Blacklist", message = blockReason } });
|
||||
app.Context.Response.Write(jsonResult);
|
||||
app.Context.Response.End();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -29,46 +29,45 @@ namespace Teknik.Modules
|
||||
string username = string.Empty;
|
||||
|
||||
bool hasAuthToken = false;
|
||||
if (context.Request != null)
|
||||
if (context.Request.Headers.HasKeys())
|
||||
{
|
||||
if (context.Request.Headers.HasKeys())
|
||||
string auth = context.Request.Headers["Authorization"];
|
||||
if (!string.IsNullOrEmpty(auth))
|
||||
{
|
||||
string auth = context.Request.Headers["Authorization"];
|
||||
if (!string.IsNullOrEmpty(auth))
|
||||
string[] parts = auth.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
|
||||
string type = string.Empty;
|
||||
string value = string.Empty;
|
||||
if (parts.Length > 0)
|
||||
{
|
||||
string[] parts = auth.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
string type = string.Empty;
|
||||
string value = string.Empty;
|
||||
if (parts.Length > 0)
|
||||
{
|
||||
type = parts[0].ToLower();
|
||||
}
|
||||
if (parts.Length > 1)
|
||||
{
|
||||
value = parts[1];
|
||||
}
|
||||
type = parts[0].ToLower();
|
||||
}
|
||||
|
||||
using (TeknikEntities entities = new TeknikEntities())
|
||||
if (parts.Length > 1)
|
||||
{
|
||||
value = parts[1];
|
||||
}
|
||||
|
||||
using (TeknikEntities entities = new TeknikEntities())
|
||||
{
|
||||
// Get the user information based on the auth type
|
||||
switch (type)
|
||||
{
|
||||
// Get the user information based on the auth type
|
||||
switch (type)
|
||||
{
|
||||
case "basic":
|
||||
KeyValuePair<string, string> authCreds = StringHelper.ParseBasicAuthHeader(value);
|
||||
case "basic":
|
||||
KeyValuePair<string, string> authCreds = StringHelper.ParseBasicAuthHeader(value);
|
||||
|
||||
bool tokenValid = UserHelper.UserTokenCorrect(entities, authCreds.Key, authCreds.Value);
|
||||
if (tokenValid)
|
||||
{
|
||||
// it's valid, so let's update it's Last Used date
|
||||
UserHelper.UpdateTokenLastUsed(entities, authCreds.Key, authCreds.Value, DateTime.Now);
|
||||
bool tokenValid = UserHelper.UserTokenCorrect(entities, authCreds.Key, authCreds.Value);
|
||||
if (tokenValid)
|
||||
{
|
||||
// it's valid, so let's update it's Last Used date
|
||||
UserHelper.UpdateTokenLastUsed(entities, authCreds.Key, authCreds.Value, DateTime.Now);
|
||||
|
||||
// Set the username
|
||||
username = authCreds.Key;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// Set the username
|
||||
username = authCreds.Key;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -321,6 +321,7 @@
|
||||
<Compile Include="Areas\Vault\ViewModels\VaultItemViewModel.cs" />
|
||||
<Compile Include="Attributes\TeknikAuthorizeAttribute.cs" />
|
||||
<Compile Include="Hubs\IRCClientHub.cs" />
|
||||
<Compile Include="Modules\BlacklistModule.cs" />
|
||||
<Compile Include="Modules\UserAuthModule.cs" />
|
||||
<Compile Include="Security\ITeknikPrincipal.cs" />
|
||||
<Compile Include="Security\TeknikPrincipal.cs" />
|
||||
@ -395,6 +396,8 @@
|
||||
<Compile Include="BaseViewPage.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="App_Data\ipBlacklist.txt" />
|
||||
<Content Include="App_Data\referrerBlacklist.txt" />
|
||||
<Content Include="App_Data\reservedUsernames.txt">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
@ -56,6 +56,7 @@
|
||||
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />
|
||||
<add name="PerfModule" type="Teknik.Modules.PerformanceMonitorModule, Teknik" />
|
||||
<add name="UserAuthModule" type="Teknik.Modules.UserAuthModule, Teknik" />
|
||||
<add name="BlacklistModule" type="Teknik.Modules.BlacklistModule, Teknik" />
|
||||
<remove name="UrlRoutingModule-4.0" />
|
||||
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
|
||||
</modules>
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using Newtonsoft.Json;
|
||||
@ -29,6 +29,8 @@ namespace Teknik.Configuration
|
||||
private string _Salt1;
|
||||
private string _Salt2;
|
||||
private string _CdnHost;
|
||||
private string _IPBlacklistFile;
|
||||
private string _ReferrerBlacklistFile;
|
||||
private UserConfig _UserConfig;
|
||||
private ContactConfig _ContactConfig;
|
||||
private EmailConfig _EmailConfig;
|
||||
@ -46,21 +48,23 @@ namespace Teknik.Configuration
|
||||
private PiwikConfig _PiwikConfig;
|
||||
private IRCConfig _IRCConfig;
|
||||
|
||||
public bool DevEnvironment { get { return _DevEnvironment; } set { _DevEnvironment = value; } }
|
||||
public bool Migrate { get { return _Migrate; } set { _Migrate = value; } }
|
||||
public bool UseCdn { get { return _UseCdn; } set { _UseCdn = value; } }
|
||||
public bool DevEnvironment { get { return _DevEnvironment; } set { _DevEnvironment = value; } }
|
||||
public bool Migrate { get { return _Migrate; } set { _Migrate = value; } }
|
||||
public bool UseCdn { get { return _UseCdn; } set { _UseCdn = value; } }
|
||||
|
||||
// Site Information
|
||||
public string Title { get { return _Title; } set { _Title = value; } }
|
||||
public string Description { get { return _Description; } set { _Description = value; } }
|
||||
public string Author { get { return _Author; } set { _Author = value; } }
|
||||
public string Host { get { return _Host; } set { _Host = value; } }
|
||||
public string SupportEmail { get { return _SupportEmail; } set { _SupportEmail = value; } }
|
||||
public string NoReplyEmail { get { return _NoReplyEmail; } set { _NoReplyEmail = value; } }
|
||||
public string BitcoinAddress { get { return _BitcoinAddress; } set { _BitcoinAddress = value; } }
|
||||
public string Salt1 { get { return _Salt1; } set { _Salt1 = value; } }
|
||||
public string Salt2 { get { return _Salt2; } set { _Salt2 = value; } }
|
||||
public string CdnHost { get { return _CdnHost; } set { _CdnHost = value; } }
|
||||
public string Title { get { return _Title; } set { _Title = value; } }
|
||||
public string Description { get { return _Description; } set { _Description = value; } }
|
||||
public string Author { get { return _Author; } set { _Author = value; } }
|
||||
public string Host { get { return _Host; } set { _Host = value; } }
|
||||
public string SupportEmail { get { return _SupportEmail; } set { _SupportEmail = value; } }
|
||||
public string NoReplyEmail { get { return _NoReplyEmail; } set { _NoReplyEmail = value; } }
|
||||
public string BitcoinAddress { get { return _BitcoinAddress; } set { _BitcoinAddress = value; } }
|
||||
public string Salt1 { get { return _Salt1; } set { _Salt1 = value; } }
|
||||
public string Salt2 { get { return _Salt2; } set { _Salt2 = value; } }
|
||||
public string CdnHost { get { return _CdnHost; } set { _CdnHost = value; } }
|
||||
public string IPBlacklistFile { get { return _IPBlacklistFile;} set { _IPBlacklistFile = value; }}
|
||||
public string ReferrerBlacklistFile { get { return _ReferrerBlacklistFile;} set { _ReferrerBlacklistFile = value; }}
|
||||
|
||||
// User Configuration
|
||||
public UserConfig UserConfig { get { return _UserConfig; } set { _UserConfig = value; } }
|
||||
@ -122,35 +126,37 @@ namespace Teknik.Configuration
|
||||
|
||||
public void SetDefaults()
|
||||
{
|
||||
DevEnvironment = false;
|
||||
Migrate = false;
|
||||
UseCdn = false;
|
||||
Title = string.Empty;
|
||||
Description = string.Empty;
|
||||
Author = string.Empty;
|
||||
Host = string.Empty;
|
||||
SupportEmail = string.Empty;
|
||||
NoReplyEmail = string.Empty;
|
||||
BitcoinAddress = string.Empty;
|
||||
Salt1 = string.Empty;
|
||||
Salt2 = string.Empty;
|
||||
CdnHost = string.Empty;
|
||||
UserConfig = new UserConfig();
|
||||
EmailConfig = new EmailConfig();
|
||||
ContactConfig = new ContactConfig();
|
||||
GitConfig = new GitConfig();
|
||||
BlogConfig = new BlogConfig();
|
||||
UploadConfig = new UploadConfig();
|
||||
PasteConfig = new PasteConfig();
|
||||
ApiConfig = new ApiConfig();
|
||||
PodcastConfig = new PodcastConfig();
|
||||
StreamConfig = new StreamConfig();
|
||||
ShortenerConfig = new ShortenerConfig();
|
||||
VaultConfig = new VaultConfig();
|
||||
StatusConfig = new StatusConfig();
|
||||
LoggingConfig = new LoggingConfig();
|
||||
PiwikConfig = new PiwikConfig();
|
||||
IRCConfig = new IRCConfig();
|
||||
DevEnvironment = false;
|
||||
Migrate = false;
|
||||
UseCdn = false;
|
||||
Title = string.Empty;
|
||||
Description = string.Empty;
|
||||
Author = string.Empty;
|
||||
Host = string.Empty;
|
||||
SupportEmail = string.Empty;
|
||||
NoReplyEmail = string.Empty;
|
||||
BitcoinAddress = string.Empty;
|
||||
Salt1 = string.Empty;
|
||||
Salt2 = string.Empty;
|
||||
CdnHost = string.Empty;
|
||||
IPBlacklistFile = string.Empty;
|
||||
ReferrerBlacklistFile = string.Empty;
|
||||
UserConfig = new UserConfig();
|
||||
EmailConfig = new EmailConfig();
|
||||
ContactConfig = new ContactConfig();
|
||||
GitConfig = new GitConfig();
|
||||
BlogConfig = new BlogConfig();
|
||||
UploadConfig = new UploadConfig();
|
||||
PasteConfig = new PasteConfig();
|
||||
ApiConfig = new ApiConfig();
|
||||
PodcastConfig = new PodcastConfig();
|
||||
StreamConfig = new StreamConfig();
|
||||
ShortenerConfig = new ShortenerConfig();
|
||||
VaultConfig = new VaultConfig();
|
||||
StatusConfig = new StatusConfig();
|
||||
LoggingConfig = new LoggingConfig();
|
||||
PiwikConfig = new PiwikConfig();
|
||||
IRCConfig = new IRCConfig();
|
||||
}
|
||||
|
||||
public static Config Deserialize(string text)
|
||||
@ -210,4 +216,4 @@ namespace Teknik.Configuration
|
||||
File.WriteAllText(path, configContents);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user