Implemented ip filtering to detect datacenter and vpn ips
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
91
Moonlight/App/Services/IpVerificationService.cs
Normal file
91
Moonlight/App/Services/IpVerificationService.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user