Skip to content

Commit

Permalink
Merge pull request #16 from ewilliams0305/development
Browse files Browse the repository at this point in the history
Added subnet and adapter scans
  • Loading branch information
ewilliams0305 authored Mar 5, 2024
2 parents 7b8c5ad + ecf82bb commit 14f3609
Show file tree
Hide file tree
Showing 24 changed files with 370 additions and 92 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
![Readme Image](../../docs/kangaroo-header.png)
![Readme Image](./docs/kangaroo-header.png)

# kangaroo Network Scanner
![GitHub](https://img.shields.io/github/license/ewilliams0305/kangaroo)
Expand Down
88 changes: 88 additions & 0 deletions source/Kangaroo.CLI/Commands/AdapterScanCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using System.Net.NetworkInformation;
using Cocona;
using Dumpify;
using Microsoft.Extensions.Logging;

namespace Kangaroo.CLI.Commands;

public sealed class AdapterScanCommand(ILogger logger, IScannerIpConfiguration config)
{

[Command("adapter", Aliases = ["a"],Description = "Scans IP address using the subnet on the provided adapter")]
public async ValueTask<int> QueryAdapter(
[Option(
shortName: 'a',
Description = "The network adapter to scan",
ValueName = "adapter")] string? adapter ,
[Option(
shortName: 't',
Description = "Query timeout in milliseconds",
ValueName = "timeout")] int? timeout)=>
adapter == null
? QueryAdapters()
: await ScanAdapter(adapter, timeout);

private int QueryAdapters()
{
var interfaces = NetworkInterface.GetAllNetworkInterfaces();

foreach (var @interface in interfaces)
{
if (@interface.OperationalStatus != OperationalStatus.Up &&
@interface.NetworkInterfaceType != NetworkInterfaceType.Loopback &&
@interface.NetworkInterfaceType != NetworkInterfaceType.Tunnel)
{
continue;
}

var ipProps = @interface.GetIPProperties();
foreach (var ip in ipProps.UnicastAddresses)
{
if (ip.Address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork)
{
continue;
}

@interface.DumpInterface(ip);
}
}
return 0;
}

public async Task<int> ScanAdapter(string adapterName, int? timeout)
{
try
{
var adapter = NetworkInterface
.GetAllNetworkInterfaces()
.FirstOrDefault(n =>
n.Name.ToLower().Replace(" ", "") ==
adapterName.ToLower().Replace(" ", ""));

if (adapter == null)
{
Console.WriteLine($"Invalid Network Adapter Specified {adapterName}");
return -1;
}
var scanner = config
.WithInterface(adapter)
.WithHttpScan(() => new HttpClient())
.WithMaxTimeout(TimeSpan.FromMilliseconds(timeout ?? 1000))
.WithMaxHops(4)
.WithParallelism(10)
.WithLogging(logger)
.Build();

var results = await scanner.QueryAddresses();
results.DumpResults();
return 0;
}
catch (InvalidSubnetException e)
{
e.Message.Dump();
}

return -1;

}
}
58 changes: 0 additions & 58 deletions source/Kangaroo.CLI/Commands/IpScanCommand.cs

This file was deleted.

48 changes: 48 additions & 0 deletions source/Kangaroo.CLI/Commands/RangeScanCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using Cocona;
using Dumpify;
using Microsoft.Extensions.Logging;

namespace Kangaroo.CLI.Commands;

public sealed class RangeScanCommand(ILogger logger, IScannerIpConfiguration config)
{
[Command("range", Description = "Scans the configured range of IP addresses")]
public async Task<int> ScanNetwork(
[Option(
shortName: 's',
Description = "Starting IP address to begin scan with",
ValueName = "start")] string start,
[Option(
shortName: 'e',
Description = "Ending IP address to stop scan at",
ValueName = "end")] string end,
[Option(
shortName: 't',
Description = "Query timeout in milliseconds",
ValueName = "timeout")] int? timeout)
{
try
{
var scanner = config

.WithRange(start, end)
.WithHttpScan(() => new HttpClient())
.WithMaxTimeout(TimeSpan.FromMilliseconds(timeout ?? 1000))
.WithMaxHops(4)
.WithParallelism(10)
.WithLogging(logger)
.Build();

var results = await scanner.QueryAddresses();
results.DumpResults();
return 0;
}
catch (InvalidIpRangeException e)
{
e.Message.Dump();
}

return -1;

}
}
49 changes: 49 additions & 0 deletions source/Kangaroo.CLI/Commands/SubnetScanCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using Cocona;
using Dumpify;
using Microsoft.Extensions.Logging;

namespace Kangaroo.CLI.Commands;

public sealed class SubnetScanCommand(ILogger logger, IScannerIpConfiguration config)
{
[Command("subnet", Description = "Scans the configured subnet, note only /16 - /24 is currently available")]
public async Task<int> ScanNetwork(
[Option(
shortName: 'i',
Description = "IP Address matching the subnet mask provided",
ValueName = "i")] string ip,
[Option(
shortName: 'm',
Description = "Subnet mask to determine IP range scope",
ValueName = "end")] string mask,
[Option(
shortName: 't',
Description = "Query timeout in milliseconds",
ValueName = "timeout")] int? timeout)
{

try
{
var scanner = config

.WithSubnet(ip, mask)
.WithHttpScan(() => new HttpClient())
.WithMaxTimeout(TimeSpan.FromMilliseconds(timeout ?? 1000))
.WithMaxHops(4)
.WithParallelism(10)
.WithLogging(logger)
.Build();

var results = await scanner.QueryAddresses();
results.DumpResults();
return 0;
}
catch (InvalidSubnetException e)
{
e.Message.Dump();
}

return -1;

}
}
2 changes: 1 addition & 1 deletion source/Kangaroo.CLI/Kangaroo.CLI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<PackAsTool>True</PackAsTool>
<ToolCommandName>kangaroo</ToolCommandName>
<PackageOutputPath>..\..\release</PackageOutputPath>
<VersionPrefix>0.0.2</VersionPrefix>
<VersionPrefix>0.0.3</VersionPrefix>
<Title>Kangaroo CLI Tool</Title>
<Description>A command line IP scanner</Description>
<Copyright></Copyright>
Expand Down
65 changes: 65 additions & 0 deletions source/Kangaroo.CLI/OutputExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using Dumpify;
using Kangaroo;

namespace Kangaroo.CLI;

public static class OutputExtensions
{
public static void DumpNode(this IEnumerable<NetworkNode> nodes)
{
var output = nodes
.Where(n => n.Alive)
.Select(n => new
{
IPAddress = n.IpAddress.ToString(),
MacAddress = n.MacAddress.ToString(),
Hostname = n.HostName,
Latency = n.Latency.ToString(),
QueryTime = n.QueryTime.ToString(),
})
.ToList();

output.Dump("NETWORK NODES LOCATED", typeNames: new TypeNamingConfig { ShowTypeNames = false });
}

public static void DumpResults(this ScanResults results)
{
var output = results.Nodes
.Where(n => n.Alive)
.Select(n => new
{
IPAddress = n.IpAddress.ToString(),
MacAddress = n.MacAddress.ToString(),
Hostname = n.HostName,
Latency = n.Latency.ToString(),
QueryTime = n.QueryTime.ToString(),
})
.ToList();

output.Dump("NETWORK NODES LOCATED", typeNames: new TypeNamingConfig { ShowTypeNames = false });
var global = new
{
Scanned = $"{results.NumberOfAliveNodes} UP / {results.NumberOfAddressesScanned}",
ElapsedTime = results.ElapsedTime.ToString(),
StartAddress = results.StartAddress.ToString(),
EndAddress = results.EndAddress.ToString()

};

global.Dump("SCANNER RESULTS", typeNames: new TypeNamingConfig { ShowTypeNames = false });
}

public static void DumpInterface(this NetworkInterface adapter, UnicastIPAddressInformation ip)
{
new
{
Adapter = adapter.Name,
Description = adapter.Description,
Address = ip.Address.ToString(),
NetMask = ip.IPv4Mask.ToString()
}.Dump("ADAPTERS", typeNames: new TypeNamingConfig { ShowTypeNames = false });
}
}
4 changes: 3 additions & 1 deletion source/Kangaroo.CLI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

var app = builder.Build();

app.AddCommands<IpScanCommand>();
app.AddCommands<RangeScanCommand>();
app.AddCommands<AdapterScanCommand>();
app.AddCommands<SubnetScanCommand>();

app.Run();
12 changes: 10 additions & 2 deletions source/Kangaroo.CLI/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
{
"profiles": {
"Kangaroo.CLI": {
"WSL": {
"commandName": "WSL2",
"distributionName": ""
},
"Kangaroo Range": {
"commandName": "Project",
"commandLineArgs": "scan -s 10.0.0.1 -e 10.0.1.254 -t 50"
"commandLineArgs": "scan -s 172.26.6.100 -e 172.26.6.200 -t 50"
},
"Kangaroo Adapter": {
"commandName": "Project",
"commandLineArgs": "adapter -a Wi-Fi"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ namespace Kangaroo;
public sealed class InvalidIpRangeException : Exception
{
public InvalidIpRangeException(IPAddress start, IPAddress end)
: base($"{start} - {end}") { }
: base($"Invalid IP address range {start} - {end}") { }
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ namespace Kangaroo;
public sealed class InvalidNetworkAdapterException : Exception
{
public InvalidNetworkAdapterException(NetworkInterface @interface)
: base($"Invalid {@interface.Name}") { }
: base($"Invalid network interface {@interface.Name}") { }
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ namespace Kangaroo;
public sealed class InvalidSubnetException : Exception
{
public InvalidSubnetException(IPAddress address, IPAddress subnet)
: base($"{address}/{subnet}") { }
: base($"Invalid IP address subnet {address}/{subnet}") { }
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
public sealed class InvalidTimeoutException : ArgumentOutOfRangeException
{
public InvalidTimeoutException(TimeSpan timeout)
: base($"{timeout} is out of range") { }
: base($"Invalid {timeout} is out of range") { }
}
Loading

0 comments on commit 14f3609

Please sign in to comment.