Astradial to FusionPBX — Inbound and Outbound Setup Guide¶
A step-by-step guide for connecting a customer FusionPBX (FreeSWITCH) to the Astradial resold Tata SIP trunk. When complete, the customer can receive calls on their allocated DIDs and place PSTN calls, authenticated by IP over a private WireGuard tunnel.
| Audience | Astradial provisioning engineer + the customer's FusionPBX administrator |
| Time | ~45 minutes |
| Model | IP-authenticated peer trunk over WireGuard. No SIP password. |
| Example customer | Skylink — FusionPBX fpbx.skylinkonline.net, tunnel IP 10.30.0.3, DIDs 918065080710 / 918065080711, extension 6000 |
1. Architecture¶
PSTN Customer FusionPBX
| (FreeSWITCH)
v |
Tata SBC --NNI--> Astradial NUC --WireGuard--> astradial-trunk profile
(reseller GW) tunnel (bound to 10.30.0.3)
10.30.0.2 10.30.0.x |
v
Inbound -> Extension
Outbound <- Extension
| Element | Value / role |
|---|---|
| Astradial NUC (reseller gateway) | Terminates the Tata NNI; SIP endpoint on the tunnel is 10.30.0.2:5070 |
| WireGuard tunnel | NUC initiates to the customer's public listener; customer gets a /32 in 10.30.0.0/24 |
| Authentication | Source IP over the tunnel. No username/password. |
| Customer FusionPBX | Runs a dedicated SIP profile bound to the tunnel IP; a gateway, inbound destinations, and an outbound route |
Note. The NUC is a B2BUA. It terminates the customer leg and originates a fresh leg to Tata, so there is no direct IP path between the customer and the carrier. Concurrency is capped per customer (default two channels), and each customer may present only its own DIDs as caller ID.
2. Prerequisites¶
| Requirement | Detail |
|---|---|
| FusionPBX host | Public IPv4, an open inbound UDP port for WireGuard (default 51821) |
| Allocated DIDs | Provided by Astradial (e.g. 918065080710, 918065080711) |
| Tunnel IP | Provided by Astradial (e.g. 10.30.0.3) |
| WireGuard keypair | Generated on the FusionPBX host; send Astradial the public key only |
| A test extension | A registered extension on the production domain (e.g. 6000) |
3. Step 1 — WireGuard tunnel (FusionPBX host)¶
The FusionPBX host is the WireGuard listener; the Astradial NUC dials in.
- Install WireGuard.
- Generate a keypair and send Astradial the public key.
cd /etc/wireguard
wg genkey | tee astradial-trunk.key | wg pubkey > astradial-trunk.pub
cat astradial-trunk.pub # send this to Astradial
- Create
/etc/wireguard/astradial-trunk.conf(replace the keys):
[Interface]
Address = 10.30.0.3/32
ListenPort = 51821
PrivateKey = <contents of astradial-trunk.key>
[Peer]
# Astradial NUC — it initiates the tunnel, so no Endpoint line here
PublicKey = <Astradial NUC public key>
AllowedIPs = 10.30.0.2/32
chmod 600 astradial-trunk.conf
wg-quick up astradial-trunk
systemctl enable wg-quick@astradial-trunk
- Open the WireGuard port in the host firewall.
- Verify once Astradial has added the peer:
wg show astradial-trunk # expect a recent handshake
ping -c3 10.30.0.2 # the Astradial gateway over the tunnel
Checkpoint.
ping 10.30.0.2must succeed before continuing. If it does not, confirm inbound UDP51821is open and that the public key sent to Astradial matches the private key in the conf.
4. Step 2 — SIP profile bound to the tunnel IP¶
FusionPBX's default external profile binds the host's public IP. SIP sourced from that IP is dropped by the tunnel. Create a dedicated profile bound to the tunnel IP 10.30.0.3.
GUI: Advanced → SIP Profiles → copy external → rename to astradial-trunk. Set the following, then Start the profile.
| Setting | Value |
|---|---|
sip-ip | 10.30.0.3 |
rtp-ip | 10.30.0.3 |
ext-sip-ip | 10.30.0.3 |
ext-rtp-ip | 10.30.0.3 |
sip-port | 5060 |
context | public |
auth-calls | false |
apply-inbound-acl | remove / leave empty |
Verify:
fs_cli -x "sofia status" | grep astradial-trunk
# expect: astradial-trunk profile sip:mod_sofia@10.30.0.3:5060 RUNNING
Note.
ext-sip-ipandext-rtp-ipare10.30.0.3(not the public IP) because the tunnel is a direct, un-NATed path.
5. Step 3 — Gateway¶
GUI: Accounts → Gateways → Add.
| Field | Value |
|---|---|
| Gateway | astradial |
| Proxy | 10.30.0.2:5070 |
| Register | False |
| Username / From User | 918065080710 (an allocated DID) |
| Profile | astradial-trunk |
| Context | public |
| Enabled | True |
Important. The From User must be an allocated DID. Left blank, FreeSWITCH puts
FreeSWITCHin the From header and the Astradial gateway rejects the call with403(anti-spoofing).
Verify:
fs_cli -x "sofia status gateway <gateway-uuid>"
# expect: Proxy sip:10.30.0.2:5070, Status UP, From <sip:918065080710@...>
6. Step 4 — Inbound (Destinations)¶
Route each DID to an extension. Use plain digits — no +, no regex.
GUI: switch to the production domain, then Dialplan → Destinations → Add.
| Field | Value |
|---|---|
| Type | Inbound |
| Country Code | (blank) |
| Destination | 918065080710 |
| Context | public |
| Action | Transfer → extension (e.g. 6000) |
| Enabled | True |
Repeat for each DID.
Critical. FusionPBX in
singledialplan mode matches the incoming number against the destination number by exact equality. If the Destination field contains a regex (for example\+?918065080710) or a+, it will never equal the plain digits the trunk delivers, and the call returns404silently. Enter the number exactly as the trunk sends it — plain digits.
Verify (from Astradial, no PSTN call needed):
# On the NUC — simulate an inbound INVITE to the customer:
asterisk -rx "channel originate PJSIP/918065080710@<customer-endpoint> application Echo"
# Expect the FusionPBX response: 100 Trying -> 183 Session Progress -> 200 OK
# A 404 means the Destination number is not plain digits (see Critical note).
7. Step 5 — Outbound (Route)¶
Let extensions dial PSTN through the astradial gateway.
GUI: production domain → Dialplan → Outbound Routes → Add.
| Field | Value |
|---|---|
| Gateway | astradial |
| Dialplan Expression | match your dialling (e.g. Indian mobiles) |
| Caller ID | an allocated DID (918065080710) |
Equivalent dialplan (10-digit sent to the trunk; Astradial formats it for Tata):
<condition field="destination_number" expression="^(?:\+?91|0091|0)?([6-9]\d{9})$">
<action application="set" data="effective_caller_id_number=918065080710"/>
<action application="bridge" data="sofia/gateway/<gateway-uuid>/$1"/>
</condition>
Note. Send the plain 10-digit number to the gateway. The Astradial NUC normalises it to the
0+ 10-digit format the Tata NNI requires. Caller ID is forced to an allocated DID by the gateway's From User, so the trunk accepts it.
8. Step 6 — Extension and softphone¶
The test extension lives on the production domain, so its SIP realm is the domain name (for example skylink.local), not the server hostname.
For a remote softphone (Zoiper or Linphone recommended):
| Field | Value |
|---|---|
| Username | 6000 |
| Password | the extension password |
| Domain / SIP realm | the production domain (e.g. skylink.local) |
| Server / Registrar | the FusionPBX host (public IP or hostname), port 5080 |
| Transport | UDP |
Two host-side requirements for remote registration:
- Resolve a private
.localrealm — add it to the client's hosts file, or use an outbound proxy pointing at the server:
- Allow the client's public IP through the FusionPBX firewall (it uses a per-IP SIP allow-list):
Note. The internal (registration) profile port on this build is
5080, not5060. Confirm withfs_cli -x "sofia status".
9. Verification¶
Inbound. Call a DID from a mobile. The mapped extension should ring with two-way audio.
Outbound. From the extension, dial a PSTN number. The call should connect and the callee should see the allocated DID as caller ID.
Signalling check (from Astradial).
# Watch the customer leg on the NUC while placing a test call:
tcpdump -i wg-reseller host 10.30.0.3 and port 5060
# Inbound success: INVITE -> 100 -> 183 -> 200
# Outbound success: INVITE -> 100 -> 183 -> 200 (From user = allocated DID)
10. Critical points (do not skip)¶
| # | Rule |
|---|---|
| 1 | Inbound Destination number is plain digits — no +, no regex. A regex there gives a silent 404. |
| 2 | The SIP profile must be bound to the tunnel IP (10.30.0.3), not the public IP, or the trunk drops the packets. |
| 3 | The gateway From User must be an allocated DID, or outbound gets 403. |
| 4 | Configure everything on the production domain, not a secondary domain. |
| 5 | The remote softphone realm is the domain name; the registrar port is the internal profile port. |
| 6 | The client IP must be in the FusionPBX SIP allow-list, or REGISTER is dropped before FreeSWITCH. |
11. Reference values (example: Skylink)¶
| Item | Value |
|---|---|
| Tunnel IP (customer) | 10.30.0.3 |
| Astradial gateway (over tunnel) | 10.30.0.2:5070 |
| SIP profile | astradial-trunk (bound 10.30.0.3:5060) |
| Gateway | astradial, From User 918065080710 |
| DIDs | 918065080710, 918065080711 |
| Inbound target | extension 6000 |
| Outbound CID | 918065080710 |
See also: the SIP Trunk Reseller design (NUC side) and the FusionPBX Integration reference (full troubleshooting) in the internal documentation.