158 lines
6.8 KiB
Markdown
158 lines
6.8 KiB
Markdown
# AstroCom SIP Bridge — Design Notes
|
|
|
|
This directory contains a set of Asterisk configuration files that act as a
|
|
**protocol bridge** between IAX2 (used by AstroCom) and SIP (used by
|
|
downstream, non-Asterisk phone systems such as FreeSWITCH, 3CX, Cisco
|
|
UCM, or any generic SIP PBX).
|
|
|
|
---
|
|
|
|
## Files
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `iax.conf` | IAX2 peers — one per bridge, pointing at AstroCom |
|
|
| `pjsip.conf` | PJSIP endpoints — one triple (endpoint/auth/aor) per bridge |
|
|
| `extensions.conf` | Dialplan — contexts that wire IAX↔PJSIP for each bridge |
|
|
|
|
---
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌─────────────────────────────────┐
|
|
│ AstroCom Platform │
|
|
│ (IAX2 server, routes DB) │
|
|
└──────────┬──────────────────────-┘
|
|
│ IAX2 (port 4569)
|
|
┌───────────────┼────────────────┐
|
|
│ │ │
|
|
IAX2 peer IAX2 peer IAX2 peer
|
|
bridge1-astrocom bridge2-astrocom bridgeN-astrocom
|
|
│ │ │
|
|
┌───────┴───────────────┴────────────────┴──────┐
|
|
│ Bridge Server │
|
|
│ (this Asterisk instance) │
|
|
│ │
|
|
│ [bridge1-from-astrocom] [bridge1-from-pbx] │
|
|
│ [bridge2-from-astrocom] [bridge2-from-pbx] │
|
|
│ [bridgeN-from-astrocom] [bridgeN-from-pbx] │
|
|
└───────┬───────────────┬────────────────┬──────┘
|
|
│ │ │
|
|
SIP peer SIP peer SIP peer
|
|
bridge1-pbx bridge2-pbx bridgeN-pbx
|
|
│ │ │
|
|
▼ ▼ ▼
|
|
PBX / System 1 PBX / System 2 PBX / System N
|
|
```
|
|
|
|
### Inbound call (AstroCom → PBX)
|
|
|
|
1. AstroCom looks up the dialled number in its `routes` table and finds
|
|
the bridge server's IP (`routes.server`) and port (`routes.port`).
|
|
2. AstroCom dials over IAX2 using the shared secret (`routes.secret`)
|
|
and delivers the call to the context named in `routes.auth`
|
|
(e.g. `bridge1-from-astrocom`).
|
|
3. The bridge's dialplan receives the call in `[bridge1-from-astrocom]`
|
|
and dials `SIP/bridge1-pbx/<EXTEN>`. Because the PBX has already
|
|
registered (`host=dynamic`), Asterisk knows the current contact URI
|
|
and sends the INVITE directly to it.
|
|
|
|
### Outbound call (PBX → AstroCom)
|
|
|
|
1. The downstream PBX has registered to this server as `bridge1-pbx`.
|
|
It sends a SIP INVITE for the target number.
|
|
2. `sip.conf` authenticates the REGISTER/INVITE against `secret` and
|
|
lands the call in context `bridge1-from-pbx`.
|
|
3. The dialplan CURLs the AstroCom routing API:
|
|
`GET /api/v1/route/<apiKey>/<ANI>/<number>`
|
|
4. The API returns either `"local"` (callee is on the same PBX — route
|
|
back via `SIP/bridge1-pbx/<exten>`) or a full
|
|
`IAX2/<auth>:<secret>@<host>:<port>/<number>` URI which is dialled
|
|
verbatim.
|
|
|
|
---
|
|
|
|
## AstroCom Database Requirements
|
|
|
|
For each bridge you must create one row in the `routes` table:
|
|
|
|
| Column | Value |
|
|
|--------|-------|
|
|
| `server` | Bridge server's public IP |
|
|
| `port` | `4569` (IAX2) |
|
|
| `auth` | `bridgeN-from-astrocom` (must match context name) |
|
|
| `secret` | The shared IAX2 secret (`BRIDGEN_IAX_SECRET`) |
|
|
| `block_start` | First number in this bridge's number block |
|
|
| `block_length` | Size of the block (default 9999) |
|
|
| `apiKey` | Auto-generated by AstroCom on creation |
|
|
|
|
---
|
|
|
|
## Isolation Model
|
|
|
|
Each bridge is **completely isolated** by default:
|
|
|
|
- IAX2 peers use separate contexts (`bridge1-from-astrocom`, etc.)
|
|
- PJSIP endpoints use separate contexts (`bridge1-from-pbx`, etc.)
|
|
- No context includes or jumps to another bridge's context
|
|
- The `[default]` context drops all unmatched calls
|
|
|
|
### Calling between bridges
|
|
|
|
Calls between Bridge-1 and Bridge-2 work through AstroCom's normal
|
|
routing — Bridge-1's PBX dials a number, it travels to AstroCom via
|
|
IAX2, AstroCom routes it to Bridge-2's context, and it arrives at
|
|
Bridge-2's PBX via PJSIP. **No special config is needed for this.**
|
|
|
|
If you want **direct PJSIP** bridging (bypassing AstroCom for inter-bridge
|
|
calls), see the commented-out section at the bottom of `extensions.conf`.
|
|
|
|
---
|
|
|
|
## Adding a New Bridge
|
|
|
|
1. **`iax.conf`** — Copy the `[bridge1-from-astrocom]` block, rename it to
|
|
`[bridgeN-from-astrocom]`, and set a new `secret` and `context`.
|
|
|
|
2. **`pjsip.conf`** — Copy the three stanzas for `bridge1-pbx`, rename them
|
|
to `bridgeN-pbx` / `bridgeN-pbx-auth`, set a new `password`, and update
|
|
`context`. The downstream PBX must be configured to register with:
|
|
- **Registrar**: `sip:<bridge server IP>:5060`
|
|
- **Username**: `bridgeN-pbx`
|
|
- **Password**: the `password` value in `[bridgeN-pbx-auth]`
|
|
|
|
3. **`extensions.conf`** — Copy both the `[bridge1-from-astrocom]` and
|
|
`[bridge1-from-pbx]` context blocks, rename them to
|
|
`[bridgeN-from-astrocom]` / `[bridgeN-from-pbx]`, and update the
|
|
`Dial()` targets and global variable names.
|
|
Add `BRIDGEN_APIKEY` and `BRIDGEN_EXCHANGE` to `globals.conf`.
|
|
|
|
4. **AstroCom** — Create the route via the admin panel or API with
|
|
`auth = bridgeN-from-astrocom` and the matching `secret`.
|
|
|
|
5. Reload Asterisk:
|
|
```
|
|
asterisk -rx "pjsip reload"
|
|
asterisk -rx "iax2 reload"
|
|
asterisk -rx "dialplan reload"
|
|
```
|
|
|
|
---
|
|
|
|
## Notes
|
|
|
|
- **Codecs**: `ulaw`, `alaw`, and `g729` are negotiated; adjust per your
|
|
network and licensing constraints.
|
|
- **NAT**: If a downstream PBX is behind NAT, set `direct_media=no` (already
|
|
in the template) and add `local_net` / `external_signaling_address` /
|
|
`external_media_address` to `[bridge-transport]` in `pjsip.conf`.
|
|
- **No `register =>`** for IAX2: IP updates use `tools/astrocom_dynamic_ip.sh`
|
|
or the `/api/v1/user/update` API endpoint — not IAX2 registration.
|
|
- **Security**: Each bridge's IAX2 secret should be a long random string
|
|
(AstroCom generates one via `crypto.randomBytes(15).toString('hex')`
|
|
if none is specified during route creation).
|
|
- **`sip.conf`**: The old `chan_sip` config is superseded by `pjsip.conf`.
|
|
Ensure `chan_sip` is not loaded (`noload => chan_sip.so` in `modules.conf`)
|
|
to avoid both modules fighting over port 5060.
|