feat: add monitoring HTTP endpoints and TLS support

Monitoring HTTP:
- /varz, /connz, /healthz via Kestrel Minimal API
- Pagination, sorting, subscription details on /connz
- ServerStats atomic counters, CPU/memory sampling
- CLI flags: -m, --http_port, --http_base_path, --https_port

TLS Support:
- 4-mode negotiation: no TLS, required, TLS-first, mixed
- Certificate loading, pinning (SHA-256), client cert verification
- PeekableStream for non-destructive TLS detection
- Token-bucket rate limiter for TLS handshakes
- CLI flags: --tls, --tlscert, --tlskey, --tlscacert, --tlsverify

29 new tests (78 → 107 total), all passing.

# Conflicts:
#	src/NATS.Server.Host/Program.cs
#	src/NATS.Server/NATS.Server.csproj
#	src/NATS.Server/NatsClient.cs
#	src/NATS.Server/NatsOptions.cs
#	src/NATS.Server/NatsServer.cs
#	src/NATS.Server/Protocol/NatsProtocol.cs
#	tests/NATS.Server.Tests/ClientTests.cs
This commit is contained in:
Joseph Doherty
2026-02-22 23:13:22 -05:00
24 changed files with 2596 additions and 43 deletions

View File

@@ -1,3 +1,4 @@
using System.Security.Authentication;
using NATS.Server.Auth;
namespace NATS.Server;
@@ -7,7 +8,7 @@ public sealed class NatsOptions
public string Host { get; set; } = "0.0.0.0";
public int Port { get; set; } = 4222;
public string? ServerName { get; set; }
public int MaxPayload { get; set; } = 1024 * 1024; // 1MB
public int MaxPayload { get; set; } = 1024 * 1024;
public int MaxControlLine { get; set; } = 4096;
public int MaxConnections { get; set; } = 65536;
public TimeSpan PingInterval { get; set; } = TimeSpan.FromMinutes(2);
@@ -27,4 +28,27 @@ public sealed class NatsOptions
// Auth timing
public TimeSpan AuthTimeout { get; set; } = TimeSpan.FromSeconds(2);
// Monitoring (0 = disabled; standard port is 8222)
public int MonitorPort { get; set; }
public string MonitorHost { get; set; } = "0.0.0.0";
public string? MonitorBasePath { get; set; }
// 0 = disabled
public int MonitorHttpsPort { get; set; }
// TLS
public string? TlsCert { get; set; }
public string? TlsKey { get; set; }
public string? TlsCaCert { get; set; }
public bool TlsVerify { get; set; }
public bool TlsMap { get; set; }
public TimeSpan TlsTimeout { get; set; } = TimeSpan.FromSeconds(2);
public bool TlsHandshakeFirst { get; set; }
public TimeSpan TlsHandshakeFirstFallback { get; set; } = TimeSpan.FromMilliseconds(50);
public bool AllowNonTls { get; set; }
public long TlsRateLimit { get; set; }
public HashSet<string>? TlsPinnedCerts { get; set; }
public SslProtocols TlsMinVersion { get; set; } = SslProtocols.Tls12;
public bool HasTls => TlsCert != null && TlsKey != null;
}