Implemented ip filtering to detect datacenter and vpn ips

This commit is contained in:
Marcel Baumgartner
2023-08-29 15:03:07 +02:00
parent 5d91077d42
commit 18b7c82613
6 changed files with 194 additions and 70 deletions

View File

@@ -304,6 +304,14 @@ public class ConfigV1
public int BlockIpDuration { get; set; } = 15;
[JsonProperty("ReCaptcha")] public ReCaptchaData ReCaptcha { get; set; } = new();
[JsonProperty("BlockDatacenterIps")]
[Description("If this option is enabled, users with an ip from datacenters will not be able to access the panel")]
public bool BlockDatacenterIps { get; set; } = true;
[JsonProperty("AllowCloudflareIps")]
[Description("Allow cloudflare ips to bypass the datacenter ip check")]
public bool AllowCloudflareIps { get; set; } = false;
}
public class ReCaptchaData

View File

@@ -15,14 +15,14 @@ public class StorageService
Directory.CreateDirectory(PathBuilder.Dir("storage", "plugins"));
await UpdateResources();
return;
if(IsEmpty(PathBuilder.Dir("storage", "resources")))
if (IsEmpty(PathBuilder.Dir("storage", "resources")))
{
Logger.Info("Default resources not found. Copying default resources");
CopyFilesRecursively(
PathBuilder.Dir("defaultstorage", "resources"),
PathBuilder.Dir("defaultstorage", "resources"),
PathBuilder.Dir("storage", "resources")
);
}
@@ -30,9 +30,9 @@ public class StorageService
if (IsEmpty(PathBuilder.Dir("storage", "configs")))
{
Logger.Info("Default configs not found. Copying default configs");
CopyFilesRecursively(
PathBuilder.Dir("defaultstorage", "configs"),
PathBuilder.Dir("defaultstorage", "configs"),
PathBuilder.Dir("storage", "configs")
);
}
@@ -40,64 +40,73 @@ public class StorageService
private async Task UpdateResources()
{
Logger.Info("Checking resources");
var client = new GitHubClient(
new ProductHeaderValue("Moonlight-Panel"));
string user = "Moonlight-Panel";
string repo = "Resources";
string branch = "main";
string resourcesDir = PathBuilder.Dir("storage", "resources");
async Task CopyDirectory(string dirPath, string localDir)
try
{
IReadOnlyList<RepositoryContent> contents;
if(string.IsNullOrEmpty(dirPath))
contents = await client.Repository.Content.GetAllContents(user, repo);
else
contents = await client.Repository.Content.GetAllContents(user, repo, dirPath);
Logger.Info("Checking resources");
foreach (var content in contents)
var client = new GitHubClient(
new ProductHeaderValue("Moonlight-Panel"));
var user = "Moonlight-Panel";
var repo = "Resources";
var resourcesDir = PathBuilder.Dir("storage", "resources");
async Task CopyDirectory(string dirPath, string localDir)
{
string localPath = Path.Combine(localDir, content.Name);
IReadOnlyList<RepositoryContent> contents;
if (content.Type == ContentType.File)
if (string.IsNullOrEmpty(dirPath))
contents = await client.Repository.Content.GetAllContents(user, repo);
else
contents = await client.Repository.Content.GetAllContents(user, repo, dirPath);
foreach (var content in contents)
{
if(content.Name.EndsWith(".gitattributes"))
continue;
if(File.Exists(localPath) && !content.Name.EndsWith(".lang"))
continue;
string localPath = Path.Combine(localDir, content.Name);
if (content.Name.EndsWith(".lang") && File.Exists(localPath) &&
new FileInfo(localPath).Length == content.Size)
if (content.Type == ContentType.File)
{
Logger.Info($"Skipped language file '{content.Name}'");
continue;
}
var fileContent = await client.Repository.Content.GetRawContent(user, repo, content.Path);
Directory.CreateDirectory(localDir); // Ensure the directory exists
await File.WriteAllBytesAsync(localPath, fileContent);
if (content.Name.EndsWith(".gitattributes"))
continue;
Logger.Debug($"Synced file '{content.Path}'");
}
else if (content.Type == ContentType.Dir)
{
await CopyDirectory(content.Path, localPath);
if (File.Exists(localPath) && !content.Name.EndsWith(".lang"))
continue;
if (content.Name.EndsWith(".lang") && File.Exists(localPath) &&
new FileInfo(localPath).Length == content.Size)
continue;
var fileContent = await client.Repository.Content.GetRawContent(user, repo, content.Path);
Directory.CreateDirectory(localDir); // Ensure the directory exists
await File.WriteAllBytesAsync(localPath, fileContent);
Logger.Debug($"Synced file '{content.Path}'");
}
else if (content.Type == ContentType.Dir)
{
await CopyDirectory(content.Path, localPath);
}
}
}
await CopyDirectory("", resourcesDir);
}
catch (RateLimitExceededException)
{
Logger.Warn("Unable to sync resources due to your ip being rate-limited by github");
}
catch (Exception e)
{
Logger.Warn("Unable to sync resources");
Logger.Warn(e);
}
await CopyDirectory("", resourcesDir);
}
private bool IsEmpty(string path)
{
return !Directory.EnumerateFileSystemEntries(path).Any();
}
private static void CopyFilesRecursively(string sourcePath, string targetPath)
{
//Now Create all of the directories
@@ -107,7 +116,7 @@ public class StorageService
}
//Copy all the files & Replaces any files with the same name
foreach (string newPath in Directory.GetFiles(sourcePath, "*.*",SearchOption.AllDirectories))
foreach (string newPath in Directory.GetFiles(sourcePath, "*.*", SearchOption.AllDirectories))
{
File.Copy(newPath, newPath.Replace(sourcePath, targetPath), true);
}

View File

@@ -0,0 +1,91 @@
using Moonlight.App.Helpers;
using Whois.NET;
namespace Moonlight.App.Services;
public class IpVerificationService
{
private readonly ConfigService ConfigService;
public IpVerificationService(ConfigService configService)
{
ConfigService = configService;
}
public async Task<bool> IsDatacenterOrVpn(string ip)
{
if (!ConfigService.Get().Moonlight.Security.BlockDatacenterIps)
return false;
if (string.IsNullOrEmpty(ip))
return false;
var datacenterNames = new List<string>()
{
"amazon",
"aws",
"microsoft",
"azure",
"google",
"google cloud",
"gcp",
"digitalocean",
"linode",
"vultr",
"ovh",
"ovhcloud",
"alibaba",
"oracle",
"ibm cloud",
"bluehost",
"godaddy",
"rackpace",
"hetzner",
"tencent",
"scaleway",
"softlayer",
"dreamhost",
"a2 hosting",
"inmotion hosting",
"red hat openstack",
"kamatera",
"hostgator",
"siteground",
"greengeeks",
"liquidweb",
"joyent",
"aruba",
"interoute",
"fastcomet",
"rosehosting",
"lunarpages",
"fatcow",
"jelastic",
"datacamp"
};
if(!ConfigService.Get().Moonlight.Security.AllowCloudflareIps)
datacenterNames.Add("cloudflare");
try
{
var response = await WhoisClient.QueryAsync(ip);
var responseText = response.Raw.ToLower();
foreach (var name in datacenterNames)
{
if (responseText.Contains(name))
{
Logger.Debug(name);
return true;
}
}
}
catch (Exception)
{
return false;
}
return false;
}
}