[Home]

Summary:ASTERISK-29190: chan_sip / pjsip: Ability to use ephemeral TCP/TLS port in signalling can improve interop
Reporter:Alexander Traud (traud)Labels:
Date Opened:2020-12-01 04:24:48.000-0600Date Closed:
Priority:MajorRegression?
Status:Open/NewComponents:Channels/chan_sip/TCP-TLS pjproject/pjsip
Versions:16.15.0 18.1.0 Frequency of
Occurrence
Related
Issues:
Environment:Attachments:
Description:Asterisk is a SIP Back-to-Back User Agent ([B2BUA|https://en.wikipedia.org/wiki/Back-to-back_user_agent]). Therefore, Asterisk does not simply proxy but transform requests. When it comes to the transport TCP (and TLS), Asterisk can be both, a TCP client and a TCP server. When Asterisk talks to a remote SIP service provider, Asterisk registers on the SIP layer and plays the role of a TCP client on the IP layer.

Such a client connection has a destination port and source port. Because that connection is kept alive, the source port cannot be re-used. In other words, for each remote registration, a unique TCP source port is required locally. Asterisk solves this by setting the source port to zero. That asks the operating system for a so-called [ephemeral port|https://en.wikipedia.org/wiki/Ephemeral_port].

In the old SIP channel driver chan_sip, this is done in {{sip_prepare_socket(.)}} ← {{__sip_xmit(.)}}:{code} /* Reset tcp source port to zero to let system pick a random one */
ast_sockaddr_set_port(&ca->local_address, 0);{code}
Not sure, where this is done in the current SIP channel driver chan_pjsip.

However, in SIP, the headers {{Via}} and {{Contact}} include the source port. And Asterisk does not write that ephemeral but a static port into those two SIP headers

For a TCP based transport, those SIP headers can be ignored because the response is sent on the same connection as the request ([source| http://mailarchive.ietf.org/arch/msg/sip/pUyEVLppGsSKOfk479ft-Llv8Kg/]). In other words, the existing connection is re-used, and the port in those SIP headers does not matter.

However, services exist which do not follow this rule. Actually, Asterisk as a server does not follow this. In chan_sip, {{nat=force_rport}} must be set. In chan_pjsip, {{rewrite_contact=yes}}, see ASTERISK-29189.

Consequently, for such services, the port on the SIP layer (especially the one in the SIP header {{Contact}}) has to match the port on the IP layer, the ephemeral port created by the operating system.

Because I do not have a service with that problem -- all my services ignore the port in the SIP header {{Contact}} -- I do not continue from here.

However, I looked into chan_sip: With that, the source port is only known to the file descriptor of the TCP client connection ({{sip_pvt→sip_socket→fd}}). Asterisk never asks the operating system for the port. Consequently, the solution is not that easy. One approach might be {{ast_ouraddrfor(.)}} ← {{ast_sip_ouraddrfor(.)}}. There, an expensive TCP connection is started, just to get the source address = ‘us’. Instead of closing that TCP client connection, its file descriptor could be retained for later. Because that descriptor would not change, its source port is available when the SIP headers are built, not after building.
Comments:By: Asterisk Team (asteriskteam) 2020-12-01 04:24:49.072-0600

Thanks for creating a report! The issue has entered the triage process. That means the issue will wait in this status until a Bug Marshal has an opportunity to review the issue. Once the issue has been reviewed you will receive comments regarding the next steps towards resolution. Please note that log messages and other files should not be sent to the Sangoma Asterisk Team unless explicitly asked for. All files should be placed on this issue in a sanitized fashion as needed.

A good first step is for you to review the [Asterisk Issue Guidelines|https://wiki.asterisk.org/wiki/display/AST/Asterisk+Issue+Guidelines] if you haven't already. The guidelines detail what is expected from an Asterisk issue report.

Then, if you are submitting a patch, please review the [Patch Contribution Process|https://wiki.asterisk.org/wiki/display/AST/Patch+Contribution+Process].

Please note that once your issue enters an open state it has been accepted. As Asterisk is an open source project there is no guarantee or timeframe on when your issue will be looked into. If you need expedient resolution you will need to find and pay a suitable developer. Asking for an update on your issue will not yield any progress on it and will not result in a response. All updates are posted to the issue when they occur.

Please note that by submitting data, code, or documentation to Sangoma through JIRA, you accept the Terms of Use present at [https://www.asterisk.org/terms-of-use/|https://www.asterisk.org/terms-of-use/].

By: Kevin Harwell (kharwell) 2020-12-03 15:29:30.695-0600

For _chan_pjsip_ are you saying there is a bug when setting {{rewrite_contact=yes}}, and it does not use the established TCP port when rewriting?

If so can you give an example scenario? For instance, is the expectation for it to use the established TCP port in the Via and Contact headers in replies, outgoing Invites, etc...?

By: Alexander Traud (traud) 2020-12-04 04:56:06.180-0600

The issue is not related to {{rewrite_contact}}. That was just an example for affected services (and how _they_ have to workaround it, right now).

Here, I am about Asterisk as the TLS client, when connected to a remote VoIP/SIP provider. In that case, both chan_sip and chan_pjsip use an ephemeral port on the TCP/IP layer. Great. However, both channel drivers state not that ephemeral port but a complete different one on the SIP layer.

By: Joshua C. Colp (jcolp) 2020-12-04 05:14:12.105-0600

Is there language from the SIP RFC that you've found which states this behavior? As far as I'm aware there is nothing that states you have to use the ephemeral port, provided the port given accepts incoming connections so the remote side can connect back. Within PJSIP we require a TLS transport to exist that can accept incoming connections, and that is the port placed in it. The remote server may choose to reuse the existing connection even without the ephemeral port present but that's not required within the RFC. There are also additional RFCs for connection reuse and such, but those require both client and server support and we don't support them.

By: Alexander Traud (traud) 2020-12-04 08:28:25.187-0600

bq. provided the port given accepts incoming connections

That is the problem. If I do not control the firewall, which is a common scenario in GSM/UMTS/LTE setups here in Europe -- the provider placed a firewall for me -- I cannot open the pjsip.conf {{bind}} port. Consequently, I am not reachable for any incoming transaction (like an INVITE) except the remote service goes for the already existing TCP connection.

Even worse:
Let us assume that port accepts incoming connections, I have a TLS server enabled (required in chan_pjsip, optional in chan_sip).
Let us assume that port is the same on the outside, no NAT (for example with IPv6).
Let us assume that port is never blocked, no firewall.
Then, my upstream VoIP/SIP provider, when he does not use the already existing TLS connection, has to
a) ignore my TLS certificate or
b) know my TLS certificate or


By: Joshua C. Colp (jcolp) 2020-12-04 08:33:41.478-0600

Okay, so your issue is not as a result of the RFC but based on user experience. It's not a bug that we're not doing it as we're doing what the RFC states so such functionality would need to be configurable, and there is no guarantee that the remote server would reuse the connection even if the ephemeral port is present in the signalling.

By: Michael Maier (micha) 2021-03-19 15:12:43.806-0500

I think it is fixed by ASTERISK-29241.