What you're seeing
NOTICE[2213]: res_pjsip/pjsip_distributor.c:...: Request 'INVITE' from '<sip:[email protected]>' failed for '10.0.0.10:5060' (callid: 5f1c...) - No matching endpoint foundOther symptoms: phones register (200 OK from Kamailio) but calls from the PBX never ring them; every call shows the same caller ID; audio dies after a transfer or hold.
Likely causes
Most common first.
- Asterisk doesn't recognise Kamailio as an endpoint. PJSIP matches incoming requests to endpoints by From user or by source IP. Calls relayed by Kamailio come from Kamailio's IP with the phone's From user, so Asterisk needs one endpoint for Kamailio, matched by IP with a type=identify section.
- Two registrars. Pick one. With Kamailio as the registrar, Asterisk sends calls for extensions to Kamailio, which finds the phone with lookup("location"). Forwarding REGISTERs to Asterisk as well, or pointing some phones at Asterisk directly, gives two conflicting pictures of where a phone is.
- Kamailio isn't staying in the dialog. Without record_route() on the initial INVITE, Asterisk sends BYE and re-INVITEs straight to the phone's Contact, which is unreachable behind NAT. Calls then can't be hung up or transferred.
- Asterisk re-INVITEs media directly between endpoints. With direct_media enabled, Asterisk re-INVITEs the two legs to send RTP to each other, using addresses only Kamailio/rtpengine can reach. Set direct_media=no on the Kamailio endpoint.
- Caller identity isn't passed. Asterisk sees every call as coming from the Kamailio endpoint. Have Kamailio assert the authenticated user in P-Asserted-Identity (removing any the client sent), and set trust_id_inbound=yes on that endpoint.
How to fix
1. One PJSIP endpoint for Kamailio, matched by IP
[kamailio]
type=endpoint
context=from-kamailio
disallow=all
allow=ulaw,alaw
aors=kamailio
direct_media=no
rtp_symmetric=yes
trust_id_inbound=yes
send_pai=yes
[kamailio]
type=aor
contact=sip:10.0.0.10:5060
[kamailio]
type=identify
endpoint=kamailio
match=10.0.0.10On FreePBX, don't edit pjsip.conf, because the GUI rewrites it. Create a PJSIP trunk to Kamailio's IP with no registration and no authentication, and set the matching options on the trunk.
2. Route phones → Asterisk and Asterisk → phones
After the usual REQINIT, WITHINDLG, AUTH and REGISTRAR routes. route[AUTH] must return early for $si == ASTERISK_IP, so the PBX isn't challenged:
#!define ASTERISK_IP "10.0.0.20"
#!define ASTERISK_URI "sip:10.0.0.20:5060"
request_route {
# ... REQINIT, NATDETECT, CANCEL/retransmission handling, WITHINDLG ...
if (is_method("INVITE|SUBSCRIBE")) {
record_route();
}
# ... AUTH, REGISTRAR ...
if ($si == ASTERISK_IP) {
# from the PBX: deliver to the registered phone
if (!lookup("location")) {
send_reply("404", "Not Found");
exit;
}
route(RELAY);
exit;
}
# from phones: everything goes to the PBX, with a trusted identity
remove_hf("P-Asserted-Identity");
append_hf("P-Asserted-Identity: <sip:$fU@$fd>\r\n");
$du = ASTERISK_URI;
route(RELAY);
exit;
}In Asterisk, dial extensions through the Kamailio endpoint, for example Dial(PJSIP/${EXTEN}@kamailio). The Request-URI then targets Kamailio and lookup() finds the phone.
3. Anchor media once
Let rtpengine on Kamailio handle NAT for the phones and keep Asterisk media in the same network with direct_media=no. If audio still goes one way, work through one-way audio with rtpengine.