You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
127 lines
4.9 KiB
C#
127 lines
4.9 KiB
C#
namespace OnlineMsgServer.Core
|
|
{
|
|
internal sealed class SecurityConfig
|
|
{
|
|
public int ListenPort { get; init; } = 13173;
|
|
public bool RequireWss { get; init; } = false;
|
|
public string? TlsCertPath { get; init; }
|
|
public string? TlsCertPassword { get; init; }
|
|
|
|
public string? ServerPrivateKeyBase64 { get; init; }
|
|
public string? ServerPrivateKeyPath { get; init; }
|
|
public bool AllowEphemeralServerKey { get; init; }
|
|
|
|
public int MaxConnections { get; init; } = 1000;
|
|
public int MaxMessageBytes { get; init; } = 64 * 1024;
|
|
public int RateLimitCount { get; init; } = 30;
|
|
public int RateLimitWindowSeconds { get; init; } = 10;
|
|
public int IpBlockSeconds { get; init; } = 120;
|
|
|
|
public int ChallengeTtlSeconds { get; init; } = 120;
|
|
public int MaxClockSkewSeconds { get; init; } = 60;
|
|
public int ReplayWindowSeconds { get; init; } = 120;
|
|
public string PeerNodeName { get; init; } = "server";
|
|
public bool PeerNodeNameExplicitlyConfigured { get; init; }
|
|
public string PeerUserPrefix { get; init; } = "peer:";
|
|
public string[] PeerUrls { get; init; } = [];
|
|
public int PeerReconnectSeconds { get; init; } = 5;
|
|
public int SeenCacheSeconds { get; init; } = 120;
|
|
|
|
public static SecurityConfig LoadFromEnvironment()
|
|
{
|
|
string? rawPeerNodeName = GetString("PEER_NODE_NAME");
|
|
return new SecurityConfig
|
|
{
|
|
ListenPort = GetInt("LISTEN_PORT", 13173, 1),
|
|
RequireWss = GetBool("REQUIRE_WSS", false),
|
|
TlsCertPath = GetString("TLS_CERT_PATH"),
|
|
TlsCertPassword = GetString("TLS_CERT_PASSWORD"),
|
|
ServerPrivateKeyBase64 = GetString("SERVER_PRIVATE_KEY_B64"),
|
|
ServerPrivateKeyPath = GetString("SERVER_PRIVATE_KEY_PATH"),
|
|
AllowEphemeralServerKey = GetBool("ALLOW_EPHEMERAL_SERVER_KEY", false),
|
|
MaxConnections = GetInt("MAX_CONNECTIONS", 1000, 1),
|
|
MaxMessageBytes = GetInt("MAX_MESSAGE_BYTES", 64 * 1024, 512),
|
|
RateLimitCount = GetInt("RATE_LIMIT_COUNT", 30, 1),
|
|
RateLimitWindowSeconds = GetInt("RATE_LIMIT_WINDOW_SECONDS", 10, 1),
|
|
IpBlockSeconds = GetInt("IP_BLOCK_SECONDS", 120, 1),
|
|
ChallengeTtlSeconds = GetInt("CHALLENGE_TTL_SECONDS", 120, 10),
|
|
MaxClockSkewSeconds = GetInt("MAX_CLOCK_SKEW_SECONDS", 60, 1),
|
|
ReplayWindowSeconds = GetInt("REPLAY_WINDOW_SECONDS", 120, 10),
|
|
PeerNodeName = rawPeerNodeName ?? CreateGuestName(),
|
|
PeerNodeNameExplicitlyConfigured = !string.IsNullOrWhiteSpace(rawPeerNodeName),
|
|
PeerUserPrefix = GetString("PEER_USER_PREFIX") ?? "peer:",
|
|
PeerUrls = GetCsv("PEER_URLS"),
|
|
PeerReconnectSeconds = GetInt("PEER_RECONNECT_SECONDS", 5, 1),
|
|
SeenCacheSeconds = GetInt("SEEN_CACHE_SECONDS", 120, 1),
|
|
};
|
|
}
|
|
|
|
private static string? GetString(string key)
|
|
{
|
|
string? value = Environment.GetEnvironmentVariable(key);
|
|
if (string.IsNullOrWhiteSpace(value))
|
|
{
|
|
return null;
|
|
}
|
|
return value.Trim();
|
|
}
|
|
|
|
private static bool GetBool(string key, bool defaultValue)
|
|
{
|
|
string? value = Environment.GetEnvironmentVariable(key);
|
|
if (string.IsNullOrWhiteSpace(value))
|
|
{
|
|
return defaultValue;
|
|
}
|
|
|
|
if (bool.TryParse(value, out bool parsed))
|
|
{
|
|
return parsed;
|
|
}
|
|
|
|
return value.Trim() switch
|
|
{
|
|
"1" => true,
|
|
"0" => false,
|
|
_ => defaultValue
|
|
};
|
|
}
|
|
|
|
private static int GetInt(string key, int defaultValue, int minValue)
|
|
{
|
|
string? value = Environment.GetEnvironmentVariable(key);
|
|
if (string.IsNullOrWhiteSpace(value))
|
|
{
|
|
return defaultValue;
|
|
}
|
|
|
|
if (!int.TryParse(value, out int parsed))
|
|
{
|
|
return defaultValue;
|
|
}
|
|
|
|
return Math.Max(parsed, minValue);
|
|
}
|
|
|
|
private static string[] GetCsv(string key)
|
|
{
|
|
string? value = Environment.GetEnvironmentVariable(key);
|
|
if (string.IsNullOrWhiteSpace(value))
|
|
{
|
|
return [];
|
|
}
|
|
|
|
return value
|
|
.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
|
.Where(item => !string.IsNullOrWhiteSpace(item))
|
|
.Distinct(StringComparer.Ordinal)
|
|
.ToArray();
|
|
}
|
|
|
|
private static string CreateGuestName()
|
|
{
|
|
return $"guest-{Random.Shared.Next(100000, 1000000)}";
|
|
}
|
|
}
|
|
}
|