cd
This commit is contained in:
parent
2f87a95828
commit
c838711e3e
23 changed files with 454 additions and 25 deletions
57
README.md
Normal file
57
README.md
Normal file
|
@ -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
|
||||||
|
```
|
52
main.key.pem
Normal file
52
main.key.pem
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
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
|
||||||
|
A6a/XxsG5QEM+okhljJX1TmpmsjsiA==
|
||||||
|
-----END PRIVATE KEY-----
|
29
main.pem
Normal file
29
main.pem
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
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
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -1,5 +1,9 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Nyangate.Lib\Nyangate.Lib.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
|
33
src/Nyangate.Lib/Data/IPRoute.cs
Normal file
33
src/Nyangate.Lib/Data/IPRoute.cs
Normal file
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
8
src/Nyangate.Lib/Data/RoutingInfo.cs
Normal file
8
src/Nyangate.Lib/Data/RoutingInfo.cs
Normal file
|
@ -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; }
|
||||||
|
}
|
15
src/Nyangate.Lib/Data/ServerHost.cs
Normal file
15
src/Nyangate.Lib/Data/ServerHost.cs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
namespace Nyangate.Lib.Data;
|
||||||
|
|
||||||
|
public class ServerHost
|
||||||
|
{
|
||||||
|
public required string Hostname { get; set; }
|
||||||
|
public ICollection<string> Aliases { get; set; } = Array.Empty<string>();
|
||||||
|
public required RoutingInfo Route { get; set; }
|
||||||
|
|
||||||
|
public Uri CreateBaseUri() => new UriBuilder()
|
||||||
|
{
|
||||||
|
Scheme = Route.UsesTls ? "https" : "http",
|
||||||
|
Host = Route.Route.GetHost(),
|
||||||
|
Port = Route.Port,
|
||||||
|
}.Uri;
|
||||||
|
}
|
27
src/Nyangate.Lib/Http/HttpContextAdapter.cs
Normal file
27
src/Nyangate.Lib/Http/HttpContextAdapter.cs
Normal file
|
@ -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;
|
||||||
|
}
|
|
@ -6,4 +6,8 @@
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
8
src/Nyangate.Lib/Routing/RoutingStrategy.cs
Normal file
8
src/Nyangate.Lib/Routing/RoutingStrategy.cs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
using Nyangate.Lib.Data;
|
||||||
|
|
||||||
|
namespace Nyangate.Lib.Routing;
|
||||||
|
|
||||||
|
public abstract class RoutingStrategy
|
||||||
|
{
|
||||||
|
public abstract IPRoute Next();
|
||||||
|
}
|
21
src/Nyangate/Filters/ContextFilter.cs
Normal file
21
src/Nyangate/Filters/ContextFilter.cs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
namespace Nyangate.Filters;
|
||||||
|
|
||||||
|
public class ContextFilter
|
||||||
|
{
|
||||||
|
private readonly List<IFilter> _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
|
||||||
|
}
|
8
src/Nyangate/Filters/IFilter.cs
Normal file
8
src/Nyangate/Filters/IFilter.cs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Nyangate.Filters;
|
||||||
|
|
||||||
|
public interface IFilter
|
||||||
|
{
|
||||||
|
public void Apply(HttpContext context);
|
||||||
|
|
||||||
|
public FilterType Type { get; }
|
||||||
|
}
|
40
src/Nyangate/Filters/ProxyHeaderFilter.cs
Normal file
40
src/Nyangate/Filters/ProxyHeaderFilter.cs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using Microsoft.Net.Http.Headers;
|
||||||
|
|
||||||
|
namespace Nyangate.Filters;
|
||||||
|
|
||||||
|
public class ProxyHeaderFilter : IFilter
|
||||||
|
{
|
||||||
|
private static readonly HashSet<string> _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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
17
src/Nyangate/Middleware/Annotator.cs
Normal file
17
src/Nyangate/Middleware/Annotator.cs
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,3 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Nyangate.Middleware;
|
namespace Nyangate.Middleware;
|
||||||
|
|
||||||
public class Filter
|
public class Filter
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
using Microsoft.Extensions.Primitives;
|
||||||
|
using Nyangate.Filters;
|
||||||
|
using Nyangate.Lib.Http;
|
||||||
using Nyangate.Services;
|
using Nyangate.Services;
|
||||||
|
|
||||||
namespace Nyangate.Middleware
|
namespace Nyangate.Middleware
|
||||||
|
@ -15,11 +18,50 @@ namespace Nyangate.Middleware
|
||||||
|
|
||||||
public async Task Invoke(HttpContext ctx)
|
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
|
//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}");
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Nyangate.Lib\Nyangate.Lib.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
using Microsoft.AspNetCore.Components.Routing;
|
|
||||||
using Nyangate;
|
|
||||||
using Nyangate.Middleware;
|
using Nyangate.Middleware;
|
||||||
using Nyangate.Services;
|
using Nyangate.Services;
|
||||||
|
|
||||||
|
@ -29,6 +27,9 @@ var app = builder.Build();
|
||||||
|
|
||||||
app.UseMiddleware<Authenticator>();
|
app.UseMiddleware<Authenticator>();
|
||||||
app.UseMiddleware<Filter>();
|
app.UseMiddleware<Filter>();
|
||||||
|
app.UseMiddleware<IPFilter>();
|
||||||
|
app.UseMiddleware<IDSFilter>();
|
||||||
|
app.UseMiddleware<Annotator>();
|
||||||
app.UseMiddleware<Nyangate.Middleware.Router>();
|
app.UseMiddleware<Nyangate.Middleware.Router>();
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Nyangate.Services;
|
namespace Nyangate.Services;
|
||||||
|
|
||||||
public class BlacklistRegistry
|
public class BlacklistRegistry
|
||||||
{
|
{
|
||||||
|
public BlacklistRegistry()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Dictionary<string, long> Blacklisted = new();
|
||||||
|
|
||||||
|
public async Task<bool> IsBlacklisted(HttpContext ctx)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
26
src/Nyangate/Services/RateLimitService.cs
Normal file
26
src/Nyangate/Services/RateLimitService.cs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace Nyangate.Services;
|
||||||
|
|
||||||
|
public class RateLimitService
|
||||||
|
{
|
||||||
|
public async Task<bool> IsRateLimited(IPAddress addr, bool update = true)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> 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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,43 @@
|
||||||
using System;
|
using Nyangate.Lib.Data;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Nyangate.Services;
|
namespace Nyangate.Services;
|
||||||
|
|
||||||
public class RoutingMap
|
public class RoutingMap
|
||||||
{
|
{
|
||||||
|
public RoutingMap()
|
||||||
|
{
|
||||||
|
_hosts.Add("meow", new()
|
||||||
|
{
|
||||||
|
Hostname = "meow",
|
||||||
|
Route = new()
|
||||||
|
{
|
||||||
|
UsesTls = false,
|
||||||
|
Port = 8888,
|
||||||
|
Route = new("localhost")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Dictionary<string, ServerHost> _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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Nyangate.Services;
|
namespace Nyangate.Services;
|
||||||
|
|
||||||
public class ServerCertificateRegistry
|
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<string, X509Certificate2> _registry = new();
|
private readonly Dictionary<string, X509Certificate2> _registry = new();
|
||||||
|
private readonly X509Certificate2 _main;
|
||||||
public X509Certificate2 GetOrDefault(string hostname)
|
public X509Certificate2 GetOrDefault(string hostname)
|
||||||
{
|
{
|
||||||
return _registry.GetValueOrDefault(hostname, Default());
|
return _registry.GetValueOrDefault(hostname, Default());
|
||||||
|
@ -16,6 +18,6 @@ public class ServerCertificateRegistry
|
||||||
|
|
||||||
public X509Certificate2 Default()
|
public X509Certificate2 Default()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return _main;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
global using Xunit;
|
|
Loading…
Reference in a new issue