Buckets:
| using System; | |
| using System.Collections.Generic; | |
| using System.Data.SQLite; | |
| using System.Linq; | |
| using System.Net; | |
| using System.Net.Http; | |
| using System.Threading; | |
| using System.Threading.Tasks; | |
| using System.Text.RegularExpressions; | |
| using Newtonsoft.Json; | |
| using Microsoft.Extensions.Configuration; | |
| using Microsoft.Extensions.Logging; | |
| using BlockchainNetworkAnalyzer.Core; | |
| using static BlockchainNetworkAnalyzer.App; | |
| namespace BlockchainNetworkAnalyzer.Core | |
| { | |
| public class FakeIPDetector | |
| { | |
| private readonly ILogger<FakeIPDetector> _logger; | |
| private readonly HttpClient _httpClient; | |
| private readonly HashSet<string> _knownFakeIPRanges; | |
| private readonly SemaphoreSlim _semaphore; | |
| public FakeIPDetector() | |
| { | |
| _logger = App.LoggerFactory.CreateLogger<FakeIPDetector>(); | |
| _httpClient = new HttpClient | |
| { | |
| Timeout = TimeSpan.FromMilliseconds( | |
| int.Parse(App.Configuration["IPDetection:ValidationTimeout"] ?? "5000")) | |
| }; | |
| _semaphore = new SemaphoreSlim( | |
| int.Parse(App.Configuration["IPDetection:MaxValidationConcurrent"] ?? "10"), | |
| int.Parse(App.Configuration["IPDetection:MaxValidationConcurrent"] ?? "10")); | |
| _knownFakeIPRanges = LoadKnownFakeIPRanges(); | |
| LoadFakeIPDatabase(); | |
| } | |
| public async Task<FakeIPDetectionResult> DetectFakeIPAsync(string ipAddress) | |
| { | |
| var result = new FakeIPDetectionResult | |
| { | |
| IPAddress = ipAddress, | |
| IsFake = false, | |
| Confidence = 0.0, | |
| Reasons = new List<string>() | |
| }; | |
| try | |
| { | |
| // Check against known fake IP ranges | |
| if (_knownFakeIPRanges.Any(range => IsIPInRange(ipAddress, range))) | |
| { | |
| result.IsFake = true; | |
| result.Confidence = 0.95; | |
| result.Reasons.Add("IP is in known fake IP range database"); | |
| return result; | |
| } | |
| // Check database | |
| if (IsInFakeIPDatabase(ipAddress)) | |
| { | |
| result.IsFake = true; | |
| result.Confidence = 0.90; | |
| result.Reasons.Add("IP found in fake IP database"); | |
| return result; | |
| } | |
| // Validate using multiple services | |
| var validationTasks = new List<Task<IPValidationResponse>>(); | |
| var services = App.Configuration.GetSection("IPDetection:ValidationServices").Get<string[]>(); | |
| if (services != null && services.Length > 0) | |
| { | |
| await _semaphore.WaitAsync(); | |
| try | |
| { | |
| foreach (var service in services) | |
| { | |
| validationTasks.Add(ValidateIPWithServiceAsync(ipAddress, service)); | |
| } | |
| var responses = await Task.WhenAll(validationTasks); | |
| AnalyzeValidationResponses(result, responses); | |
| } | |
| finally | |
| { | |
| _semaphore.Release(); | |
| } | |
| } | |
| // Additional heuristics | |
| ApplyHeuristics(result, ipAddress); | |
| // Save to database if fake | |
| if (result.IsFake && result.Confidence > 0.7) | |
| { | |
| SaveToFakeIPDatabase(ipAddress, result); | |
| } | |
| } | |
| catch (Exception ex) | |
| { | |
| _logger.LogError(ex, $"Error detecting fake IP for {ipAddress}"); | |
| } | |
| return result; | |
| } | |
| private async Task<IPValidationResponse> ValidateIPWithServiceAsync(string ip, string serviceUrl) | |
| { | |
| try | |
| { | |
| var url = serviceUrl.Replace("{ip}", ip); | |
| var response = await _httpClient.GetStringAsync(url); | |
| return JsonConvert.DeserializeObject<IPValidationResponse>(response); | |
| } | |
| catch (Exception ex) | |
| { | |
| _logger.LogWarning(ex, $"Failed to validate IP {ip} with service {serviceUrl}"); | |
| return null; | |
| } | |
| } | |
| private void AnalyzeValidationResponses(FakeIPDetectionResult result, IPValidationResponse[] responses) | |
| { | |
| var validResponses = responses.Where(r => r != null).ToList(); | |
| if (validResponses.Count == 0) | |
| { | |
| result.Reasons.Add("Could not validate IP - all services failed"); | |
| result.Confidence += 0.1; | |
| return; | |
| } | |
| // Check for VPN/Proxy indicators | |
| var vpnCount = validResponses.Count(r => r.IsVPN == true || r.IsProxy == true); | |
| if (vpnCount > 0) | |
| { | |
| result.IsFake = true; | |
| result.Confidence += 0.4; | |
| result.Reasons.Add($"Detected as VPN/Proxy by {vpnCount} service(s)"); | |
| } | |
| // Check for hosting/datacenter IPs (often used by IP changing tools) | |
| var hostingCount = validResponses.Count(r => | |
| !string.IsNullOrEmpty(r.Hosting) && | |
| (r.Hosting.Contains("hosting", StringComparison.OrdinalIgnoreCase) || | |
| r.Hosting.Contains("datacenter", StringComparison.OrdinalIgnoreCase))); | |
| if (hostingCount > 0) | |
| { | |
| result.Confidence += 0.2; | |
| result.Reasons.Add("IP appears to be from hosting/datacenter (common for IP changers)"); | |
| } | |
| // Check for mismatched geolocation | |
| var locations = validResponses.Where(r => !string.IsNullOrEmpty(r.Country)).Select(r => r.Country).Distinct().ToList(); | |
| if (locations.Count > 1) | |
| { | |
| result.IsFake = true; | |
| result.Confidence += 0.3; | |
| result.Reasons.Add($"Geolocation mismatch detected across services: {string.Join(", ", locations)}"); | |
| } | |
| } | |
| private void ApplyHeuristics(FakeIPDetectionResult result, string ip) | |
| { | |
| // Check for common fake IP patterns | |
| if (IsCommonFakePattern(ip)) | |
| { | |
| result.IsFake = true; | |
| result.Confidence += 0.3; | |
| result.Reasons.Add("IP matches common fake IP pattern"); | |
| } | |
| // Check if IP is in known VPN/Proxy ranges | |
| if (IsVPNProxyRange(ip)) | |
| { | |
| result.IsFake = true; | |
| result.Confidence += 0.4; | |
| result.Reasons.Add("IP is in known VPN/Proxy range"); | |
| } | |
| } | |
| private bool IsCommonFakePattern(string ip) | |
| { | |
| // Common patterns used by fake IP tools | |
| var patterns = new[] | |
| { | |
| @"^10\.10\.10\.", // Common fake range | |
| @"^192\.0\.2\.", // TEST-NET | |
| @"^198\.51\.100\.", // TEST-NET-2 | |
| @"^203\.0\.113\.", // TEST-NET-3 | |
| }; | |
| return patterns.Any(pattern => Regex.IsMatch(ip, pattern)); | |
| } | |
| private bool IsVPNProxyRange(string ip) | |
| { | |
| // استفاده از دیتابیس جهانی رایگان (IPHub): | |
| try | |
| { | |
| // API پابلیک IPHub (rate-limited and free tier): | |
| var client = new HttpClient(); | |
| client.DefaultRequestHeaders.Add("X-Key", "free_iphub_api_key_goes_here"); | |
| var resp = client.GetAsync($"https://v2.api.iphub.info/ip/{ip}").Result; | |
| if(resp.IsSuccessStatusCode) | |
| { | |
| var json = resp.Content.ReadAsStringAsync().Result; | |
| var jobj = Newtonsoft.Json.Linq.JObject.Parse(json); | |
| int block = jobj.Value<int>("block"); | |
| // block==1 => Hosting/VPN/Proxy | |
| if(block==1) return true; | |
| } | |
| } | |
| catch(Exception ex) { | |
| _logger.LogDebug(ex, "IPHub query failed"); | |
| } | |
| return false; | |
| } | |
| private bool IsIPInRange(string ip, string range) | |
| { | |
| if (!range.Contains("/")) | |
| return ip == range; | |
| var parts = range.Split('/'); | |
| if (parts.Length != 2) | |
| return false; | |
| var networkIP = IPAddress.Parse(parts[0]); | |
| var prefixLength = int.Parse(parts[1]); | |
| var targetIP = IPAddress.Parse(ip); | |
| return IsIPInSubnet(targetIP, networkIP, prefixLength); | |
| } | |
| private bool IsIPInSubnet(IPAddress address, IPAddress subnet, int prefixLength) | |
| { | |
| var addressBytes = address.GetAddressBytes(); | |
| var subnetBytes = subnet.GetAddressBytes(); | |
| if (addressBytes.Length != subnetBytes.Length) | |
| return false; | |
| var bytes = prefixLength / 8; | |
| var bits = prefixLength % 8; | |
| for (int i = 0; i < bytes; i++) | |
| { | |
| if (addressBytes[i] != subnetBytes[i]) | |
| return false; | |
| } | |
| if (bits > 0) | |
| { | |
| var mask = (byte)(0xFF << (8 - bits)); | |
| return (addressBytes[bytes] & mask) == (subnetBytes[bytes] & mask); | |
| } | |
| return true; | |
| } | |
| private HashSet<string> LoadKnownFakeIPRanges() | |
| { | |
| var ranges = new HashSet<string> | |
| { | |
| // Common fake IP ranges used by IP changing tools | |
| "10.10.10.0/24", | |
| "192.0.2.0/24", | |
| "198.51.100.0/24", | |
| "203.0.113.0/24" | |
| }; | |
| // Load from database/file | |
| try | |
| { | |
| LoadFakeIPDatabase(); | |
| } | |
| catch (Exception ex) | |
| { | |
| _logger.LogWarning(ex, "Failed to load fake IP database"); | |
| } | |
| return ranges; | |
| } | |
| private void LoadFakeIPDatabase() | |
| { | |
| // Load from SQLite database | |
| try | |
| { | |
| using var connection = DatabaseManager.GetConnection(); | |
| connection.Open(); | |
| var sql = "SELECT IPAddress, IPRange FROM FakeIPDatabase"; | |
| using var command = new SQLiteCommand(sql, connection); | |
| using var reader = command.ExecuteReader(); | |
| while (reader.Read()) | |
| { | |
| var ip = reader["IPAddress"]?.ToString(); | |
| var range = reader["IPRange"]?.ToString(); | |
| if (!string.IsNullOrEmpty(ip)) | |
| _knownFakeIPRanges.Add(ip); | |
| if (!string.IsNullOrEmpty(range)) | |
| _knownFakeIPRanges.Add(range); | |
| } | |
| } | |
| catch (Exception ex) | |
| { | |
| _logger.LogWarning(ex, "Failed to load fake IP database"); | |
| } | |
| } | |
| private bool IsInFakeIPDatabase(string ipAddress) | |
| { | |
| try | |
| { | |
| using var connection = DatabaseManager.GetConnection(); | |
| connection.Open(); | |
| var sql = "SELECT COUNT(*) FROM FakeIPDatabase WHERE IPAddress = @IP OR IPRange LIKE @IPRange"; | |
| using var command = new SQLiteCommand(sql, connection); | |
| command.Parameters.AddWithValue("@IP", ipAddress); | |
| command.Parameters.AddWithValue("@IPRange", $"%{ipAddress}%"); | |
| var count = Convert.ToInt64(command.ExecuteScalar()); | |
| return count > 0; | |
| } | |
| catch | |
| { | |
| return false; | |
| } | |
| } | |
| private void SaveToFakeIPDatabase(string ipAddress, FakeIPDetectionResult result) | |
| { | |
| try | |
| { | |
| using var connection = DatabaseManager.GetConnection(); | |
| connection.Open(); | |
| var sql = @"INSERT OR REPLACE INTO FakeIPDatabase | |
| (IPAddress, Source, DetectionMethod, ConfidenceLevel) | |
| VALUES (@IP, 'Auto-Detection', @Method, @Confidence)"; | |
| using var command = new SQLiteCommand(sql, connection); | |
| command.Parameters.AddWithValue("@IP", ipAddress); | |
| command.Parameters.AddWithValue("@Method", string.Join("; ", result.Reasons)); | |
| command.Parameters.AddWithValue("@Confidence", result.Confidence); | |
| command.ExecuteNonQuery(); | |
| } | |
| catch (Exception ex) | |
| { | |
| _logger.LogWarning(ex, $"Failed to save fake IP to database: {ipAddress}"); | |
| } | |
| } | |
| } | |
| public class FakeIPDetectionResult | |
| { | |
| public string IPAddress { get; set; } | |
| public bool IsFake { get; set; } | |
| public double Confidence { get; set; } | |
| public List<string> Reasons { get; set; } = new List<string>(); | |
| } | |
| public class IPValidationResponse | |
| { | |
| [] | |
| public string IP { get; set; } | |
| [] | |
| public string Country { get; set; } | |
| [] | |
| public string City { get; set; } | |
| [] | |
| public string Organization { get; set; } | |
| [] | |
| public string Hosting { get; set; } | |
| [] | |
| public bool? IsVPN { get; set; } | |
| [] | |
| public bool? IsProxy { get; set; } | |
| } | |
| } | |
Xet Storage Details
- Size:
- 14 kB
- Xet hash:
- 69867eca1c636a33cb96f0f53f7875e4f9d9e76de759b3e7097581affea5fe50
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.