Custom PJSIP Trunk

Hello everyone

We have an application that accepts and sends INVITEs from/to specified IPs via SIP URIs on port 5064.

I created a ‘TestAppTrunk’ PJSIP Trunk:

Then I went added the below to pjsip.transports_custom.conf

[testapp-udp]
type=transport
protocol=udp
bind=0.0.0.0:5064
external_media_address=xx.xxx.xxx.xx
external_signaling_address=xx.xxx.xxx.xx
allow_reload=no
tos=cs3
cos=3
local_net=10.128.14.0/24
local_net=192.168.1.0/24

And then the below to pjsip.endpoint_custom_post.conf

[TestAppTrunk](+)
transport=testapp-udp

I can confirm that the Trunk is now using the custom transport

yplab*CLI> pjsip show endpoint TestAppTrunk

 Endpoint:  <Endpoint/CID.....................................>  <State.....>  <Channels.>
    I/OAuth:  <AuthId/UserName...........................................................>
        Aor:  <Aor............................................>  <MaxContact>
      Contact:  <Aor/ContactUri..........................> <Hash....> <Status> <RTT(ms)..>
  Transport:  <TransportId........>  <Type>  <cos>  <tos>  <BindAddress..................>
   Identify:  <Identify/Endpoint.........................................................>
        Match:  <criteria.........................>
    Channel:  <ChannelId......................................>  <State.....>  <Time.....>
        Exten: <DialedExten...........>  CLCID: <ConnectedLineCID.......>
==========================================================================================

 Endpoint:  TestAppTrunk                                           Unavailable   0 of inf
        Aor:  TestAppTrunk                                         0
      Contact:  TestAppTrunk/sip:10.128.14.109:5064          871ada327c Unavail         nan
  Transport:  testapp-udp                udp      3     96  0.0.0.0:5064
   Identify:  TestAppTrunk/TestAppTrunk
        Match: 10.128.14.109/32
        Match: 192.168.1.224/32
        Match: xx.xxx.xx.xx/32
        Match: 10.128.14.201/32

The application can successfully send an INVITE to the PBX by calling sip:[email protected]:5064

However, I have two issues.

Issue #1: Outgoing calls

It seems that if the PJSIP endpoint does not have an active/online AOR, then it will not even try to call the URI. Reading here: Redirect a call to SIP URI when endpoint is unavailable - #3 by billsimon it seems that calling the PJSIP Trunk directly should work (although I can’t confirm the actual setting since the pictures aren’t loading in that post) but when I try, it fails.

yplab*CLI> channel originate PJSIP/55412@TestAppTrunk application echo
[2023-02-15 06:27:13] ERROR[10921]: res_pjsip.c:849 ast_sip_create_dialog_uac: Endpoint 'TestAppTrunk': Could not create dialog to invalid URI 'TestAppTrunk'.  Is endpoint registered and reachable?
[2023-02-15 06:27:13] ERROR[10921]: chan_pjsip.c:2672 request: Failed to create outgoing session to endpoint 'TestAppTrunk'

What am I missing?

Issue #2: Incoming calls to :5060

Even tho we set the Trunk to use a custom UDP transport which listens on :5064, Asterisk will accept calls on both :5064 and :5060 (the original PJSIP UDP/5060). Is there any way we can restrict that it should only be able to accept calls on :5064?
Meaning, this Trunk has the IP of the Application and listens on 5064. If the Application sends a call to :5060, why isn’t it treated as an anonymous/SIP Guest call?

Appreciate any pointers

Thanks

I don’t believe there is any way of restricting type=identify to a particular transport.

I think you need to disable qualify.

[root@yplab ~]# cat /etc/asterisk/pjsip.identify.conf
<snip>
...
[TestAppTrunk]
type=identify
endpoint=TestAppTrunk
match=10.128.14.109/32,192.168.1.224/32,xx.xxx.xxx.xx/32,10.128.14.201/32

It seems that it does have a field to apply to a specific endpoint, but it doesn’t seem to be working?

The sample file also seems to be indicating that you can do that:

Setting qualify frequency to 0 fixed this. Thank you!

The endpoint isn’t an input to the match, it is an output. If the identify matches one of the address ranges, the request is assumed to have come from the named endpoint.

@krzykat As far as the listening ports. You’re listening on 5060 and 5064 for chan_pjsip so it doesn’t matter which port they use, pjsip is listening on it.

As for sending to qualify, is the contact actually listening on 5064?

I assume this is a mistake?

Correct. My understanding was, that you can specify a port/transport to a Trunk/Endpoint, and that Trunk/Endpoint will only accept traffic according to the transport configuration/rules.

That app doesn’t accept OPTIONS. I haven’t tested yet the actual application, but once I disabled qualify Asterisk is actually calling the URI.

Asterisk doesn’t require that OPTIONS be accepted, just that the SIP protocol is honoured, which means that OPTIONS must produce a response, even if it is Method not allowed.

I think you problem in understanding the endpoint parameter in type=identify is that the examples use a degenerate naming scheme, which looks as though identify and endpoint are tied together by name, whereas, I believe, the identify name is not relevant to Asterisk, as long as it is unique.

Holy crap, yeah. Didn’t even catch that.

No, that will be the transport the endpoint uses for requests it generates. Notifies, etc. You want to only match traffic from a remote source by IP and port you need to do that with match as such match=10.1.1.1:5064/32 and that will accept traffic from 10.1.1.1:5064 if they send from 10.1.1.1:5060 it will ignore it.

So what’s the point of specifying a Trunk port if Asterisk anyway honors the port specified in the Transport config

That is true if the source address will always be 10.1.1.1:5064.

I may be misunderstanding the concept of using multiple listening ports using the same protocol. But I imagined that this would allow you, for example, to create multiple Trunks with the same vendor/IP and each Trunk communicates on a different port. Apparently, if I remove all the match IPs, since the SIP server IP is in the Trunk, Asterisk will accept any traffic from this IP as long as they match a transport.

Thanks for your time, Tom and David!

Do not conflate what FreePBX does on the backend with how Asterisk actually functions. FreePBX is taking the server IP and automatically adding a match for it. If you were to do this in just Asterisk, it wouldn’t accept the incoming traffic unless you made an identify section yourself to match that IP.

The transport port is the local port (for requests). Ports in contacts are those on the remote end.

Got it. So in other words: If there is an identify field like this

[TestAppTrunk]
type=identify
endpoint=TestAppTrunk
match=192.168.10.4/32

Asterisk will send ‘ANY’ traffic from this IP, regardless of the source or destination port to this Trunk.

Chan_pjsip matches any traffic from this IP as long as it hits an IP/port bound to chan_pjsip. It will also accept traffic from that source IP regardless of source port. More importantly, it will match the first match it finds meaning if you have endpoints that match against the same IPs, the first loaded into memory will match.

This is also based on the identification order, which default is; ip, username, anonymous along with auth_name, header options. For example, on my main setup the order is header, username, ip which means the endpoints will only match against a specific custom SIP header I send from the proxy between the servers and users. If it can’t find a matching header, match a username, can’t find a matching username, match by IP.

Love getting blamed for things I didn’t even do. Just ask my wife :blush:

This topic was automatically closed 31 days after the last reply. New replies are no longer allowed.