From ed5b2b8daa92d46074ef85a3a21d40896b8bc75f Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 21 Jul 2026 22:04:15 +0000 Subject: [PATCH] docs: add PSTN calling (VoIP.ms) planning notes Captures the toll-fraud / prepaid-cap research and decisions from a design discussion (provider: VoIP.ms, US-only calling for now) so implementation can be picked up in a future session without re-deriving the background. Nothing implemented yet. --- docs/pstn-calling-voipms-plan.md | 87 ++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 docs/pstn-calling-voipms-plan.md diff --git a/docs/pstn-calling-voipms-plan.md b/docs/pstn-calling-voipms-plan.md new file mode 100644 index 0000000..47cc74c --- /dev/null +++ b/docs/pstn-calling-voipms-plan.md @@ -0,0 +1,87 @@ +# PSTN Calling via VoIP.ms — Planning Notes + +Research and decisions from a design discussion, saved here so the work can +be picked up in a fresh chat without re-deriving the background. **Nothing +has been implemented yet** — this is prep for a future `services/*.sh` +addition on top of `asterisk-digital-ocean`. + +## Decision so far +- **Provider: VoIP.ms.** Chosen for its prepaid-balance model: turn off + auto-recharge in the account's Finances settings and outbound calls simply + fail once the balance hits $0 — that's the toll-fraud backstop if the + droplet's Asterisk (`asterisk-digital-ocean`) is ever compromised. This + behavior wasn't verified against a live account — confirm the + auto-recharge toggle still works this way at sign-up time, since billing + UX can change. +- **Scope: US calling only, for now.** No international, no premium-rate + destinations. Enforce this twice — once via whatever dial-plan/prefix + VoIP.ms requires for US routing, and again independently in Asterisk's own + dialplan (see below), so a compromised extension can't reach anything + outside the US even if the trunk itself would technically allow more later. + +## Why this matters (toll fraud) +A compromised Asterisk box can dial premium-rate or international numbers +that cost real money fast (some destinations run several $/min) before +anyone notices. Two independent layers matter more than either alone: +1. **Trunk-side cap** — prepaid balance, auto-recharge off. Limits total + possible loss to whatever the balance is topped up to, but a live + compromise could still burn through that balance in minutes if nothing + else restricts what can be dialed. +2. **Dialplan-side restriction** — Asterisk should refuse to route calls + outside the US/NANP pattern at all, regardless of what the trunk allows. + This is the first line of defense and should exist independent of the + trunk's own capabilities. + +## What it takes technically (asterisk-digital-ocean) +- A PJSIP trunk to VoIP.ms: `endpoint` / `aor` / `auth` / `identify` + sections in the pjsip config, using either IP authentication or SIP + registration — VoIP.ms supports both. IP auth is simpler for a droplet + (it has a static IP already) and avoids storing a SIP password in the + config at all — worth confirming with VoIP.ms which they actually + recommend before choosing. +- An outbound dialplan route matching US numbers only, e.g. `_1NXXNXXXXX` + (11-digit NANP with leading 1) or `_NXXNXXXXX`, depending on how numbers + get dialed from the existing extensions, routed to the VoIP.ms trunk. No + catch-all `_X.` pattern — an explicit NANP pattern is itself a hard block + on non-US destinations at the dialplan level. +- VoIP.ms-specific setup that isn't scriptable (user does this manually): + create the account, decide whether a DID is needed (this research was + outbound-only — inbound PSTN wasn't discussed/decided), pick a VoIP.ms + POP/server (affects the trunk hostname), fund the prepaid balance, turn + off auto-recharge. +- Defense-in-depth to design alongside the trunk (not yet designed): + - Per-extension concurrent-call cap in the dialplan (`GROUP()` / + `GROUP_COUNT()`) so one compromised extension can't open dozens of + simultaneous outbound legs at once. + - A simple outbound call-count/spend alert — could live in the existing + `security-dashboard` service (see `services/security-dashboard.sh`) or + as a separate CDR-based check. Not designed yet. + - Worth being explicit that CrowdSec's existing `asterisk_bf` / + `asterisk_user_enum` scenarios (see `services/crowdsec.sh`) cover + registration brute-force, which is a *different* threat model from a + legitimately-registered extension being used for toll fraud — nobody + should assume CrowdSec alone already covers this. + +## Provider landscape (for reference — not chosen) +- **SIP.US** — also prepaid, flat per-channel rate, built-in fraud + detection. Considered, not chosen. +- Several providers (Nextiva, IDT Express) advertise AI/ML-based fraud + monitoring as a second layer on top of normal billing — an extra net, not + a substitute for a hard prepaid ceiling. +- Most providers don't market an explicit "spending cap" feature — the + prepaid-balance + auto-recharge-off pattern is the de facto mechanism + across the space, VoIP.ms included. + +## Open items for whoever picks this up next +1. Decide: new `services/voipms-trunk.sh`, or an optional trunk section + added directly to `services/asterisk-digital-ocean.sh`? Leaning toward a + separate service file so trunk config isn't forced on installs that + don't want PSTN calling, matching this repo's one-feature-per-file + convention (see CLAUDE.md). +2. IP auth vs. registration — confirm which VoIP.ms recommends for a single + fixed-IP droplet. +3. Exact NANP dial pattern(s) and any prefix-stripping VoIP.ms requires. +4. Whether inbound (a DID) is wanted at all, or outbound-only for now — not + discussed yet. +5. Design the concurrent-call cap and any spend/volume alerting mentioned + above.