[OpenSIPS-Users] force_tcp_alias default behavior seems wrong – should not use port from Via-header

Bogdan-Andrei Iancu bogdan at opensips.org
Mon Sep 28 23:27:04 CEST 2015


Hi Jonas,

Thanks for the additional information. Indeed, what you say makes sense, 
but before making a call (and it is not a SIP call :) ), I need a fresh 
mind tomorrow morning - to go again through the scenario, through the 
RFC and all the logic aspects here.

Best regards,

Bogdan-Andrei Iancu
OpenSIPS Founder and Developer
http://www.opensips-solutions.com

On 28.09.2015 17:51, Jonas Borjesson wrote:
> Hi,
>
> Sorry, I thought I did buy no, the request-uri will NOT be
> "sip:public_ip:5061", if it was it would not find the correct
> connection since it is not stored under that key. Due to
> "fix_nated_contact", as part of the REGISTER flow, the Contact of that
> REGISTER will now be "sip:public_ip:public_port" and as such, when the
> call comes back to opensips, that is what the request uri will be.
> Hence, the fix_nated_contact and force_tcp_alias are now doing the
> exact same thing, which makes sense. I.e., they are changing "things"
> to match that of the actual connection and not like today where
> fix_nated_contact will match the incoming connection but
> force_tcp_alias will not (because it grabs the port from the
> Via-header instead of the actual port of the connection - also compare
> with rport usage, which does the correct thing).
>
> Also, if you keep the force_tcp_alias as is, every client behind the
> same NAT would be broken because only the very first client that
> established the connection would ever be able to receive a call
> (assuming they port the same port in their Via-header). Even if you
> then tried to fix things by using fix_nated_contact then no clients
> would work since none of them would have a stored connection under the
> "fixed" contact and as such, all attempts to connect to those clients
> would fail (of course, UDP would work but then again force_tcp_alias
> is obviously not used for UDP). At the end of the day, this is kind of
> a poor-mans version of SIP outbound (rfc5626) I guess...
>
> /Jonas
>
>
> On Mon, Sep 28, 2015 at 4:14 AM, Bogdan-Andrei Iancu
> <bogdan at opensips.org> wrote:
>> Hi Jonas,
>>
>> One question (which remained unanswered): when the call comes back to
>> opensips (from main server to Alice, let's say), what it the the RURI? Is
>> "sip:public_ip:5061" (as per contact in REGISTER) ? If you use
>> fix_nated_contact() at REGISTER time, does the RURI in INVITE changes to
>> "sip:public_ip:NAT_port" ?
>>
>> I'm asking as the the whole aliasing mechanism is not network level only,
>> but it is tightly linked to the SIP level too, to how the SIP entities do
>> map over the TCP connections.
>>
>> Best regards,
>>
>> Bogdan-Andrei Iancu
>> OpenSIPS Founder and Developer
>> http://www.opensips-solutions.com
>>
>> On 24.09.2015 17:52, Jonas Borjesson wrote:
>>> Hi,
>>>
>>> The exact details is as follows:
>>>
>>> The client will establish a TLS connection, which is terminated by
>>> opensips. The client will then send an OPTIONS and from the 200
>>> response will learn about its external, to opensips, IP and port
>>> through the received and rport from the Via-header. It will then issue
>>> a REGISTER using the same connection and populate that REGISTER with
>>> the information it learned from the OPTIONS. I agree that this is not
>>> really per any spec but in general, this is really the very same as
>>> issuing an initial REGISTER (which it will get wrong), examine the Via
>>> in that response and re-register with the correct Contact based off of
>>> that info. Now, this particular client has currently two issues, which
>>> I'm having them fix:
>>>
>>> 1. They “forgot” to use the rport value in the Via from the response
>>> to the OPTIONS as the port in their Contact of the REGISTER. Hence,
>>> they essentially will register with Contact: <public_ip>:5061 but this
>>> can be easily fixed by opensips fix_nated_contact and, I'm arguing, is
>>> a separate issue from connection management.
>>>
>>> 2. The client doesn't end up using the rport in the new Via, which
>>> then effectively becomes 5061 and that is in fact how I found this
>>> issue. In general though, I think the Via in this case actually
>>> shouldn't be the external facing IP and port but rather the actual
>>> private ip and port of where the connection is “attached” to on
>>> Alice's client since because of “symmetric response routing” this is
>>> not an issue (the use of rport etc) and in general, you can't really
>>> trust the information in there anyway (which is why we have received
>>> and rport in the first place).
>>>
>>> However, even though the client has some issues I think that the
>>> connection management of opensips is a separate problem but of course,
>>> if the Client gets the Contact wrong, and it isn't being fixed by
>>> opensips through e.g. fix_nated_contact then the “key” used to lookup
>>> the connection for any future requests going to that client will of
>>> course be wrong and the request will fail. Anyway, I believe that
>>> since we are dealing with connections, the key for that connection
>>> must be calculated off of the information representing that
>>> connection, which a layer 7 protocol, such as SIP, does not. Hence,
>>> they key should be local IP + local port + remote IP + remote port +
>>> transport and this is irrespective of what it says in the SIP message
>>> itself. Based on that philosophy, I changed the force_tcp_alias to
>>> grab the port from the packet instead (port=msg->rcv.src_port) and
>>> that will correctly store the connection under the correct key, which
>>> then truly represents that connection and this will address the issue.
>>> Again though, the Contact of the REGISTER must of course match that
>>> but at least now, all connections will be stored correctly in the
>>> internal map of opensips.
>>>
>>> Does that make sense?
>>>
>>> /Jonas
>>>
>>>
>>> On Thu, Sep 24, 2015 at 12:51 AM, Bogdan-Andrei Iancu
>>> <bogdan at opensips.org> wrote:
>>>> Hi Jonas,
>>>>
>>>> A quick question first about the Contact hdr used by Alice and Bob
>>>> devices
>>>> during registration. From your explanation, I understand that STUN
>>>> correctly
>>>> discover the IP address of the NAT, but you haven't mentioned anything on
>>>> the port. So, I guess the contact populated in the Register is a mixing
>>>> of
>>>> the public NAT address and the port of the local box. Is this correct ?
>>>>
>>>> I'm asking, as before exploring the issue about the "force_tcp_alias"
>>>> (which, I agree, has some problems), I want to understand how the
>>>> end-user
>>>> (bob or alice) are to be addressed on the OpenSIPS proxy - like INVITE to
>>>> sip:bob at NAT_IP:local_port ?
>>>>
>>>> Regards,
>>>>
>>>> Bogdan-Andrei Iancu
>>>> OpenSIPS Founder and Developer
>>>> http://www.opensips-solutions.com
>>>>
>>>>
>>>> On 24.09.2015 03:34, Jonas Borjesson wrote:
>>>>> Hi all,
>>>>>
>>>>> I have the following problem (sorry for somewhat long explanation,
>>>>> want to get it right on the first try :-):
>>>>>
>>>>> * Alice is behind a NAT and registers with whatever.com and has
>>>>> through STUN figured out her public ip, which will go into the Contact
>>>>> of the REGISTER.
>>>>> * Bob is behind the same NAT as Alice and registers with whatever.com
>>>>> and has through STUN figured out his public ip, which will go into the
>>>>> Contact of the REGISTER.
>>>>> * Carol is another user that calls bob at whatever.com.
>>>>> * opensips is acting as a pure transaction stateful proxy for all SIP
>>>>> traffic (including REGISTER so I'm not using opensips as a registrar)
>>>>> * opensips config is using force_tcp_alias() so that the connection
>>>>> can be re-used at a later point.
>>>>> * Alice's and Bob's clients are sending keep-alive traffic (double
>>>>> crlf) to keep the connection up.
>>>>>
>>>>> In the above scenario, because of the way force_tcp_alias works, Bob
>>>>> will NOT get the call but rather Alice for the following reason:
>>>>>
>>>>> When Alice's client registers and the force_tcp_alias is executed, a
>>>>> mapping between Alice's public ip + the port found in the top-most
>>>>> Via-header and her incoming TCP/TLS connection will be created. When
>>>>> Bob registers, which he does after Alice, he too will create mapping
>>>>> between his connection and the public_ip + port in Via. Of course,
>>>>> since Alice and Bob are behind the same NAT they will have the same
>>>>> IP, hence “half” the key is shared between Alice & Bob at all times.
>>>>> If Alice & Bob also puts the same port as each other in the top-most
>>>>> Via-header, they now share the exact same key for the connection
>>>>> whereby opensips will complain with the following message:
>>>>> “tcpconn_add_alias: possible port hijack attempt”. Hence, when Carol
>>>>> later on calls Bob, which then will be “resolved” to
>>>>> bob at public_ip:some_port (by a location aware proxy behind opensips)
>>>>> and subsequently proxied to Bob via the opensips node, it will find a
>>>>> live connection and re-use that, which ends up at Alice.
>>>>>
>>>>> So, looking at the code (action.c):
>>>>>
>>>>> case FORCE_TCP_ALIAS_T:
>>>>>>>>>>        if (a->elem[0].type==NOSUBTYPE) {
>>>>>            port=msg->via1->port;
>>>>>        ...
>>>>>
>>>>> which clearly grabs the port out of the Via. By doing this there is a
>>>>> chance that clients will happen to have the same local port and you
>>>>> will run into the scenario above. Even worse, for those clients that
>>>>> do not set the port on the Via to the actual port of the connection
>>>>> (which clients do) they will end up with the default for the
>>>>> transport, which in my case was 5061 for TLS. Malicious users behind
>>>>> the same corporate NAT could take advantage of this by setting up many
>>>>> connections to effectively “steal” other peoples phone calls, granted,
>>>>> they may have to setup several thousands of connections to be sure so
>>>>> perhaps not practical.
>>>>>
>>>>> So, suggested solutions:
>>>>>
>>>>> Suggestion 1: I do not see any value with using the port from the via
>>>>> but rather always use the port from the src packet itself since that
>>>>> is what you really want anyway. That will avoid everything above.
>>>>>
>>>>> Suggestion 2: Allow for script variables to force_tcp_alias so you
>>>>> could pass whatever you want, which in my case always would be the
>>>>> source port of the incoming packet. Currently, the config-file grammar
>>>>> only allows for number but could be easily extended to allow for other
>>>>> types as well.
>>>>>
>>>>> Both solutions are fairly trivial where solution 1 seems to be the
>>>>> correct default behavior but solution 2 has the most flexibility and
>>>>> also wouldn't mess with any existing deployments in the wild, even
>>>>> though I'm guessing they suffer from the same problem as described but
>>>>> may not have been discovered yet.
>>>>>
>>>>> Comments/thoughts? If people agree, I will issue a pull request
>>>>> against latest 1.11. Also, the behavior is the same for at least
>>>>> versions 1.8 and 1.11. I am assuming it’s also the same for all
>>>>> versions in between as well, and possibly earlier versions but I
>>>>> haven't checked.
>>>>>
>>>>> Thanks,
>>>>>
>>>>> /Jonas
>>>>>
>>>>> _______________________________________________
>>>>> Users mailing list
>>>>> Users at lists.opensips.org
>>>>> http://lists.opensips.org/cgi-bin/mailman/listinfo/users
>>>>




More information about the Users mailing list