Skip to content

Host API Security

JumpWatch edited this page Apr 25, 2026 · 1 revision

Host API Security

ServerFabric-Host is the control-plane entry point for instance management.

Because of that, its HTTP API should be treated as a sensitive internal service, not a general public web API.

Security layers currently supported

ServerFabric-Host now supports multiple layers of protection:

  • bearer-token authentication
  • signed request authentication
  • replay protection using nonces
  • timestamp window validation
  • temporary IP bans for repeated failed authentication
  • per-route-group rate limiting
  • trusted CIDR handling for internal infrastructure
  • audit logging
  • rotating compressed audit logs

Recommended deployment model

The recommended deployment model is:

  • bind the host to localhost, LAN, VPN, or another private/internal interface
  • do not expose the host directly to the public internet unless you know exactly what you are doing
  • firewall access so only the proxy or trusted infrastructure can reach it
  • use trusted CIDRs for internal container/proxy networks
  • use signed requests once the proxy has been migrated

Authentication modes

The host supports multiple authentication modes.

TOKEN_ONLY

Only bearer token authentication is accepted.

This is the legacy/simple mode.

TOKEN_OR_SIGNED

Signed requests are accepted.
If signed headers are not present, bearer token auth is still accepted.

This is the recommended migration mode.

SIGNED_ONLY

Only signed requests are accepted.
Bearer token auth is ignored.

This is the strongest mode currently supported.


Migration path

Recommended rollout order:

  1. start with TOKEN_ONLY
  2. switch to TOKEN_OR_SIGNED
  3. update the proxy so it sends valid signed requests
  4. verify audit logs show successful signed auth
  5. switch to SIGNED_ONLY

Bearer token authentication

Bearer mode uses:

Authorization: Bearer <token>

This is still supported for compatibility and transition, but it is weaker than signed requests because it does not provide replay protection or tamper detection.


Signed request authentication

Signed request mode adds these headers:

  • X-SFabric-KeyId
  • X-SFabric-Timestamp
  • X-SFabric-Nonce
  • X-SFabric-Body-SHA256
  • X-SFabric-Signature

Header meanings

X-SFabric-KeyId

Identifies which configured key/secret is being used.

Example:

X-SFabric-KeyId: proxy-main

X-SFabric-Timestamp

Unix epoch time in seconds.

Example:

X-SFabric-Timestamp: 1776972012

X-SFabric-Nonce

A unique per-request random nonce, usually a UUID.

X-SFabric-Body-SHA256

SHA-256 hash of the raw request body in lowercase hex.

X-SFabric-Signature

The HMAC-SHA256 signature of the canonical request string, also in lowercase hex.


Canonical signing format

The signed request canonical string is:

METHOD
PATH
TIMESTAMP
NONCE
BODY_SHA256

Joined with newline characters.

Example:

POST
/server/create
1776972012
2b56d7d5-12d0-4a2e-a9e7-5dbe2bdf8a4e
3fd5...abcd

The proxy signs this canonical string using HMAC-SHA256 and the configured shared secret.

The host rebuilds the same canonical string and verifies the signature.


Replay protection

Replay protection uses two checks:

Timestamp window

Requests must be recent enough to fall within the configured clock skew window.

If the request is too old or too far in the future, it is rejected.

Nonce store

Each (keyId, nonce) pair is remembered for a short TTL.

If the same nonce is seen again during that TTL, the request is rejected as a replay.


Trusted CIDRs

Trusted CIDRs are intended for internal infrastructure such as:

  • localhost
  • proxy host IPs
  • Docker/Pterodactyl bridge networks
  • VPN/private subnets

Trusted CIDRs:

  • are still fully authenticated
  • are still fully audited
  • are not auto-banned
  • are not rate-limited in the current implementation

This is useful for internal orchestration traffic that may be noisy but should not trip protection rules.

Important

Trusted CIDRs do not bypass authentication.
They only bypass the firewall-style protections.


Failed-auth bans

The host tracks repeated failed authentication attempts per IP.

If an IP exceeds the configured threshold inside the configured time window, it is temporarily blocked.

This is meant to slow down brute-force or abuse attempts.

Trusted CIDRs are excluded from auto-ban behavior.


Rate limiting

Requests are rate-limited by route group.

Current route groups are:

  • READ
  • CONTROL
  • DANGEROUS

Typical examples

READ

  • /status
  • /templates
  • /version

CONTROL

  • /server/start
  • /server/stop
  • /server/restart
  • /server/command
  • /server/runtime
  • /server/logs
  • /server/stats

DANGEROUS

  • /server/create
  • /server/delete
  • /server/kill

Trusted CIDRs bypass rate limiting in the current implementation.


Audit logging

The host writes an audit log with entries that include:

  • timestamp
  • request ID
  • source IP
  • HTTP method
  • path
  • event
  • detail

This allows you to answer:

  • who called the host
  • from where
  • for what route
  • whether authentication passed
  • what action happened
  • what the result was
  • how long it took

Audit log rotation

The audit log supports rotation and compression.

Current behavior:

  • active log file remains host-audit.log
  • when the active file exceeds the size limit, it is rotated
  • rotated logs are compressed as .gz
  • archive names are date-based, for example:
2026-04-22-1.log.gz
2026-04-22-2.log.gz

This keeps logging useful without allowing the log file to grow forever.


Common audit events

Examples include:

  • request.begin
  • auth.ok
  • auth.failed
  • auth.failed.trusted
  • signed_auth.ok
  • signed_auth.failed
  • security.trusted
  • request.ok
  • request.blocked
  • ip.banned

Route-specific events also exist, such as:

  • instance.create.request
  • instance.start.request
  • instance.stats.request

Time synchronization

Signed request mode depends on time.

If the proxy and host clocks are badly out of sync, valid signed requests may fail with timestamp-related errors.

Make sure your systems have reasonably correct time.


Error behavior

The host now uses structured JSON API errors.

Example:

{
  "ok": false,
  "error": "not_running",
  "message": "Instance is offline. Live stats are unavailable.",
  "requestId": "..."
}

This makes it easier for the proxy and tools to handle errors cleanly.


Example config keys

securityTrustedCidrs=127.0.0.1/32,172.20.0.0/16,10.0.0.0/8
securityAuthMode=TOKEN_OR_SIGNED
securitySignedKeyId=proxy-main
securitySignedSecret=CHANGE_ME_TO_A_LONG_RANDOM_SECRET
securityClockSkewSeconds=30
securityNonceTtlSeconds=300

Recommended current setup

A good current setup is:

  • private bind or private network only
  • trusted CIDRs configured for internal traffic
  • TOKEN_OR_SIGNED during migration
  • then SIGNED_ONLY
  • audit logging enabled
  • rotating compressed logs kept under retention

Clone this wiki locally