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