-
-
Notifications
You must be signed in to change notification settings - Fork 4
Hardening
This page covers Stratum controls that protect the server from bad or abusive client behavior.
- Config model:
sources/VintagestoryLib/Vintagestory.Server/StratumConfig.cs(hardening-related sections) - Runtime guards:
sources/VintagestoryLib/Vintagestory.Server/StratumPacketLimiter.cs,sources/VintagestoryLib/Vintagestory.Server/StratumPacketBackPressure.cs,sources/VintagestoryLib/Vintagestory.Server/StratumBlockBreakGuard.cs,sources/VintagestoryLib/Vintagestory.Server/StratumLoginProtection.cs,sources/VintagestoryLib/Vintagestory.Server/StratumPlayerPrivacy.cs - Hook/wiring:
sources/VintagestoryLib/Vintagestory.Server/StratumRuntime.cs,sources/VintagestoryLib/Vintagestory.Server/ServerSystemStratum.cs, relatedpatches/entries
The canonical config model is StratumConfig and runtime wiring starts in StratumRuntime and ServerSystemStratum.
PacketLimits is handled by StratumRuntime.PacketLimiter (StratumPacketLimiter).
These settings cap packet traffic per client and per packet type, with optional violation-based disconnects.
stratum.default.json:
"PacketLimits": {
"Enabled": true,
"DropViolations": true,
"LogViolations": false,
"KickViolations": true,
"KickInvalidPackets": true,
"KickOversizedCustomPackets": true,
"KickAfterViolations": 8,
"KickMessage": "Disconnected by Stratum packet protection",
"WindowSeconds": 5,
"DefaultMaxPackets": 300,
"MovementMaxPackets": 420,
"InventoryMaxPackets": 90,
"BlockInteractionMaxPackets": 140,
"EntityInteractionMaxPackets": 140,
"HandInteractionMaxPackets": 90,
"CustomPacketMaxPackets": 120,
"CustomPacketMaxBytes": 262144
}/stratum packets returns the limiter report through:
return TextCommandResult.Success(StratumRuntime.PacketLimiter.BuildReport() + "\n" + StratumRuntime.BlockBreakGuard.BuildReport());PacketBackPressure is handled by StratumRuntime.PacketBackPressure (StratumPacketBackPressure).
Back-pressure is separate from packet limits:
- limits classify/rate-limit abusive input
- back-pressure caps main-thread packet drain work per tick
public bool Enabled { get; set; } = true;
public int MaxMillisecondsPerTick { get; set; } = 25;
public int MaxPacketsPerClientPerTick { get; set; } = 32;
public int MaxQueueDepthPerClient { get; set; } = 2000;
public bool KickOnQueueOverflow { get; set; } = true;See deep dive: Feature: Packet Back-Pressure.
BlockBreakGuards is handled by StratumRuntime.BlockBreakGuard (StratumBlockBreakGuard) and called from block break handling in ServerSystemBlockSimulation.
Config shape:
public bool Enabled { get; set; } = true;
public bool RequireServerSelection { get; set; } = false;
public bool DropViolations { get; set; } = true;
public bool LogViolations { get; set; } = false;
public bool KickViolations { get; set; } = false;
public int KickAfterViolations { get; set; } = 12;
public int ViolationWindowSeconds { get; set; } = 20;
public float RequiredProgressRatio { get; set; } = 0.5f;
public float GraceSeconds { get; set; } = 0.5f;
public float MinimumTrackedBreakSeconds { get; set; } = 0.5f;
public float PartialProgressRetentionSeconds { get; set; } = 8f;
public float MaxRememberedProgressRatio { get; set; } = 0.95f;
public int MaxRememberedPartialBreaksPerClient { get; set; } = 24;Fast or trivial breaks can be accepted without tracked-progress checks:
if (resistance <= 0f || expectedBreakSeconds <= Math.Max(0f, config.MinimumTrackedBreakSeconds))
{
return true;
}Partial progress is remembered for a short window after the player stops mining or changes target. This covers normal vanilla partial block damage without accepting stale progress forever.
Violation window and kick threshold are enforced by per-client rolling state:
state.RegisterViolation(now, Math.Max(1, config.ViolationWindowSeconds));
shouldKick = config.KickViolations && config.KickAfterViolations > 0 && state.ViolationsInWindow >= config.KickAfterViolations;See deep dive: Feature: Block Break Guard.
ClientModPolicy is implemented in StratumRuntime.BuildClientModWhitelist(...).
When both Enabled and StrictWhitelist are true, Stratum builds a whitelist from:
- server universal mods (optional)
- server config whitelist entries
- explicit
AllowModIds
"ClientModPolicy": {
"Enabled": true,
"StrictWhitelist": true,
"IncludeServerUniversalMods": true,
"AllowModIds": [],
"LogPolicyOnStartup": true
}LoginProtection is implemented in StratumLoginProtection.
On join, Stratum starts the engine invulnerability activity timer and tracks per-player protection state:
player.Entity.SetActivityRunning("invulnerable", (int)durationMs);Protection ends on timeout or configured cancel conditions (movement and/or fire/lava).
"LoginProtection": {
"Enabled": true,
"ProtectionSeconds": 5,
"CancelOnHorizontalMove": true,
"MoveThresholdBlocks": 0.5,
"CancelInFireOrLava": true,
"AnnounceOnStart": true,
"AnnounceOnEnd": true
}PlayerPrivacy is implemented in StratumPlayerPrivacy and connected through PlayerMapDisclosureHook.
At startup it can also push world config overrides such as render distance:
server.api.World.Config.SetFloat("mapPlayerRenderDistance", cfg.MaxBroadcastDistanceBlocks);And disclosure decisions are made in AllowMapPinDisclosure(...) and CoordinateSnap(...).
"PlayerPrivacy": {
"Enabled": false,
"HideMapPins": true,
"AllowGroupMapVisibility": true,
"CoordinateSnapBlocks": 0,
"MaxBroadcastDistanceBlocks": -1
}ServerSystemStratum.OnBeginRunGame calls StratumPlayerPrivacy.Initialize(server).
For commands/chat/theme/nametags/identity, see Commands and Identity.
For runtime tuning that affects load rather than hardening policy, see Performance.