Files
sepot/rust/sepot-relay/Cargo.toml
T
Julius Joska 5222c301ff fix(relay): bounded resources for traffic spikes
- Reject envelopes for addresses without a device (404) instead of
  queueing them for 30 days; random addresses were the cheapest way
  to fill the relay's disk.
- Per-sender hourly quota on stored envelopes (count and bytes, 429)
  and a count cap on each recipient's queue next to the byte cap.
- Per-account attachment quota: bytes per day and bytes stored within
  the TTL, kept in memory only (no account-to-blob link is stored).
- Disk watermarks: below a configurable share of free space the relay
  refuses new attachments, then new offline envelopes (507), before
  Postgres runs out of space.
- WebSocket buffers 4 KiB read / unbuffered write: ~16.6 KiB per
  connection instead of ~137 KiB (10 500 connections measured at
  ~180 MiB including the DB pool).
- reqwest with HTTP/2: APNs only accepts HTTP/2, so no iOS wake-up
  could ever be delivered. APNs registration with only a VoIP token
  is stored instead of deleted.
- All limits configurable via environment (limits.rs). Defaults keep
  previous behaviour except registration per IP (50 + 1/10 s, for
  carrier-grade NAT) guarded by a global cap (40/s), separate Tor
  buckets (SEPOT_TOR_PEERS) and a rate limit on opening WebSockets.
  SEPOT_REGISTRATION_PAUSED=1 pauses new registrations (503).
- Envelopes whose encoding exceeds the queue column limit are 400
  before they count against the sender quota.

Rate limiting moves from tower_governor to governor directly, so Tor
and clearnet can use different quotas on the same route.
2026-10-23 11:04:33 +02:00

61 lines
2.1 KiB
TOML

[package]
name = "sepot-relay"
version = "0.1.0"
edition.workspace = true
license.workspace = true
[dependencies]
sepot-proto = { path = "../sepot-proto" }
prost = { workspace = true }
tokio = { workspace = true }
anyhow = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
axum = { version = "0.8", features = ["ws"] }
sqlx = { version = "0.8", default-features = false, features = [
"postgres",
"runtime-tokio",
"tls-rustls",
"chrono",
"migrate",
"macros",
] }
dashmap = "6"
# CIDR match trusted proxy sítí pro anti-abuse klíč (viz net.rs)
ipnet = "2"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
base64 = "0.22"
# TURN údaje pro hovory: coturn ověřuje HMAC-SHA1 (REST schéma use-auth-secret)
hmac = "0.12"
sha1 = "0.10"
hex = "0.4"
chrono = "0.4"
rand = "0.9"
futures-util = "0.3"
# Streaming download příloh z disku (ReaderStream)
tokio-util = { version = "0.7", features = ["io"] }
# Oficiální Signal krypto — POUZE pro roli certifikační autority sealed
# senderu (ServerCertificate/SenderCertificate) a ověření XEdDSA podpisů
# při AUTH. Relay NIKDY nešifruje/nedešifruje zprávy (hloupý relay).
libsignal-protocol = { git = "https://github.com/signalapp/libsignal", tag = "v0.96.4" }
libsignal-core = { git = "https://github.com/signalapp/libsignal", tag = "v0.96.4" }
# Rate limity (token bucket per IP / Tor / globálně, limits.rs)
governor = "0.10"
tower-http = { version = "0.7.0", features = ["timeout"] }
# Push budíčky (UnifiedPush/WebPush = POST na endpoint). rustls, ať build
# zůstane bez OpenSSL (stejně jako sqlx tls-rustls). Bez default featur —
# nechceme native-tls ani zbytečné kodeky. http2: APNs jiný protokol
# nepřijme (HTTP/1.1 spojení odmítne) — bez něj nedorazil žádný iOS budíček.
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "json", "http2"] }
# FCM fast mode: RS256 JWT pro OAuth2 service account flow
jsonwebtoken = "9"
# setrlimit(RLIMIT_NOFILE) při startu — docker dává soft limit 1024
libc = "0.2"
[dev-dependencies]
tokio = { workspace = true, features = ["full"] }