--- id: vessel-voip name: Vessel VoIP troubleshooting description: >- Deep procedural guide for GeneseasX VoIP — SIP registration, one-way audio, RTP path, IAX trunks, and Asterisk NAT on ship stacks. priority: 90 rule_ids: - one-way-audio - no-registration - outbound-trunk-failure - asterisk-health match: keywords: - voip - sip - pjsip - rtp - registration - one-way - one way - trunk - iax - dialplan - codec - yealink - phone - dial tone - no audio - asterisk --- # Vessel VoIP stack ## Layer model (bottom → top) | Layer | Component | Typical symptoms | |-------|-----------|------------------| | 1 | pfSense VM | Blocked SIP/RTP, wrong NAT, missing pass on phone VLAN | | 2 | Docker VM (`shipPortal`) | Container down, wrong published ports | | 3 | Asterisk container | Registration, SDP, codec, dialplan | | 4 | Phones / FortiGate | Yealink NAT quirks, trunk via wrong gateway | **Topology is vessel-specific.** Golden-lab reference (confirm live): | Role | Typical IP / alias | |------|---------------------| | pfSense Management | `10.20.30.1` (`vtnet4`) | | shipPortal / Docker VM | `10.20.30.222` | | Business VLAN | `10.0.100.0/24` (`vtnet3`) | | CREW VLAN | `192.168.100.0/24` (`vtnet2`) | Interface map (verify on device): `vtnet0`=WAN1, `vtnet1`=WAN2, `vtnet2`=CREW, `vtnet3`=Business, `vtnet4`=Management. ## Symptom → start here | Symptom | First layer | Then | |---------|-------------|------| | Phone won't register | pfSense — SIP NAT + pass rules on phone VLAN | Asterisk — `pjsip show registrations` | | One-way audio | pfSense — UDP 10000-10029 pass toward shipPortal | Asterisk — `local_net`, `external_media_address` | | Trunk / dial tone down | Asterisk — PJSIP/IAX peers | pfSense — outbound NAT if media leaves WAN | | Codec mismatch | Asterisk — allowed codecs vs trunk | Not pfSense unless blocked | ## One-way audio playbook (proven order) 1. **Which direction is silent?** Remote can't hear phone → phone→Asterisk RTP likely blocked. Phone can't hear remote → Asterisk→phone or return path. 2. **pfSense filter.log** — blocked flows from phone to `shipPortal:100xx` on Business (`vtnet3`)? 3. **Pass rule** — `pass udp` phone VLAN → shipPortal ports `10000-10029`. 4. **Outbound NAT** — RTP SNAT to correct segment IP (e.g. phone VLAN VIP `192.168.0.254`) when hairpin involved. 5. **Asterisk** — `local_net` must include phone subnet AND VoIP subnet (`10.20.30.0/24`). `external_media_address` / `external_signaling_address` = reachable Asterisk IP. 6. **Live verify** — RTP RX/TX counters during call; both directions should increment. ## Registration playbook - Phones typically register via **pfSense SIP NAT redirect** (e.g. `192.168.0.254:5060` → Asterisk), not directly to Asterisk IP in phone config. - Yealink red flags: SIP server = pfSense VIP with NAT keepalive on but rport off. - Asterisk: failing `qualify` on endpoint = path/NAT problem, not credentials. - Check: port-forward UDP 5060, matching pass rule, `pjsip show registrations`, `pjsip show contacts`. ## Outbound trunk / IAX - IAX2 uses UDP **4569** — confirm pfSense pass + outbound NAT if crossing WAN. - Dialplan: `_7XXXX` patterns may strip prefix — verify dial string matches trunk expectation. - Codec: trunk may require ulaw while endpoint negotiates opus — check `iax2 show peer` / PJSIP allow list. - Congestion = route/codec/dialplan, not firewall, when peer shows OK but calls fail. ## Evidence to capture - pfSense rule tracker IDs, filter.log lines for blocked RTP/SIP - Asterisk CLI: endpoint config, channel stats, `core show channels` - **Config baseline drift** — task report includes `asterisk_config_baseline` when GeneseasX Asterisk is diagnosed; fix any **DRIFT** on `local_net`, RTP range, dialplan before chasing firewall - Do not propose firewall writes without backup — see pfsense-change-safe skill ## During investigation - Read before write on pfSense. - Cross-check NAT rules with their associated filter rules. - Build on project memory hits — do not repeat ruled-out causes from prior tasks.