Browse Source

Add project files.

master
Adam Pippin 3 years ago
parent
commit
538bf052a8
  1. 17
      KnockKnock.CLI/KnockKnock.CLI.csproj
  2. 40
      KnockKnock.CLI/Program.cs
  3. 85
      KnockKnock.Lib/Connection.cs
  4. 78
      KnockKnock.Lib/ConnectionPool.cs
  5. 7
      KnockKnock.Lib/KnockKnock.Lib.csproj
  6. 47
      KnockKnock.Lib/Listener.cs
  7. 34
      KnockKnock.Lib/Manager.cs
  8. 72
      KnockKnock.Lib/Proxy.cs
  9. 30
      KnockKnock.Lib/Upstream.cs
  10. 20
      KnockKnock.Service/KnockKnock.Service.csproj
  11. 11
      KnockKnock.Service/Program.cs
  12. 11
      KnockKnock.Service/Properties/launchSettings.json
  13. 67
      KnockKnock.Service/Worker.cs
  14. 8
      KnockKnock.Service/appsettings.Development.json
  15. 8
      KnockKnock.Service/appsettings.json
  16. 1
      KnockKnock.Service/service-install.bat
  17. 2
      KnockKnock.Service/service-uninstall.bat
  18. 37
      KnockKnock.sln

17
KnockKnock.CLI/KnockKnock.CLI.csproj

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.PowerShell.SDK" Version="7.1.4" />
<PackageReference Include="System.Management.Automation" Version="7.1.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\KnockKnock.Lib\KnockKnock.Lib.csproj" />
</ItemGroup>
</Project>

40
KnockKnock.CLI/Program.cs

@ -0,0 +1,40 @@
using System;
using System.Net;
using System.Management.Automation;
namespace KnockKnock.CLI
{
internal class Program
{
static void Main(string[] args)
{
Lib.Manager m = new Lib.Manager();
Lib.Proxy p = new Lib.Proxy(new IPEndPoint(IPAddress.Any, 1234), new IPEndPoint(IPAddress.Parse("10.200.0.10"), 3389));
p.Idle += P_Idle;
p.Active += P_Active;
m.AddProxy(p);
//m.AddProxy(new IPEndPoint(IPAddress.Any, 1234), new IPEndPoint(IPAddress.Parse("172.217.14.195"), 80));
P_Active(p);
Console.WriteLine("Running");
Console.ReadLine();
m.Close();
Console.WriteLine("Good night!");
}
private static void P_Active(Lib.Proxy sender)
{
Console.WriteLine("Active!");
PowerShell ps = PowerShell.Create();
ps.AddScript("Resume-VM Debian");
foreach (PSObject result in ps.Invoke())
{
Console.WriteLine(result);
}
}
private static void P_Idle(Lib.Proxy sender)
{
Console.WriteLine("Idle");
}
}
}

85
KnockKnock.Lib/Connection.cs

@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace KnockKnock.Lib
{
internal class Connection
{
public delegate void SocketReceivedEvent(Connection sender, byte[] data);
public delegate void SocketEvent(Connection sender);
public SocketReceivedEvent Received;
public SocketEvent Closed;
const int BUFFER_SIZE = 1024;
Socket socket;
byte[] buffer = new byte[BUFFER_SIZE];
public Connection(Socket socket)
{
this.socket = socket;
}
public void Open()
{
this.socket.BeginReceive(this.buffer, 0, BUFFER_SIZE, SocketFlags.None, this.SocketReceive, null);
}
public void Close()
{
this.socket.Close();
}
public void Send(byte[] data)
{
try
{
this.socket.Send(data);
}
catch
{
this.Closed(this);
}
}
protected void SocketReceive(IAsyncResult result)
{
int read;
try
{
read = socket.EndReceive(result);
}
catch
{
Closed(this);
return;
}
if (read == 0)
{
// Connection closed
Closed(this);
}
else
{
byte[] received = new byte[read];
Array.Copy(this.buffer, 0, received, 0, read);
Received(this, received);
try
{
socket.BeginReceive(this.buffer, 0, BUFFER_SIZE, SocketFlags.None, this.SocketReceive, null);
}
catch
{
Closed(this);
}
}
}
}
}

78
KnockKnock.Lib/ConnectionPool.cs

@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace KnockKnock.Lib
{
internal class ConnectionPool
{
public delegate void PoolEvent(ConnectionPool sender);
public event PoolEvent Closed;
List<Connection> connections;
public ConnectionPool()
{
connections = new List<Connection>();
}
public void Open()
{
foreach (Connection c in this.connections)
{
c.Open();
}
}
public void AddConnection(Connection c)
{
this.connections.Add(c);
c.Received += Connection_Receive;
c.Closed += Connection_Closed;
}
public void RemoveConnection(Connection c)
{
this.connections.Remove(c);
c.Received -= Connection_Receive;
c.Closed -= Connection_Closed;
}
public void Close()
{
foreach (Connection c in this.connections)
{
c.Close();
}
}
protected void Connection_Receive(Connection sender, byte[] data)
{
System.Diagnostics.Debug.WriteLine("Receive " + data.Length + " bytes");
foreach (Connection c in this.connections)
{
if (c != sender)
{
System.Diagnostics.Debug.WriteLine("Send " + data.Length + " bytes");
c.Send(data);
}
}
}
protected void Connection_Closed(Connection sender)
{
System.Diagnostics.Debug.WriteLine("Closed");
foreach (Connection c in this.connections)
{
if (c != sender)
{
c.Close();
}
}
Closed(this);
}
}
}

7
KnockKnock.Lib/KnockKnock.Lib.csproj

@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
</Project>

47
KnockKnock.Lib/Listener.cs

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace KnockKnock.Lib
{
internal class Listener
{
public delegate void ConnectedEvent(Listener sender, Socket socket);
public event ConnectedEvent Connected;
int port;
Socket listener;
public Listener(int port)
{
this.port = port;
}
public void Start()
{
listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(new IPEndPoint(IPAddress.Loopback, this.port));
listener.Listen();
listener.BeginAccept(this.ListenerAcceptCallback, null);
}
public void Stop()
{
listener.Close();
listener = null;
}
protected void ListenerAcceptCallback(IAsyncResult result)
{
if (listener == null) return;
Socket client = listener.EndAccept(result);
listener.BeginAccept(this.ListenerAcceptCallback, null);
this.Connected(this, client);
}
}
}

34
KnockKnock.Lib/Manager.cs

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace KnockKnock.Lib
{
public class Manager
{
List<Proxy> proxies;
public Manager()
{
proxies = new List<Proxy>();
}
public void AddProxy(Proxy p)
{
proxies.Add(p);
p.Start();
}
public void Close()
{
foreach (Proxy p in this.proxies)
{
p.Stop();
}
}
}
}

72
KnockKnock.Lib/Proxy.cs

@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace KnockKnock.Lib
{
public class Proxy
{
public delegate void ProxyEvent(Proxy sender);
public event ProxyEvent Active;
public event ProxyEvent Idle;
Listener listener;
Upstream upstream;
List<ConnectionPool> connections;
public Proxy(IPEndPoint listener, IPEndPoint upstream)
{
this.listener = new Listener(listener.Port);
this.upstream = new Upstream(upstream.Address, upstream.Port);
this.connections = new List<ConnectionPool>();
}
public void Start()
{
this.listener.Connected += Listener_Connected;
this.listener.Start();
}
public void Stop()
{
foreach (ConnectionPool p in connections)
{
p.Close();
}
connections.Clear();
}
private void Listener_Connected(Listener sender, Socket client_socket)
{
if (this.connections.Count == 0 && this.Active != null)
{
this.Active(this);
}
Socket upstream_socket = this.upstream.Connect();
Connection client_conn = new Connection(client_socket);
Connection upstream_conn = new Connection(upstream_socket);
ConnectionPool cp = new ConnectionPool();
cp.AddConnection(client_conn);
cp.AddConnection(upstream_conn);
cp.Closed += Connection_Closed;
cp.Open();
}
private void Connection_Closed(ConnectionPool sender)
{
connections.Remove(sender);
if (connections.Count == 0 && this.Idle != null)
{
this.Idle(this);
}
}
}
}

30
KnockKnock.Lib/Upstream.cs

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace KnockKnock.Lib
{
internal class Upstream
{
IPAddress ip;
int port;
public Upstream(IPAddress ip, int port)
{
this.ip = ip;
this.port = port;
}
public Socket Connect()
{
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
s.Connect(this.ip, this.port);
return s;
}
}
}

20
KnockKnock.Service/KnockKnock.Service.csproj

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk.Worker">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>dotnet-KnockKnock.Service-7A5DE5F7-7176-47CB-A545-C289BBFCF99D</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0-rc.1.21451.13" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
<PackageReference Include="Microsoft.PowerShell.SDK" Version="7.1.4" />
<PackageReference Include="System.Management.Automation" Version="7.1.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\KnockKnock.Lib\KnockKnock.Lib.csproj" />
</ItemGroup>
</Project>

11
KnockKnock.Service/Program.cs

@ -0,0 +1,11 @@
using KnockKnock.Service;
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<Worker>();
})
.UseWindowsService()
.Build();
await host.RunAsync();

11
KnockKnock.Service/Properties/launchSettings.json

@ -0,0 +1,11 @@
{
"profiles": {
"KnockKnock.Service": {
"commandName": "Project",
"dotnetRunMessages": true,
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Development"
}
}
}
}

67
KnockKnock.Service/Worker.cs

@ -0,0 +1,67 @@
namespace KnockKnock.Service;
using System.Net;
using System.Management.Automation;
using System.Timers;
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
public Worker(ILogger<Worker> logger)
{
_logger = logger;
}
Lib.Manager manager;
Timer idleTimer;
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Starting KnockKnock");
manager = new Lib.Manager();
_logger.LogInformation("Creating proxy for :1234 -> 10.200.0.10:3389");
Lib.Proxy p = new Lib.Proxy(new IPEndPoint(IPAddress.Any, 1234), new IPEndPoint(IPAddress.Parse("10.200.0.10"), 3389));
p.Active += Proxy_Active;
p.Idle += Proxy_Idle;
_logger.LogInformation("Instantiating Idle Timer");
idleTimer = new Timer(10000);
idleTimer.Elapsed += IdleTimer_Elapsed;
_logger.LogInformation("Starting");
manager.AddProxy(p);
while (!stoppingToken.IsCancellationRequested)
{
await Task.Delay(1000, stoppingToken);
}
manager.Close();
}
private void IdleTimer_Elapsed(object? sender, ElapsedEventArgs e)
{
idleTimer.Stop();
_logger.LogDebug("Suspending VM");
PowerShell ps = PowerShell.Create();
ps.AddScript("Suspend-VM Debian");
ps.Invoke();
}
private void Proxy_Idle(Lib.Proxy sender)
{
_logger.LogDebug("Idle -- starting idle timer");
idleTimer.Start();
}
private void Proxy_Active(Lib.Proxy sender)
{
idleTimer.Stop();
_logger.LogDebug("Resuming VM");
PowerShell ps = PowerShell.Create();
ps.AddScript("Resume-VM Debian");
ps.Invoke();
}
}

8
KnockKnock.Service/appsettings.Development.json

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}

8
KnockKnock.Service/appsettings.json

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}

1
KnockKnock.Service/service-install.bat

@ -0,0 +1 @@
sc create "KnockKnock" start=auto binpath="%~d0%~p0\bin\Release\net6.0\KnockKnock.Service.exe"

2
KnockKnock.Service/service-uninstall.bat

@ -0,0 +1,2 @@
sc stop "KnockKnock"
sc delete "KnockKnock"

37
KnockKnock.sln

@ -0,0 +1,37 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31717.71
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KnockKnock.Lib", "KnockKnock.Lib\KnockKnock.Lib.csproj", "{AE473668-717A-422D-A319-E1F88859EF6B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KnockKnock.CLI", "KnockKnock.CLI\KnockKnock.CLI.csproj", "{1AB960B3-F48A-4787-A031-3D938595A2E0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KnockKnock.Service", "KnockKnock.Service\KnockKnock.Service.csproj", "{B82D18F9-BEF8-461F-898B-EE81F486C20D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AE473668-717A-422D-A319-E1F88859EF6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AE473668-717A-422D-A319-E1F88859EF6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AE473668-717A-422D-A319-E1F88859EF6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AE473668-717A-422D-A319-E1F88859EF6B}.Release|Any CPU.Build.0 = Release|Any CPU
{1AB960B3-F48A-4787-A031-3D938595A2E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1AB960B3-F48A-4787-A031-3D938595A2E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1AB960B3-F48A-4787-A031-3D938595A2E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1AB960B3-F48A-4787-A031-3D938595A2E0}.Release|Any CPU.Build.0 = Release|Any CPU
{B82D18F9-BEF8-461F-898B-EE81F486C20D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B82D18F9-BEF8-461F-898B-EE81F486C20D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B82D18F9-BEF8-461F-898B-EE81F486C20D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B82D18F9-BEF8-461F-898B-EE81F486C20D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {98F24DFD-A873-4227-B0EF-6CCD67208132}
EndGlobalSection
EndGlobal
Loading…
Cancel
Save