diff --git a/README.md b/README.md
new file mode 100644
index 0000000..da25ca8
--- /dev/null
+++ b/README.md
@@ -0,0 +1,57 @@
+# Nyangate
+
+NYANET reverse proxy for HTTP
+
+## Features
+
+- [ ] configurable routing
+- [ ] load balancing
+- [ ] access control
+- [ ] integration with IPMeow IPAM
+- [ ] header stripping and rewriting
+- [ ] intrusion detection
+- [ ] rate limiting
+- [ ] CLI interface
+- [ ] REST API
+
+## Building
+
+Building with Docker
+
+```bash
+ docker build . --tag nyangate
+```
+
+Local compilation
+
+```bash
+ dotnet build
+```
+
+## Running
+
+To run with Docker
+
+```bash
+ docker run -it nyanet/nyangate
+```
+
+or docker-compose
+
+```yaml
+version: '3.3'
+services:
+ nyangate:
+ ports:
+ - '80:80'
+ - '443:443'
+ volumes:
+ - './data:/srv/nyangate/config'
+ - './certs:/etc/tls/certs:ro'
+ restart: always
+ image: nyanet/nyangate
+```
+
+```bash
+ docker-compose up -d
+```
diff --git a/main.key.pem b/main.key.pem
new file mode 100644
index 0000000..e6769fc
--- /dev/null
+++ b/main.key.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+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
+A6a/XxsG5QEM+okhljJX1TmpmsjsiA==
+-----END PRIVATE KEY-----
diff --git a/main.pem b/main.pem
new file mode 100644
index 0000000..a94379e
--- /dev/null
+++ b/main.pem
@@ -0,0 +1,29 @@
+-----BEGIN CERTIFICATE-----
+MIIFAzCCAuugAwIBAgIUSSnKwcDCcz5MhNWZ/eV+uhBap6kwDQYJKoZIhvcNAQEL
+BQAwETEPMA0GA1UEAwwGTllBTkVUMB4XDTIzMDMyODEwMzMxM1oXDTI0MDMyNzEw
+MzMxM1owETEPMA0GA1UEAwwGTllBTkVUMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
+MIICCgKCAgEAtxOJBxEe9EWGYZgzQfH9mnvoTwVMVPgIPpos4PYYFvJeXrCitwIA
+j0ZCmT4Pekvq/5RH4n4NOltpSEXjM1ghbt8Yo/W5y5YquQGO74nK6HQhQBT+ix0l
+9M3xKvZZv8H8R6FLHT0Y0IHz5dV0BjAXsztT2tFvYDOXZHz+gehp9fZ2ToqJKa4W
+2avhMWL4v/OaP48WmW/42q6sDIqbvQ+TvAQKMFRrDSKoeC8wN1uOh2BFv0FIsrA5
+PhGlFnD9GmNYW5HZAi0RmiQVdlq6abZud9Ve/ny9SpT7+3XP2QjE737lRbkELnfQ
+KTo17eHfFGv82yUY0PImzkSBojuZg4wf44dpml5RiXYprJGVirxeTkMVOS3tnFA4
+75Ux0MoS9xSxwznHJpDQ+7NMooxQSDk1KY5cBqAdymSAptAL0jJBMg83hkBpGEx6
+tzEoIlH4skGKoV4HuSBlihk8uLcV/NpW49Th8THVr55lZZwXCma8JgWpFd9eF1Es
+mPGzQzRUeiunBpWwDvGKjWZ6jxXR/2OCofKPQOMOkWq8TXZiV0Xbg6KXFJTisZB2
+nwC6hqKzaudGxuBnbogwMaLBqqfndrcWO9pJhEMIow6OEUhEIvmUl8B8HFXu+dOR
+dxRyNQldEBU7erN+dLrhIjbO0LayRHIQge6mjiikLJF0IHEVL4v5GOECAwEAAaNT
+MFEwHQYDVR0OBBYEFPwC9awfqcrGqfdfByhXS7eF0/9JMB8GA1UdIwQYMBaAFPwC
+9awfqcrGqfdfByhXS7eF0/9JMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
+BQADggIBAKN1U3DSTamMqHb5mETk55wokbGGOJfxz7WDfqzbOnpUkyuvMEiZ0QI9
+nMHFJd7LHGca2f28y3yZWAcvGkhLk2A6LDeBBoE1q+V2Ss4LR7dMK/UU895yJKLC
+whs+04cR8kKPLOlaOUdO/uqCJ0JDBxXTsIj2VIHVeF3FybvRgPSjuO0nej+SQDT1
+dG3ZJV09AVujWBA9gYLl/7Cr9GdgJmfx+JJ685R7qDrO5n7hpW5P7HAa+7viXzhd
+x34er0l8b4pLzBXn2bl2gsaKvXCBXs6TkL2i+FwoihDk7rMiMpxKvzaHmk/9F6xD
+HrOrJHCSv5vTxsPTHsfgGa2D8eNg7qK8rySEbzOiMw2CgT6peQMlDTvQbSCE4E/q
+7g5rOc4GSFOd6C6HMP18BGBFNW3iGwrB7I3s+sonLzEesKlG9JnmQTTIC0bnZjzl
+5RDkpaQjawBkU0jVYx7//2Fmj7SplLCuAj54LHTh1bhk8kduEi7qX2TmaTJboVX2
+J1JB3OhEOkaJ4rd+u3LED6sbkO8TWNsI7/Vyz3gbfB5E/nop8jibpoZ67LI1Yjf4
+eior7k6HOJ7uisnCp3n69aVkUd0FEEVEXr1+LcNt2V5iR24jhs76XSLYqsUwVdU/
+6zfPt1qT//7MS/KZNU69oJzstqkprXRkelc0SoBB+BY4oWUIvSXR
+-----END CERTIFICATE-----
diff --git a/src/Nyangate.Cli/Nyangate.Cli.csproj b/src/Nyangate.Cli/Nyangate.Cli.csproj
index f02677b..9424d3d 100644
--- a/src/Nyangate.Cli/Nyangate.Cli.csproj
+++ b/src/Nyangate.Cli/Nyangate.Cli.csproj
@@ -1,5 +1,9 @@
+
+
+
+
Exe
net7.0
diff --git a/src/Nyangate.Lib/Data/IPRoute.cs b/src/Nyangate.Lib/Data/IPRoute.cs
new file mode 100644
index 0000000..3874ca5
--- /dev/null
+++ b/src/Nyangate.Lib/Data/IPRoute.cs
@@ -0,0 +1,33 @@
+using System.Net;
+
+namespace Nyangate.Lib.Data;
+
+public enum RouteType : byte
+{
+ STATIC_ADDRESS = 0x0,
+ HOSTNAME = 0x1
+}
+
+public class IPRoute
+{
+ public IPRoute(string addrOrName)
+ {
+ if (!IPAddress.TryParse(addrOrName, out _addr))
+ {
+ _dnsName = addrOrName;
+ }
+ }
+
+ private readonly IPAddress? _addr;
+ private readonly string? _dnsName;
+ public RouteType Type { get; set; }
+ public IPAddress Resolve()
+ {
+ return _addr ?? Dns.GetHostEntry(_dnsName!, System.Net.Sockets.AddressFamily.Unspecified).AddressList.First();//TODO: Cleanup
+ }
+
+ public string GetHost()
+ {
+ return _dnsName ?? _addr!.ToString();
+ }
+}
diff --git a/src/Nyangate.Lib/Data/RoutingInfo.cs b/src/Nyangate.Lib/Data/RoutingInfo.cs
new file mode 100644
index 0000000..fbbbe7f
--- /dev/null
+++ b/src/Nyangate.Lib/Data/RoutingInfo.cs
@@ -0,0 +1,8 @@
+namespace Nyangate.Lib.Data;
+
+public class RoutingInfo
+{
+ public bool UsesTls { get; set; }
+ public required IPRoute Route { get; set; }
+ public required int Port { get; set; }
+}
diff --git a/src/Nyangate.Lib/Data/ServerHost.cs b/src/Nyangate.Lib/Data/ServerHost.cs
new file mode 100644
index 0000000..4fc5079
--- /dev/null
+++ b/src/Nyangate.Lib/Data/ServerHost.cs
@@ -0,0 +1,15 @@
+namespace Nyangate.Lib.Data;
+
+public class ServerHost
+{
+ public required string Hostname { get; set; }
+ public ICollection Aliases { get; set; } = Array.Empty();
+ public required RoutingInfo Route { get; set; }
+
+ public Uri CreateBaseUri() => new UriBuilder()
+ {
+ Scheme = Route.UsesTls ? "https" : "http",
+ Host = Route.Route.GetHost(),
+ Port = Route.Port,
+ }.Uri;
+}
diff --git a/src/Nyangate.Lib/Http/HttpContextAdapter.cs b/src/Nyangate.Lib/Http/HttpContextAdapter.cs
new file mode 100644
index 0000000..a150f96
--- /dev/null
+++ b/src/Nyangate.Lib/Http/HttpContextAdapter.cs
@@ -0,0 +1,27 @@
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.Extensions;
+
+namespace Nyangate.Lib.Http;
+
+public class HttpContextAdapter
+{
+ public HttpContextAdapter(HttpContext ctx)
+ {
+ _ctx = ctx;
+
+ _msg = new HttpRequestMessage(new HttpMethod(ctx.Request.Method), ctx.Request.GetEncodedUrl());
+
+ foreach (var header in ctx.Request.Headers)
+ {
+ _msg.Headers.Add(header.Key, header.Value.AsEnumerable());
+ }
+
+ _msg.VersionPolicy = HttpVersionPolicy.RequestVersionOrHigher;
+ }
+
+ private readonly HttpContext _ctx;
+
+ public HttpRequestMessage _msg;
+
+ public HttpRequestMessage Message => _msg;
+}
diff --git a/src/Nyangate.Lib/Nyangate.Lib.csproj b/src/Nyangate.Lib/Nyangate.Lib.csproj
index cfadb03..b0aae5e 100644
--- a/src/Nyangate.Lib/Nyangate.Lib.csproj
+++ b/src/Nyangate.Lib/Nyangate.Lib.csproj
@@ -6,4 +6,8 @@
enable
+
+
+
+
diff --git a/src/Nyangate.Lib/Routing/RoutingStrategy.cs b/src/Nyangate.Lib/Routing/RoutingStrategy.cs
new file mode 100644
index 0000000..946b819
--- /dev/null
+++ b/src/Nyangate.Lib/Routing/RoutingStrategy.cs
@@ -0,0 +1,8 @@
+using Nyangate.Lib.Data;
+
+namespace Nyangate.Lib.Routing;
+
+public abstract class RoutingStrategy
+{
+ public abstract IPRoute Next();
+}
diff --git a/src/Nyangate/Filters/ContextFilter.cs b/src/Nyangate/Filters/ContextFilter.cs
new file mode 100644
index 0000000..085b514
--- /dev/null
+++ b/src/Nyangate/Filters/ContextFilter.cs
@@ -0,0 +1,21 @@
+namespace Nyangate.Filters;
+
+public class ContextFilter
+{
+ private readonly List _filters = typeof(IFilter).Assembly.GetTypes().Where(t => t.IsAssignableFrom(typeof(IFilter))).Select(t => (IFilter)Activator.CreateInstance(t)!).ToList();
+ public void ApplyAll(FilterType type, HttpContext ctx)
+ {
+ foreach (var filter in _filters.Where(f => f.Type.HasFlag(type)))
+ {
+ filter.Apply(ctx); //TODO: Priorities
+ }
+ }
+}
+
+[Flags]
+public enum FilterType : int
+{
+ Proxy = 0x1,
+ Sensitive = 0x2,
+ All = 0xff
+}
diff --git a/src/Nyangate/Filters/IFilter.cs b/src/Nyangate/Filters/IFilter.cs
new file mode 100644
index 0000000..a2136ba
--- /dev/null
+++ b/src/Nyangate/Filters/IFilter.cs
@@ -0,0 +1,8 @@
+namespace Nyangate.Filters;
+
+public interface IFilter
+{
+ public void Apply(HttpContext context);
+
+ public FilterType Type { get; }
+}
diff --git a/src/Nyangate/Filters/ProxyHeaderFilter.cs b/src/Nyangate/Filters/ProxyHeaderFilter.cs
new file mode 100644
index 0000000..dd4e2d5
--- /dev/null
+++ b/src/Nyangate/Filters/ProxyHeaderFilter.cs
@@ -0,0 +1,40 @@
+using System.Collections.Immutable;
+using Microsoft.Net.Http.Headers;
+
+namespace Nyangate.Filters;
+
+public class ProxyHeaderFilter : IFilter
+{
+ private static readonly HashSet _headersToExclude = new(18, StringComparer.OrdinalIgnoreCase)
+ {
+ HeaderNames.Connection,
+ HeaderNames.TransferEncoding,
+ HeaderNames.KeepAlive,
+ HeaderNames.Upgrade,
+ HeaderNames.ProxyConnection,
+ HeaderNames.ProxyAuthenticate,
+ "Proxy-Authentication-Info",
+ HeaderNames.ProxyAuthorization,
+ "Proxy-Features",
+ "Proxy-Instruction",
+ "Security-Scheme",
+ "ALPN",
+ "Close",
+ "HTTP2-Settings",
+ HeaderNames.UpgradeInsecureRequests,
+ HeaderNames.TE,
+ HeaderNames.AltSvc,
+ HeaderNames.StrictTransportSecurity,
+ };
+
+ public FilterType Type => FilterType.Proxy;
+
+ public void Apply(HttpContext context)
+ {
+ foreach (var header in context.Request.Headers.Where(x => _headersToExclude.Contains(x.Key, StringComparer.OrdinalIgnoreCase)).ToArray())
+ {
+ context.Request.Headers.Remove(header);
+ }
+
+ }
+}
diff --git a/src/Nyangate/Middleware/Annotator.cs b/src/Nyangate/Middleware/Annotator.cs
new file mode 100644
index 0000000..1a62993
--- /dev/null
+++ b/src/Nyangate/Middleware/Annotator.cs
@@ -0,0 +1,17 @@
+namespace Nyangate.Middleware;
+
+public class Annotator
+{
+ private readonly RequestDelegate _next;
+
+ public Annotator(RequestDelegate next)
+ {
+ _next = next;
+ }
+
+ public async Task Invoke(HttpContext ctx)
+ {
+ ctx.Request.Headers.Add("Forwarded", $"for={ctx.Connection.RemoteIpAddress};by={ctx.Connection.LocalIpAddress};proto={ctx.Request.Scheme}");
+ await _next.Invoke(ctx);
+ }
+}
diff --git a/src/Nyangate/Middleware/Filter.cs b/src/Nyangate/Middleware/Filter.cs
index 7dbb085..eb493c4 100644
--- a/src/Nyangate/Middleware/Filter.cs
+++ b/src/Nyangate/Middleware/Filter.cs
@@ -1,8 +1,3 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-
namespace Nyangate.Middleware;
public class Filter
diff --git a/src/Nyangate/Middleware/Router.cs b/src/Nyangate/Middleware/Router.cs
index 4594ed2..e7c8eec 100644
--- a/src/Nyangate/Middleware/Router.cs
+++ b/src/Nyangate/Middleware/Router.cs
@@ -1,3 +1,6 @@
+using Microsoft.Extensions.Primitives;
+using Nyangate.Filters;
+using Nyangate.Lib.Http;
using Nyangate.Services;
namespace Nyangate.Middleware
@@ -15,11 +18,50 @@ namespace Nyangate.Middleware
public async Task Invoke(HttpContext ctx)
{
- string host = ctx.Request.Host.Host;
+ string hostname = ctx.Request.Host.Host;
//check ctx.Request.IsHttps if strict https required
+
+ var host = _map.Get(hostname) ?? _map.GetFallback();
+
+ if (host is null)
+ {
+ ctx.Response.StatusCode = 404;
+ await ctx.Response.WriteAsync("meowless~");
+ await ctx.Response.CompleteAsync();
+ return;
+ }
+
+ ctx.Request.Host = new HostString(host.Route.Route.GetHost(), host.Route.Port);
+ ctx.Request.Scheme = host.Route.UsesTls ? "https" : "http";
+
+ new ProxyHeaderFilter().Apply(ctx);
+
+ using HttpClient http = new();
+
+ HttpRequestMessage request = new HttpContextAdapter(ctx).Message;
+
+ if (ctx.Request.Body.CanRead)
+ {
+ request.Content = new StreamContent(ctx.Request.Body);
+ }
+
+ var response = await http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
+
Console.WriteLine($"meow: {ctx.Connection.RemoteIpAddress}");
- ctx.Response.StatusCode = 200;
- await _next.Invoke(ctx);
+
+ ctx.Response.StatusCode = (int)response.StatusCode;
+ ctx.Response.Headers.Clear();
+
+ foreach (var header in response.Headers.NonValidated)
+ {
+ ctx.Response.Headers.Add(header.Key, new StringValues(header.Value.ToArray()));
+ }
+
+ ctx.Response.ContentType = response.Content.Headers.ContentType?.ToString();
+ ctx.Response.Headers.Add("Content-Encoding", new StringValues(response.Content.Headers.ContentEncoding.ToArray()));
+
+ await response.Content.CopyToAsync(ctx.Response.Body);
+ await ctx.Response.CompleteAsync();
}
}
}
diff --git a/src/Nyangate/Nyangate.csproj b/src/Nyangate/Nyangate.csproj
index 4c2bb77..dcac148 100644
--- a/src/Nyangate/Nyangate.csproj
+++ b/src/Nyangate/Nyangate.csproj
@@ -1,5 +1,9 @@
+
+
+
+
net7.0
enable
diff --git a/src/Nyangate/Program.cs b/src/Nyangate/Program.cs
index fbbb356..8f3074e 100644
--- a/src/Nyangate/Program.cs
+++ b/src/Nyangate/Program.cs
@@ -1,5 +1,3 @@
-using Microsoft.AspNetCore.Components.Routing;
-using Nyangate;
using Nyangate.Middleware;
using Nyangate.Services;
@@ -29,6 +27,9 @@ var app = builder.Build();
app.UseMiddleware();
app.UseMiddleware();
+app.UseMiddleware();
+app.UseMiddleware();
+app.UseMiddleware();
app.UseMiddleware();
app.Run();
diff --git a/src/Nyangate/Services/BlacklistRegistry.cs b/src/Nyangate/Services/BlacklistRegistry.cs
index 5c74d45..2346da4 100644
--- a/src/Nyangate/Services/BlacklistRegistry.cs
+++ b/src/Nyangate/Services/BlacklistRegistry.cs
@@ -1,11 +1,16 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-
namespace Nyangate.Services;
public class BlacklistRegistry
{
+ public BlacklistRegistry()
+ {
+ }
+
+ private readonly Dictionary Blacklisted = new();
+
+ public async Task IsBlacklisted(HttpContext ctx)
+ {
+ throw new NotImplementedException();
+ }
}
diff --git a/src/Nyangate/Services/RateLimitService.cs b/src/Nyangate/Services/RateLimitService.cs
new file mode 100644
index 0000000..1079c8a
--- /dev/null
+++ b/src/Nyangate/Services/RateLimitService.cs
@@ -0,0 +1,26 @@
+using System.Net;
+
+namespace Nyangate.Services;
+
+public class RateLimitService
+{
+ public async Task IsRateLimited(IPAddress addr, bool update = true)
+ {
+ throw new NotImplementedException();
+ }
+
+ public async Task IsRateLimited(HttpContext ctx, bool update = true)
+ {
+ throw new NotImplementedException();
+ }
+
+ public async Task UpdateActivity(HttpContext ctx)
+ {
+ throw new NotImplementedException();
+ }
+
+ public async Task UpdateActivity(IPAddress addr)
+ {
+ throw new NotImplementedException();
+ }
+}
diff --git a/src/Nyangate/Services/RoutingMap.cs b/src/Nyangate/Services/RoutingMap.cs
index 94d27de..cf3666c 100644
--- a/src/Nyangate/Services/RoutingMap.cs
+++ b/src/Nyangate/Services/RoutingMap.cs
@@ -1,11 +1,43 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
+using Nyangate.Lib.Data;
namespace Nyangate.Services;
public class RoutingMap
{
+ public RoutingMap()
+ {
+ _hosts.Add("meow", new()
+ {
+ Hostname = "meow",
+ Route = new()
+ {
+ UsesTls = false,
+ Port = 8888,
+ Route = new("localhost")
+ }
+ });
+ }
+ private readonly Dictionary _hosts = new();
+ private readonly ServerHost? _fallbackHost;
+
+ public ServerHost? Get(string hostname)
+ {
+ return GetByMainHostname(hostname) ?? GetByAlias(hostname);
+ }
+
+ public ServerHost? GetByMainHostname(string hostname)
+ {
+ return _hosts.GetValueOrDefault(hostname);
+ }
+
+ public ServerHost? GetByAlias(string alias)
+ {
+ return _hosts.SingleOrDefault(x => x.Value.Aliases.Contains(alias)).Value;
+ }
+
+ public ServerHost? GetFallback()
+ {
+ return _fallbackHost;
+ }
}
diff --git a/src/Nyangate/Services/ServerCertificateRegistry.cs b/src/Nyangate/Services/ServerCertificateRegistry.cs
index b989cc7..b46b535 100644
--- a/src/Nyangate/Services/ServerCertificateRegistry.cs
+++ b/src/Nyangate/Services/ServerCertificateRegistry.cs
@@ -1,14 +1,16 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
using System.Security.Cryptography.X509Certificates;
-using System.Threading.Tasks;
namespace Nyangate.Services;
public class ServerCertificateRegistry
{
+ public ServerCertificateRegistry()
+ {
+ _main = X509Certificate2.CreateFromPemFile("/home/nya/Dev/csharp/nyangate/main.pem", "/home/nya/Dev/csharp/nyangate/main.key.pem");
+ }
+
private readonly Dictionary _registry = new();
+ private readonly X509Certificate2 _main;
public X509Certificate2 GetOrDefault(string hostname)
{
return _registry.GetValueOrDefault(hostname, Default());
@@ -16,6 +18,6 @@ public class ServerCertificateRegistry
public X509Certificate2 Default()
{
- throw new NotImplementedException();
+ return _main;
}
}
diff --git a/test/Nyangate.Test/Usings.cs b/test/Nyangate.Test/Usings.cs
index 8c927eb..e69de29 100644
--- a/test/Nyangate.Test/Usings.cs
+++ b/test/Nyangate.Test/Usings.cs
@@ -1 +0,0 @@
-global using Xunit;
\ No newline at end of file