Buckets:

immErfanrajabee/bd / Core /NetworkScanner.cs
imerfanrajabee's picture
download
raw
16.6 kB
using System;
using System.Collections.Generic;
using System.Data.SQLite;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using BlockchainNetworkAnalyzer.Core.Models;
using static BlockchainNetworkAnalyzer.App;
namespace BlockchainNetworkAnalyzer.Core
{
public class NetworkScanner
{
private readonly ILogger<NetworkScanner> _logger;
private readonly SemaphoreSlim _semaphore;
private readonly CancellationTokenSource _cancellationTokenSource;
private readonly FakeIPDetector _fakeIPDetector;
private readonly BlockchainAnalyzer _blockchainAnalyzer;
public event EventHandler<ScanProgressEventArgs> ScanProgress;
public event EventHandler<IPResult> IPResultFound;
public NetworkScanner()
{
_logger = App.LoggerFactory.CreateLogger<NetworkScanner>();
var maxConcurrent = int.Parse(App.Configuration["NetworkScanning:MaxConcurrentScans"] ?? "50");
_semaphore = new SemaphoreSlim(maxConcurrent, maxConcurrent);
_cancellationTokenSource = new CancellationTokenSource();
_fakeIPDetector = new FakeIPDetector();
_blockchainAnalyzer = new BlockchainAnalyzer();
}
public async Task<ScanResult> ScanAsync(ScanConfiguration config)
{
var scanResult = new ScanResult
{
ScanType = config.ScanName ?? "Network Scan",
StartTime = DateTime.Now,
Status = "Running"
};
try
{
DatabaseManager.LogAudit("Scan Started", details: $"Scan: {scanResult.ScanType}");
// Generate IPs based on selection mode
var ipManager = new IPManager();
var ipsToScan = ipManager.GenerateIPs(config);
scanResult.TotalIPs = ipsToScan.Count;
// Get ports to scan
var portsToScan = config.Ports.Any()
? config.Ports
: GetDefaultBlockchainPorts();
// Save scan to database
var scanId = await SaveScanResultAsync(scanResult);
// Scan each IP
var tasks = new List<Task>();
int scannedCount = 0;
object lockObject = new object();
foreach (var ip in ipsToScan)
{
if (_cancellationTokenSource.Token.IsCancellationRequested)
break;
await _semaphore.WaitAsync(_cancellationTokenSource.Token);
tasks.Add(Task.Run(async () =>
{
try
{
var hasOpenPort = await ScanIPAsync(ip, portsToScan, config, scanId);
lock (lockObject)
{
scannedCount++;
scanResult.ScannedIPs = scannedCount;
if (hasOpenPort)
{
scanResult.FoundHosts++;
}
OnScanProgress(new ScanProgressEventArgs
{
Scanned = scannedCount,
Total = scanResult.TotalIPs,
Percentage = (scannedCount * 100.0) / scanResult.TotalIPs
});
}
}
finally
{
_semaphore.Release();
}
}, _cancellationTokenSource.Token));
}
await Task.WhenAll(tasks);
scanResult.EndTime = DateTime.Now;
scanResult.Status = "Completed";
// Update scan result
await UpdateScanResultAsync(scanId, scanResult);
DatabaseManager.LogAudit("Scan Completed", details: $"Scan: {scanResult.ScanType}, Found: {scanResult.FoundHosts}");
}
catch (Exception ex)
{
_logger.LogError(ex, "Error during network scan");
scanResult.Status = "Error";
scanResult.EndTime = DateTime.Now;
throw;
}
return scanResult;
}
private async Task<bool> ScanIPAsync(string ipAddress, List<int> ports, ScanConfiguration config, long scanId)
{
try
{
// Basic connectivity check
using var ping = new Ping();
var reply = await ping.SendPingAsync(ipAddress, config.Timeout);
if (reply?.Status != IPStatus.Success)
{
return false; // IP is not reachable
}
bool hasOpenPort = false;
var ipResult = new IPResult
{
ScanResultId = scanId,
IPAddress = ipAddress,
ResponseTime = (int)reply.RoundtripTime
};
// Fake IP detection
if (config.EnableFakeIPDetection)
{
var fakeDetection = await _fakeIPDetector.DetectFakeIPAsync(ipAddress);
ipResult.IsFakeIP = fakeDetection.IsFake;
ipResult.FakeIPReason = string.Join("; ", fakeDetection.Reasons);
}
// Port scanning
if (config.EnablePortScanning)
{
foreach (var port in ports)
{
var portResult = await ScanPortAsync(ipAddress, port, config.Timeout);
if (portResult.IsOpen)
{
hasOpenPort = true;
ipResult.Port = port;
ipResult.PortStatus = "Open";
// Service detection
ipResult.Service = DetectService(port, portResult.Banner);
ipResult.Protocol = DetectProtocol(port);
break; // Found at least one open port
}
}
}
// Blockchain detection
if (config.EnableBlockchainDetection && ipResult.Port.HasValue)
{
var blockchainResult = await _blockchainAnalyzer.AnalyzeBlockchainAsync(
ipAddress, ipResult.Port.Value, config.Timeout);
if (blockchainResult.IsBlockchain)
{
ipResult.BlockchainDetected = true;
ipResult.BlockchainType = blockchainResult.Type;
}
}
// Only save result if we found something or if fake IP was detected
if (hasOpenPort || ipResult.IsFakeIP || ipResult.BlockchainDetected)
{
await SaveIPResultAsync(ipResult);
OnIPResultFound(ipResult);
}
return hasOpenPort;
}
catch (Exception ex)
{
_logger.LogWarning(ex, $"Error scanning IP {ipAddress}");
return false;
}
}
private async Task<PortScanResult> ScanPortAsync(string ipAddress, int port, int timeout)
{
var result = new PortScanResult { Port = port };
try
{
using var client = new TcpClient();
var connectTask = client.ConnectAsync(ipAddress, port);
var timeoutTask = Task.Delay(timeout);
var completedTask = await Task.WhenAny(connectTask, timeoutTask);
if (completedTask == connectTask && client.Connected)
{
result.IsOpen = true;
// Try to get banner
try
{
using var stream = client.GetStream();
stream.ReadTimeout = 2000;
var buffer = new byte[1024];
var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
if (bytesRead > 0)
{
result.Banner = System.Text.Encoding.UTF8.GetString(buffer, 0, bytesRead);
}
}
catch
{
// Ignore banner read errors
}
client.Close();
}
}
catch
{
result.IsOpen = false;
}
return result;
}
private string DetectService(int port, string banner)
{
// Service detection based on port and banner
var serviceMap = new Dictionary<int, string>
{
{ 8332, "Bitcoin RPC" },
{ 8333, "Bitcoin P2P" },
{ 8545, "Ethereum JSON-RPC" },
{ 30303, "Ethereum P2P" },
{ 4444, "Stratum" },
{ 3333, "Stratum" },
{ 4028, "Stratum" },
{ 7777, "Stratum" },
{ 9332, "Litecoin RPC" },
{ 9333, "Litecoin P2P" },
{ 14444, "Stratum SSL" },
{ 14433, "Stratum" }
};
if (serviceMap.ContainsKey(port))
return serviceMap[port];
// Try to detect from banner
if (!string.IsNullOrEmpty(banner))
{
banner = banner.ToLowerInvariant();
if (banner.Contains("stratum"))
return "Stratum Mining";
if (banner.Contains("bitcoin"))
return "Bitcoin";
if (banner.Contains("ethereum") || banner.Contains("eth"))
return "Ethereum";
}
return "Unknown";
}
private string DetectProtocol(int port)
{
var protocolMap = new Dictionary<int, string>
{
{ 8332, "Bitcoin RPC" },
{ 8333, "Bitcoin P2P" },
{ 8545, "Ethereum JSON-RPC" },
{ 30303, "Ethereum P2P" },
{ 4444, "Stratum" },
{ 3333, "Stratum" },
{ 4028, "Stratum" }
};
return protocolMap.ContainsKey(port) ? protocolMap[port] : "TCP";
}
private List<int> GetDefaultBlockchainPorts()
{
var ports = App.Configuration.GetSection("Blockchain:DefaultPorts").Get<int[]>();
return ports?.ToList() ?? new List<int> { 8332, 8333, 8545, 4444, 3333 };
}
private async Task<long> SaveScanResultAsync(ScanResult scanResult)
{
return await Task.Run(() =>
{
using var connection = DatabaseManager.GetConnection();
connection.Open();
var sql = @"INSERT INTO ScanResults
(ScanType, StartTime, Status, TotalIPs, ScannedIPs, FoundHosts, Configuration)
VALUES (@Type, @Start, @Status, @Total, @Scanned, @Found, @Config);
SELECT last_insert_rowid();";
using var command = new SQLiteCommand(sql, connection);
command.Parameters.AddWithValue("@Type", scanResult.ScanType);
command.Parameters.AddWithValue("@Start", scanResult.StartTime);
command.Parameters.AddWithValue("@Status", scanResult.Status);
command.Parameters.AddWithValue("@Total", scanResult.TotalIPs);
command.Parameters.AddWithValue("@Scanned", scanResult.ScannedIPs);
command.Parameters.AddWithValue("@Found", scanResult.FoundHosts);
command.Parameters.AddWithValue("@Config", scanResult.Configuration ?? "");
return Convert.ToInt64(command.ExecuteScalar());
});
}
private async Task UpdateScanResultAsync(long scanId, ScanResult scanResult)
{
await Task.Run(() =>
{
using var connection = DatabaseManager.GetConnection();
connection.Open();
var sql = @"UPDATE ScanResults
SET EndTime = @End, Status = @Status, ScannedIPs = @Scanned, FoundHosts = @Found
WHERE Id = @Id";
using var command = new SQLiteCommand(sql, connection);
command.Parameters.AddWithValue("@End", scanResult.EndTime);
command.Parameters.AddWithValue("@Status", scanResult.Status);
command.Parameters.AddWithValue("@Scanned", scanResult.ScannedIPs);
command.Parameters.AddWithValue("@Found", scanResult.FoundHosts);
command.Parameters.AddWithValue("@Id", scanId);
command.ExecuteNonQuery();
});
}
private async Task SaveIPResultAsync(IPResult ipResult)
{
await Task.Run(() =>
{
using var connection = DatabaseManager.GetConnection();
connection.Open();
var sql = @"INSERT INTO IPResults
(ScanResultId, IPAddress, Port, PortStatus, Service, Protocol, ResponseTime,
IsFakeIP, FakeIPReason, BlockchainDetected, BlockchainType, Geolocation, ISP, ASN)
VALUES (@ScanId, @IP, @Port, @PortStatus, @Service, @Protocol, @ResponseTime,
@IsFake, @FakeReason, @Blockchain, @BlockchainType, @Geo, @ISP, @ASN)";
using var command = new SQLiteCommand(sql, connection);
command.Parameters.AddWithValue("@ScanId", ipResult.ScanResultId);
command.Parameters.AddWithValue("@IP", ipResult.IPAddress);
command.Parameters.AddWithValue("@Port", (object)ipResult.Port ?? DBNull.Value);
command.Parameters.AddWithValue("@PortStatus", ipResult.PortStatus ?? "");
command.Parameters.AddWithValue("@Service", ipResult.Service ?? "");
command.Parameters.AddWithValue("@Protocol", ipResult.Protocol ?? "");
command.Parameters.AddWithValue("@ResponseTime", (object)ipResult.ResponseTime ?? DBNull.Value);
command.Parameters.AddWithValue("@IsFake", ipResult.IsFakeIP ? 1 : 0);
command.Parameters.AddWithValue("@FakeReason", ipResult.FakeIPReason ?? "");
command.Parameters.AddWithValue("@Blockchain", ipResult.BlockchainDetected ? 1 : 0);
command.Parameters.AddWithValue("@BlockchainType", ipResult.BlockchainType ?? "");
command.Parameters.AddWithValue("@Geo", ipResult.Geolocation ?? "");
command.Parameters.AddWithValue("@ISP", ipResult.ISP ?? "");
command.Parameters.AddWithValue("@ASN", ipResult.ASN ?? "");
command.ExecuteNonQuery();
});
}
public void Cancel()
{
_cancellationTokenSource.Cancel();
}
protected virtual void OnScanProgress(ScanProgressEventArgs e)
{
ScanProgress?.Invoke(this, e);
}
protected virtual void OnIPResultFound(IPResult e)
{
IPResultFound?.Invoke(this, e);
}
}
public class ScanProgressEventArgs : EventArgs
{
public int Scanned { get; set; }
public int Total { get; set; }
public double Percentage { get; set; }
}
public class PortScanResult
{
public int Port { get; set; }
public bool IsOpen { get; set; }
public string Banner { get; set; }
}
}

Xet Storage Details

Size:
16.6 kB
·
Xet hash:
240aa24e2724785b85734dc3de93be6138ccf8026344fc18c3d6f90c9f8fc151

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.