Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CheckProxy.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<ItemGroup>
<PackageReference Include="Spectre.Console" Version="0.45.0" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>

</Project>
192 changes: 42 additions & 150 deletions Program.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using Spectre.Console;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.CommandLine;

/// <summary>
Expand Down Expand Up @@ -53,21 +51,26 @@ public static async Task<int> Main(string[] args)
/// <param name="timeout">The timeout in milliseconds for each check.</param>
static async Task CheckSingleProxy(string proxyAddress, int timeout)
{
if (IPEndPoint.TryParse(proxyAddress, out var proxyEndPoint))
if (IPEndPoint.TryParse(proxyAddress, out _))
{
var webProxy = new WebProxy(proxyAddress);
AnsiConsole.MarkupLine("Target: [bold]" + proxyAddress + "[/]");

var columns = new List<Markup>
{
new Markup("[bold]Ping Check[/]"),
new Markup("[bold]TCP Connection[/]"),
new Markup("[bold]HTTP Proxy Check[/]"),
};
AnsiConsole.Write(new Columns(columns));

var results = await RunChecksInParallel(webProxy, proxyEndPoint, timeout);
AnsiConsole.Write(new Columns(results.Select(r => new Markup(r.ToString()))));
var checker = new ProxyChecker(webProxy);
var proxyInfo = await checker.CheckProxyAsync();

var table = new Table();
table.AddColumn("Property");
table.AddColumn("Value");

table.AddRow("Address", proxyInfo.Address ?? "N/A");
table.AddRow("Type", proxyInfo.Type ?? "N/A");
table.AddRow("Anonymity", proxyInfo.Anonymity ?? "N/A");
table.AddRow("Country", proxyInfo.Country ?? "N/A");
table.AddRow("ASN", proxyInfo.Asn ?? "N/A");
table.AddRow("Outgoing IP", proxyInfo.OutgoingIp ?? "N/A");
table.AddRow("Alive", proxyInfo.IsAlive ? "[green]Yes[/]" : "[red]No[/]");
table.AddRow("Additional Headers", proxyInfo.AdditionalHeaders ?? "N/A");

AnsiConsole.Write(table);
}
else
{
Expand All @@ -91,14 +94,14 @@ static async Task CheckProxiesFromFile(FileInfo file, int timeout)
var proxies = await File.ReadAllLinesAsync(file.FullName);
AnsiConsole.MarkupLine($"[yellow]Found {proxies.Length} proxies in {file.Name}. Starting checks...[/]");

var columns = new List<Markup>
{
new Markup("[bold]Proxy[/]"),
new Markup("[bold]Ping[/]"),
new Markup("[bold]TCP[/]"),
new Markup("[bold]HTTP[/]"),
};
AnsiConsole.Write(new Columns(columns));
var table = new Table();
table.AddColumn("Address");
table.AddColumn("Type");
table.AddColumn("Anonymity");
table.AddColumn("Country");
table.AddColumn("ASN");
table.AddColumn("Outgoing IP");
table.AddColumn("Alive");

var tasks = new List<Task>();
var semaphore = new SemaphoreSlim(10); // Limit to 10 concurrent checks
Expand All @@ -111,25 +114,25 @@ static async Task CheckProxiesFromFile(FileInfo file, int timeout)
{
try
{
if (IPEndPoint.TryParse(proxyAddress, out var proxyEndPoint))
if (IPEndPoint.TryParse(proxyAddress, out _))
{
var webProxy = new WebProxy(proxyAddress);
var results = await RunChecksInParallel(webProxy, proxyEndPoint, timeout);
AnsiConsole.Write(new Columns(
new Markup(proxyAddress),
new Markup(results[0].ToString()),
new Markup(results[1].ToString()),
new Markup(results[2].ToString())
));
var checker = new ProxyChecker(webProxy);
var proxyInfo = await checker.CheckProxyAsync();

table.AddRow(
proxyInfo.Address ?? "N/A",
proxyInfo.Type ?? "N/A",
proxyInfo.Anonymity ?? "N/A",
proxyInfo.Country ?? "N/A",
proxyInfo.Asn ?? "N/A",
proxyInfo.OutgoingIp ?? "N/A",
proxyInfo.IsAlive ? "[green]Yes[/]" : "[red]No[/]"
);
}
else
{
AnsiConsole.Write(new Columns(
new Markup(proxyAddress),
new Markup("[red]Invalid[/]"),
new Markup("[red]Invalid[/]"),
new Markup("[red]Invalid[/]")
));
table.AddRow(proxyAddress, "[red]Invalid[/]", "[red]Invalid[/]", "[red]Invalid[/]", "[red]Invalid[/]", "[red]Invalid[/]", "[red]No[/]");
}
}
finally
Expand All @@ -140,118 +143,7 @@ static async Task CheckProxiesFromFile(FileInfo file, int timeout)
}

await Task.WhenAll(tasks);
AnsiConsole.Write(table);
AnsiConsole.MarkupLine("[green]All proxy checks complete.[/]");
}

/// <summary>
/// Runs a series of checks for a given proxy in parallel.
/// </summary>
/// <param name="wp">The WebProxy object for the proxy.</param>
/// <param name="proxyEp">The IPEndPoint for the proxy.</param>
/// <param name="timeout">The timeout in milliseconds for each check.</param>
/// <returns>A boolean array indicating the result of each check.</returns>
static async Task<bool[]> RunChecksInParallel(WebProxy wp, IPEndPoint proxyEp, int timeout)
{
var pingCheckTask = PingCheckAsync(proxyEp.Address.ToString(), timeout);
var tcpConnectionTask = TcpConnectionCheckAsync(wp.Address.Host, wp.Address.Port, timeout);
var httpProxyCheckTask = HttpProxyCheckAsync(wp, timeout);

await Task.WhenAll(
pingCheckTask,
tcpConnectionTask,
httpProxyCheckTask);

return new[]
{
pingCheckTask.Result,
tcpConnectionTask.Result,
httpProxyCheckTask.Result,
};
}

/// <summary>
/// Performs an HTTP GET request through the proxy to check its functionality.
/// </summary>
/// <param name="wp">The WebProxy to use for the request.</param>
/// <param name="timeout">The timeout in milliseconds for the request.</param>
/// <returns>True if the request is successful; otherwise, false.</returns>
static async Task<bool> HttpProxyCheckAsync(WebProxy wp, int timeout)
{
var handler = new HttpClientHandler
{
Proxy = wp,
UseProxy = true,
};

using var client = new HttpClient(handler);
client.Timeout = TimeSpan.FromMilliseconds(timeout);

try
{
using var response = await client.GetAsync("http://www.google.com/generate_204");
return response.IsSuccessStatusCode;
}
catch
{
return false;
}
}

/// <summary>
/// Pings the specified address to check for reachability.
/// </summary>
/// <param name="address">The IP address or hostname to ping.</param>
/// <param name="timeout">The timeout in milliseconds for the ping.</param>
/// <returns>True if the ping is successful; otherwise, false.</returns>
static async Task<bool> PingCheckAsync(string address, int timeout)
{
using var ping = new Ping();
try
{
var reply = await ping.SendPingAsync(address, timeout);
return reply?.Status == IPStatus.Success;
}
catch (PingException)
{
return false;
}
}

/// <summary>
/// Attempts to open a TCP socket to the specified host and port.
/// </summary>
/// <param name="host">The target host.</param>
/// <param name="port">The target port.</param>
/// <param name="timeout">The timeout in milliseconds for the connection attempt.</param>
/// <returns>True if the connection is successful; otherwise, false.</returns>
static async Task<bool> TcpConnectionCheckAsync(string host, int port, int timeout)
{
using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
var connectTask = socket.ConnectAsync(host, port);
var timeoutTask = Task.Delay(TimeSpan.FromMilliseconds(timeout));

var completedTask = await Task.WhenAny(connectTask, timeoutTask);

if (completedTask == timeoutTask)
{
return false;
}

await connectTask;
return socket.Connected;
}
catch
{
return false;
}
finally
{
if (socket.Connected)
{
socket.Disconnect(false);
}
}
}
}
}
Loading
Loading