add unix socket proxy to http

This commit is contained in:
seroquel 2021-10-21 19:29:07 -07:00
parent 0be549b2de
commit 38eccc69d8
36 changed files with 161 additions and 62 deletions

@ -1,3 +1,4 @@
using System.Linq;
using cloud.insecurity.docker; using cloud.insecurity.docker;
using cloud.insecurity.http; using cloud.insecurity.http;
@ -5,44 +6,47 @@ namespace cloud.insecurity.docker.ipam
{ {
public static class HttpHandler public static class HttpHandler
{ {
private static Scope[] RootScopes;
[HttpRequestHandler(IHttpRequest.RequestMethod.Post, "/Plugin.Activate")] [HttpRequestHandler(IHttpRequest.RequestMethod.Post, "/Plugin.Activate")]
public static void Activate() public static IHttpResponse Activate(HttpRequest request)
{ {
throw new System.NotImplementedException(); RootScopes = Scope.GetParentScopes().ToArray();
return new HttpResponse(request).Ok();
} }
[HttpRequestHandler(IHttpRequest.RequestMethod.Post, "/IpamDriver.GetCapabilities")] [HttpRequestHandler(IHttpRequest.RequestMethod.Post, "/IpamDriver.GetCapabilities")]
public static void GetCapabilities() public static IHttpResponse GetCapabilities(HttpRequest request)
{ {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }
[HttpRequestHandler(IHttpRequest.RequestMethod.Post, "/IpamDriver.GetDefaultAddressSpaces")] [HttpRequestHandler(IHttpRequest.RequestMethod.Post, "/IpamDriver.GetDefaultAddressSpaces")]
public static void GetDefaultAddressSpaces() public static IHttpResponse GetDefaultAddressSpaces(HttpRequest request)
{ {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }
[HttpRequestHandler(IHttpRequest.RequestMethod.Post, "/IpamDriver.RequestPool")] [HttpRequestHandler(IHttpRequest.RequestMethod.Post, "/IpamDriver.RequestPool")]
public static void RequestPool() public static IHttpResponse RequestPool(HttpRequest request)
{ {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }
[HttpRequestHandler(IHttpRequest.RequestMethod.Post, "/IpamDriver.ReleasePool")] [HttpRequestHandler(IHttpRequest.RequestMethod.Post, "/IpamDriver.ReleasePool")]
public static void ReleasePool() public static IHttpResponse ReleasePool(HttpRequest request)
{ {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }
[HttpRequestHandler(IHttpRequest.RequestMethod.Post, "/IpamDriver.RequestAddress")] [HttpRequestHandler(IHttpRequest.RequestMethod.Post, "/IpamDriver.RequestAddress")]
public static void RequestAddress() public static IHttpResponse RequestAddress(HttpRequest request)
{ {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }
[HttpRequestHandler(IHttpRequest.RequestMethod.Post, "/IpamDriver.ReleaseAddress")] [HttpRequestHandler(IHttpRequest.RequestMethod.Post, "/IpamDriver.ReleaseAddress")]
public static void ReleaseAddress() public static IHttpResponse ReleaseAddress(HttpRequest request)
{ {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }

@ -1,9 +1,16 @@
using System; using System;
using System.Collections.Generic;
using System.IO.Pipes;
using System.Linq; using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using cloud.insecurity.http; using cloud.insecurity.http;
using log4net; using log4net;
namespace cloud.insecurity.docker.ipam namespace cloud.insecurity.docker.ipam
{ {
internal class Ipam internal class Ipam
@ -17,28 +24,95 @@ namespace cloud.insecurity.docker.ipam
} }
internal static void Main(string[] args) internal static void Main(string[] args)
{ {
Task<Task> UnixSocketProxy;
log4net.Config.XmlConfigurator.Configure(); log4net.Config.XmlConfigurator.Configure();
Task server = HttpServer.Server.Start(new string[]
var tasks = new Task<Task>[]
{ {
"http://127.0.0.1:8000/", HttpServer.Server.Start(new string[]
}); {
@"http://127.0.0.1:65467/",
Scope.GetParentScopes().ToList().ForEach(f => Console.WriteLine( }),
string.Format("{0}", f.ToString()))); ProxyRequestsFromUnixSocket()
};
Console.CancelKeyPress += (sender, eventArgs) => Console.CancelKeyPress += (sender, eventArgs) =>
{ {
Console.WriteLine("shutting down"); Console.WriteLine("shutting down, waiting for unfinished tasks..");
HttpServer.Server.Stop(); HttpServer.Server.Stop();
server.Wait();
tasks.ToList().ForEach(t => t.Wait());
Environment.Exit(0); Environment.Exit(0);
}; };
ReadKey: cKey:
switch (Console.ReadKey().Key) switch (Console.ReadKey())
{ {
default: default:
goto ReadKey; goto cKey;
}
}
private static async Task<Task> ProxyRequestsFromUnixSocket()
{
var listeningPort = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.IP);
var endPoint = new UnixDomainSocketEndPoint(@"/run/cloud.insecurity.docker/ipam.sock");
listeningPort.Bind(endPoint);
listeningPort.Listen(0);
ManualResetEvent AcceptFinished = new ManualResetEvent(false);
while (HttpServer.Server.Running)
{
listeningPort.BeginAccept(ConnectionAccepted,
new Tuple<Socket, ManualResetEvent>(listeningPort, AcceptFinished));
AcceptFinished.WaitOne();
}
return Task.CompletedTask;
}
private static void ConnectionAccepted(IAsyncResult ar)
{
ManualResetEvent ReceiveFinished = new ManualResetEvent(false);
var socket = (ar.AsyncState as Tuple<Socket, ManualResetEvent>)?.Item1;
var finished = (ar.AsyncState as Tuple<Socket, ManualResetEvent>)?.Item2;
var ProxySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
ProxySocket.Connect(new IPEndPoint(0x7f000001, 0xffbb));
var buffer = new List<ArraySegment<byte>>();
bool ReceivedFromClient = false;
recv:
while (!Encoding.UTF8.GetString(buffer.SelectMany(bytes => bytes)
.ToArray())
.EndsWith("\r\n\r\n"))
{
(ReceivedFromClient ? ProxySocket : socket)?.BeginReceive(buffer,
SocketFlags.None, result =>
{
(result.AsyncState as ManualResetEvent)?.Set();
}, ReceiveFinished);
ReceiveFinished.WaitOne();
}
if (ReceivedFromClient)
{
socket?.Send(buffer);
finished?.Set();
}
else
{
ProxySocket.Send(buffer);
buffer = new List<ArraySegment<byte>>();
ReceivedFromClient = true;
goto recv;
} }
} }
} }

@ -29,6 +29,8 @@ namespace cloud.insecurity.docker.ipam
public int PrefixLen { get; set; } public int PrefixLen { get; set; }
public List<string>? Tags { get; set; } public List<string>? Tags { get; set; }
public int? TcpIpVersion { get; set; } public int? TcpIpVersion { get; set; }
public bool Allocated { get; set; }
private static LiteDatabase Db = new LiteDatabase(@"IPAM.db"); private static LiteDatabase Db = new LiteDatabase(@"IPAM.db");
private static log4net.ILog Log private static log4net.ILog Log
@ -92,12 +94,7 @@ namespace cloud.insecurity.docker.ipam
{ {
} }
public override bool Equals(object? obj)
{
return (GetHashCode() == obj.GetHashCode());
}
public static IPNetwork GetNetworkObject(string network, int prefixLen) public static IPNetwork GetNetworkObject(string network, int prefixLen)
{ {
return IPNetwork.Parse(string.Format("{0}/{1}", network, prefixLen.ToString())); return IPNetwork.Parse(string.Format("{0}/{1}", network, prefixLen.ToString()));
@ -115,7 +112,7 @@ namespace cloud.insecurity.docker.ipam
if (bytes.Length == 4) if (bytes.Length == 4)
{ {
bytes = new byte[] {0, 0, 0, 0}.Concat(bytes).ToArray() bytes = new byte[] {0, 0, 0, 0}.Concat(bytes).ToArray()
.Concat(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0}).ToArray(); .Concat(new byte[] {0, 0, 0, 0, 0, 0, 0, 0}).ToArray();
} }
//bytes = bytes.Select(b => Convert.ToByte(b ^ prefixLen)).ToArray(); //bytes = bytes.Select(b => Convert.ToByte(b ^ prefixLen)).ToArray();
@ -126,17 +123,17 @@ namespace cloud.insecurity.docker.ipam
{ {
// https://en.wikipedia.org/wiki/Universally_unique_identifier#History // https://en.wikipedia.org/wiki/Universally_unique_identifier#History
return new Guid( return new Guid(
b.ReadUInt32(), // time low b.ReadUInt32(),
b.ReadUInt16(), // time mid b.ReadUInt16(),
b.ReadUInt16(), // time hi and version b.ReadUInt16(),
b.ReadByte(), // clock seq hi and res? b.ReadByte(),
b.ReadByte(), // clock seq lo? b.ReadByte(),
b.ReadByte(), b.ReadByte(),
b.ReadByte(), b.ReadByte(),
b.ReadByte(), b.ReadByte(),
b.ReadByte(), b.ReadByte(),
b.ReadByte(), b.ReadByte(),
b.ReadByte() /* 48-bit node id */); b.ReadByte());
// however this is RFC4122 (g)UUID and the information // however this is RFC4122 (g)UUID and the information
// is definitely not relevant but a nice piece of // is definitely not relevant but a nice piece of
// nostalgia. // nostalgia.
@ -144,24 +141,24 @@ namespace cloud.insecurity.docker.ipam
} }
} }
} }
new public int GetHashCode()
{
return GetUniqueId(Net, PrefixLen).GetHashCode();
}
public Scope GetUnassignedScope() public Scope GetUnassignedScope()
{ {
if (Locked)
throw new InvalidOperationException("scope is locked");
return Network.Subnet(Convert.ToByte(Schema.child_prefix)).Where(s =>
// Network.Subnet(Convert.ToByte(Schema.child_prefix)).Where(p => {
// { return !Db.GetCollection<Scope>("Scopes")
// using (var db = new LiteDatabase(@"IPAM.db")) .Find(scope => scope.Id == GetUniqueId(s.Network.ToString(), s.Cidr)
// { && scope.Allocated)
// var col = db.GetCollection<Scope>("Scopes"); .Any();
// }).Select(s => new Scope()
// } {
// }); Net = s.Network.ToString(),
throw new NotImplementedException();; PrefixLen = Schema.child_prefix.GetValueOrDefault(),
ParentScope = this,
}).Single();
} }
public IPAddress LeaseNetworkAddress() public IPAddress LeaseNetworkAddress()
@ -183,7 +180,8 @@ namespace cloud.insecurity.docker.ipam
return EnumerateSchemaScopes(enumerable); return EnumerateSchemaScopes(enumerable);
} }
private static IEnumerable<Scope> EnumerateSchemaScopes(IEnumerable<schema.Scope> enumerable, Scope? parent = null) private static IEnumerable<Scope> EnumerateSchemaScopes(IEnumerable<schema.Scope> enumerable,
Scope? parent = null)
{ {
foreach (var scope in enumerable) foreach (var scope in enumerable)
{ {
@ -203,7 +201,7 @@ namespace cloud.insecurity.docker.ipam
Log.Debug("DB not initialized?", ex); Log.Debug("DB not initialized?", ex);
} }
if (newScope == null) if (newScope == null)
{ {
newScope = new Scope() newScope = new Scope()
{ {
@ -216,7 +214,6 @@ namespace cloud.insecurity.docker.ipam
TcpIpVersion = scope.tcp_ip_version, TcpIpVersion = scope.tcp_ip_version,
Locked = (scope.lock_down.GetValueOrDefault()) ? true : false, Locked = (scope.lock_down.GetValueOrDefault()) ? true : false,
ParentScope = parent ParentScope = parent
}; };
Db.GetCollection<Scope>("Scopes") Db.GetCollection<Scope>("Scopes")

@ -5,7 +5,7 @@ namespace cloud.insecurity.http
{ {
public class HttpRequest : IHttpRequest public class HttpRequest : IHttpRequest
{ {
private readonly HttpListenerContext Context; internal readonly HttpListenerContext Context;
public IHttpRequest.RequestMethod Method public IHttpRequest.RequestMethod Method

@ -6,44 +6,50 @@ namespace cloud.insecurity.http
{ {
public class HttpResponse : IHttpResponse public class HttpResponse : IHttpResponse
{ {
HttpListenerContext Context; internal HttpRequest Request;
public WebHeaderCollection Headers = new WebHeaderCollection() public WebHeaderCollection Headers = new WebHeaderCollection()
{ {
{"Server", "insecurity"}, {"Server", "insecurity"},
}; };
public HttpResponse(HttpListenerContext context) public HttpResponse(HttpRequest request)
{ {
Context = context; Request = request;
Context.Response.Headers = Headers;
} }
public void Dispose() public void Dispose()
{ {
DefaultHttpResponse.New(Context).Dispose(); DefaultHttpResponse.New(Request.Context).Dispose();
} }
public IHttpResponse SendResponse() public IHttpResponse SendResponse()
{ {
return DefaultHttpResponse.New(Context) return DefaultHttpResponse.New(Request.Context)
.SendResponse(); .SendResponse();
} }
public IHttpResponse NotFound() public IHttpResponse NotFound()
{ {
return DefaultHttpResponse.New(Context) return DefaultHttpResponse.New(Request.Context)
.NotFound(); .NotFound();
} }
public IHttpResponse InternalServerError() public IHttpResponse InternalServerError()
{ {
return DefaultHttpResponse.New(Context) return DefaultHttpResponse.New(Request.Context)
.InternalServerError(); .InternalServerError();
} }
public IHttpResponse NotImplemented() public IHttpResponse NotImplemented()
{ {
return DefaultHttpResponse.New(Context) return DefaultHttpResponse.New(Request.Context)
.NotImplemented(); .NotImplemented();
} }
public IHttpResponse Ok()
{
return DefaultHttpResponse
.New(Request.Context)
.Ok();
}
} }
} }

@ -45,6 +45,12 @@ namespace cloud.insecurity.http
return this; return this;
} }
public IHttpResponse Ok()
{
Context.Response.StatusCode = (int) IHttpResponse.ResponseCodes.Ok;
return this;
}
public static IHttpResponse New(HttpListenerContext context) public static IHttpResponse New(HttpListenerContext context)
{ {
return new DefaultHttpResponse(context); return new DefaultHttpResponse(context);

@ -20,6 +20,15 @@ namespace cloud.insecurity.http
private readonly HttpListener Listener = new HttpListener(); private readonly HttpListener Listener = new HttpListener();
private readonly static HttpServer Instance = new HttpServer(); private readonly static HttpServer Instance = new HttpServer();
private readonly Tuple<MethodInfo, HttpRequestHandler>[] Handlers; private readonly Tuple<MethodInfo, HttpRequestHandler>[] Handlers;
public bool Running
{
get
{
return Listener.IsListening;
}
}
public static HttpServer Server public static HttpServer Server
{ {
@ -58,7 +67,7 @@ namespace cloud.insecurity.http
Listener.Close(); Listener.Close();
} }
public async Task Start(string[] listeners) public async Task<Task> Start(string[] listeners)
{ {
listeners.ToList().ForEach(l => Listener.Prefixes.Add(l)); listeners.ToList().ForEach(l => Listener.Prefixes.Add(l));
@ -98,6 +107,8 @@ namespace cloud.insecurity.http
}, Listener.GetContext()); }, Listener.GetContext());
} }
}); });
return Task.CompletedTask;
} }
private IHttpResponse HandleContext(HttpListenerContext ctx) private IHttpResponse HandleContext(HttpListenerContext ctx)

@ -71,5 +71,6 @@ namespace cloud.insecurity.http
public IHttpResponse NotFound(); public IHttpResponse NotFound();
public IHttpResponse InternalServerError(); public IHttpResponse InternalServerError();
public IHttpResponse NotImplemented(); public IHttpResponse NotImplemented();
public IHttpResponse Ok();
} }
} }