[Home]

Summary:ASTERISK-08614: nat=no is not RFC 3261 compliant regarding sending responses
Reporter:mikma (mikma)Labels:
Date Opened:2007-01-19 14:32:41.000-0600Date Closed:2009-06-26 15:47:00
Priority:MinorRegression?No
Status:Closed/CompleteComponents:Channels/chan_sip/General
Versions:Frequency of
Occurrence
Related
Issues:
causesASTERISK-26438 [patch] chan_sip: auto_force_rport: No NAT = No Symmetric Response.
Environment:Attachments:( 0) 8855.patch
Description:A note should be added to sip.conf.sample that using nat=no makes Asterisk send responses to the address in the "sent-by" value instead of using the source address of the request. This doesn't comply with RFC 3261 section 18.2.1 and 18.2.2.


  RFC 3261 section 18.2.1 Receiving Requests

  If the host portion of the "sent-by" parameter
  contains a domain name, or if it contains an IP address that differs
  from the packet source address, the server MUST add a "received"
  parameter to that Via header field value.  This parameter MUST
  contain the source address from which the packet was received.  This
  is to assist the server transport layer in sending the response,
  since it must be sent to the source IP address from which the request
  came.


  RFC 3261 section 18.2.2 Sending Responses.

        Otherwise (for unreliable unicast transports), if the top Via
        has a "received" parameter, the response MUST be sent to the
        address in the "received" parameter
Comments:By: Anthony LaMantia (alamantia) 2007-01-19 14:55:42.000-0600

mikma, do you have a sip dump that shows the rfc3261 non-compliant session in progress?



By: mikma (mikma) 2007-01-19 16:16:46.000-0600

To demonstrate I have configured Twinkle with 192.168.17.2 as the public IP. A registration request from Twinkle results in the following response, which you can see isn't fully RFC 3261 compliant since the "received" parameter in the top Via isn't used when Asterisk sends the response.

<<--- SIP read from 192.168.0.2:5066 --->
REGISTER sip:xxx SIP/2.0
Via: SIP/2.0/UDP 192.168.17.2:5066;rport;branch=z9hG4bKfmqfzjch
Max-Forwards: 70
To: <sip:2001@xxx>
From: <sip:2001@xxx>;tag=vtsij
Call-ID: isuvadwkuvesfoe@192.168.0.4
CSeq: 707 REGISTER
Contact: <sip:2001@192.168.17.2:5066>;expires=3600
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, PRACK, REFER, NOTIFY, SUBSCRIBE, INFO
User-Agent: Twinkle/0.9
Content-Length: 0

<------------->
--- (11 headers 0 lines) ---
Sending to 192.168.0.2 : 5066 (NAT)

<--- Transmitting (no NAT) to 192.168.17.2:5066 --->
SIP/2.0 100 Trying
Via: SIP/2.0/UDP 192.168.17.2:5066;branch=z9hG4bKfmqfzjch;received=192.168.0.2;rport=5066
From: <sip:2001@xxx>;tag=vtsij
To: <sip:2001@xxx>
Call-ID: isuvadwkuvesfoe@192.168.0.4
CSeq: 707 REGISTER
User-Agent: Asterisk PBX
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY
Supported: replaces
Contact: <sip:2001@192.168.0.2:5068>
Content-Length: 0
<------------>
<--- Transmitting (no NAT) to 192.168.17.2:5066 --->
SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 192.168.17.2:5066;branch=z9hG4bKfmqfzjch;received=192.168.0.2;rport=5066
From: <sip:2001@xxx>;tag=vtsij
To: <sip:2001@xxx>;tag=as36f7f55e
Call-ID: isuvadwkuvesfoe@192.168.0.4
CSeq: 707 REGISTER
User-Agent: Asterisk PBX
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY
Supported: replaces
WWW-Authenticate: Digest algorithm=MD5, realm="asterisk", nonce="1c8b76e7"
Content-Length: 0



By: Tilghman Lesher (tilghman) 2007-01-19 18:50:53.000-0600

Um, I'm reading the section you quoted and I'm looking at your trace, and it seems to me that it is complying 100% with the section you quoted:

1) It contains an address other than the address other than the address from which it received the packet.

2) It therefore adds a "received" parameter.

3) And it sends the packet back to the IP in the received parameter.

How is this not in compliance?

By: mikma (mikma) 2007-01-20 02:51:15.000-0600

The log says "Sending to 192.168.0.2 : 5066 (NAT)", but the responses are actually transmitted to 192.168.17.2:5066, not to 192.168.0.2:5066.

By: Olle Johansson (oej) 2007-01-24 02:52:56.000-0600

Mikma, thank again for a good report.

What would happen if we changed the behaviour so that nat=no did what the RFC says, simply send back SIP to the address we get it from? Anything that would break, as far as you know?

By: mikma (mikma) 2007-01-24 03:43:02.000-0600

No, I can't think of anything it would break.

By: Olle Johansson (oej) 2007-01-25 14:47:55.000-0600

Neither can I. Thanks for your feedback!

By: Olle Johansson (oej) 2007-05-15 11:24:44

Moving this to the top of the list of "todo's" for trunk.

By: Ronald Chan (loloski) 2007-09-07 22:06:01

Any news here ? thanks

By: Olle Johansson (oej) 2007-12-16 03:19:57.000-0600

re-categorizing this bug report so that it belongs to chan_sip again.

By: Mark Michelson (mmichelson) 2008-04-03 11:30:47

I noticed this issue and wrote a quick patch that might take care of the issue. The way this patch works is that when it attempts to determine where to send the packet, it uses the same rules as we use for NAT if the packet is a SIP response. In other words, we send the packet back to the address from which we received the packet.

I ran a few quick tests to be sure I didn't introduce any terrible regressions, but I'd appreciate further testing to be certain that this fixes the issue reported.

By: Kevin P. Fleming (kpfleming) 2008-07-22 18:34:17

I fear there are much deeper issues here than have been described, and that the patches offered on this issue and on ASTERISK-12326 don't really address the larger problems.

Let's start with a simple question: if RFC3261 says we always have to respond to the IP/port we received the request from, regardless of what appears in the Via header that the request contained, then (a) we don't need to bother doing a DNS resolution on the hostname in the Via header since we'll never respond there and (b) exactly what does 'nat=no' mean in this context? (For the moment let's only worry about the SIP signaling and not the media layers... let's sort out one thing at a time). If 'nat=no' was supposed to turn off the RFC compliant behavior, I don't see why we should offer that option at all. If 'nat=no' was supposed to do something else, then I can't figure out what it is.

Based on my reading of the code today (for Asterisk 1.4):

1) we always add a 'received' tag to the Via header, regardless of what NAT mode has been set (even nat=never)

2) if RFC3581 is enabled (nat=no or nat=yes), we add an 'rport' tag to our outgoing Via headers, and we add an 'rport' tag to our copy of the incoming Via header whether it was requested or not. The RFC3581 setting *never* affects where we send signaling or media. If we see an incoming 'rport' tag in the topmost Via header, we attempt to enable RFC3581 processing for that dialog, but that behavior is broken, because it will later be overriden by the user/peer NAT settings.

3) There is also 'ROUTE' NAT mode (nat=route or nat=yes), which is the mode that is used to trigger responding to the source IP/port instead of the Via header IP/port. I don't understand why this mode is useful, if that behavior is required by the RFC.

4) There are some parts of request processing that use the global NAT settings, when later parts use the settings found for the peer or user in question. I haven't yet determined if the results of those early steps are *always* overwritten (re-performed) by later steps, but if not, then we could easily get non-obvious behavior. The trace in this bug is one example; when check_via() is called (which outputs the "Sending to.." line, the global NAT settings are in place. Later, when register_verify() has found a peer to process the registration for, the peer's NAT settings are in place, which is why the "Transmitting (no NAT)..." line has a different destination address (and says "no NAT"). This is at a minimum very confusing, because if the admin has configured everything with 'nat=rfc3581' then turns on debugging, all the debug messages will say "Transmitting (no NAT)...".

I can't remember ever seeing a system configured with anything but 'nat=yes', and I suspect that is because nobody really understands these modes and changing it from 'yes' breaks connectivity under unexpected circumstances, even when a NAT may not be involved.

So let's try to answer three questions first:

1) Is there ever a case where we will send our response for a SIP request to an address/port *OTHER* than the one we received it from?

2) Is RFC3581 *PURELY* informational? If so, it should be broken out into a separate configuration option or made clearer that that is the case. Based on comments in the code, the only reason it was added was to help some buggy phone firmware in the distant past that broke if it received an 'rport' tag in our Via header.

3) Is there any real need to *DISABLE* NAT mode, and if so, what exactly are we disabling?

By: Kevin P. Fleming (kpfleming) 2008-07-22 18:39:15

Adding you as a monitor to issue ASTERISK-8614, since your issue(s) were duplicates of this one, and I want to ensure everyone involved in all three issues is working on the same issue. Thanks.

By: Kevin P. Fleming (kpfleming) 2008-07-22 18:40:44

This is one of our oldest outstanding issues and I've agreed to try to bring it to resolution, but I'd like to make sure you can stay involved so I'm adding you to the monitor list.

By: klaus3000 (klaus3000) 2008-07-23 01:20:47

Hi Kevin!

The standard is a little bit more complicated:

RFC 3261 defines that responses are sent to (source IP address of the request):(port indicated in via header). If this fails (e.g. ICMP error message is received, TCP connection breaks down), the client may retry using (IP address indicated in Via header, if domainname follow RFC 3263):(port indicated in via header). The received= parameter is actually only needed when the UA proxies requests stateless, to know the source IP of the request when relaying the response, nevertheless adding will not harm and is indeed very useful for debugging at the client side.

RFC 3851 defines that: received= must be added to Via header (although this would not be needed as Asterisk is not a proxy it might be useful for the SIP client to detect the public IP address). Further, it defines the replies are sent to (source IP address of the request):(source port of the request).

Thus reagarding SIP signalling. As Asterisk uses symmetric SIP signaling it should not be a problem to add rport always to any outgoing SIP request, regardless of nat=.... (if for some reason the rport should be ommited IMO there should be a separate config option as there is a difference between NAT traversal of peers/users and its own NAT traversal).

For incoming requests IMO Asterisk should always be standard conform. This means even if nat=no route according to the standards: no rport->srcIP:viaPort, rport->srcIP:srcPort

And with nat=yes, IMO Asterisk should behave like rport is always present (thus send back symmetrically)

Regarding RTP: IMO with nat=no Asterisk should send media to the IP:port announced in the SDP. With nat=yes Asterisk should send media to the IP:port from which it received the audio.

Any currently I do not see a reason for nat=never or nat=rfc3851.

By: Iñaki Baz Castillo (ibc) 2008-07-23 03:23:47

Hi,  about Klaus comment:

If a reply to srcIP:viaPort fails then the UAS should perform steps in RFC 3261 (DNS NAPTR, SRV...) for the host indicated in Via. Anyway, I think this step could be omited and I also know about other SIP stacks omiting this step. Sincerely I think it makes no sense to receive a request via address A and send the response via address B because a network error sending it to address A. It's completely safe to destroy the transaction server when the response reports a network error (at least for a stateful proxy or for a UAS). Of course this is a personal opinion, but I think SIP design is too much "exotic" and anti-realistic in this point.

I don't see problem in adding always "rport=SrcPort" to the Via header (so "received" MUST also be added according to RFC 3581). In fact, in OpenSer proxy there is an option "force_rport" and it's safe to use (we assume all the clientes use symmetric SIP signalling).

I agree when Klaus says that "nat=never" shouldn't exist. So we just have 2 things:
- RFC 3581 ("rport" for signalling).
- Comedia mode (Asterisk sending RTP to IP:port from which it received the audio).


Well, then "nat" options could be:

- nat=force_rport => So "rport" (and "received") is always added (even if not present) to the request, and response is sent to "received:rport" according to RFC 3581.

- nat=yes => Includes "nat=force_rport" and RTP is sent to the IP:port from which audio is received (comedia mode).

- nat=no => Don't force "rport" (so just use it if present in the original request) and don't use comedia mode.


I don't want to imagine the purpose of "nat=route".

By: Iñaki Baz Castillo (ibc) 2008-07-23 03:39:15

Replies to question of Kpflemming:


> 1) Is there ever a case where we will send our response for a SIP request to
> an address/port *OTHER* than the one we received it from?

* In UDP:
Yes, the case in which a client is behind NAT (so received port is different than the indicated in "Via") and the peer is not configured with "nat=force_rport/rfc3581" or "nat=yes". In this case the response would be sent to received IP address and port in original "Via" (so it will fail).

* In TCP:
No, in TCP a response MUST be *always* sent using the same connection. In fact, AFAIK using "received" and/or "rport" in TCP is competely useless (but mandatory). If the response can't be sent using the same connection then RFC 3261 should be performed for the "sent-by" host indicated in the original "Via" (I think this is competely useless and IMHO I wouldn't implement replies failover at all).



> 2) Is RFC3581 *PURELY* informational? If so, it should be broken out into a
> separate configuration option or made clearer that that is the case. Based
> on comments in the code, the only reason it was added was to help some buggy
> phone firmware in the distant past that broke if it received an 'rport' tag
> in our Via header.

"rport" is mandatory if the client includes it in its request. We can also force (add) it ot the request and it shouldn't generate problems in the client (that MUST ignore "Via" parameters that doesn't understand).


> 3) Is there any real need to *DISABLE* NAT mode, and if so, what exactly are
> we disabling?

I don't think so. You could use more complex options as:
- force_rport=yes/no
- use_comedia_mode=yes/no
but I think they are more doifficult to understand.

By: Olle Johansson (oej) 2008-07-23 04:16:27

One sidenote, but related. In many cases I want to force symmetrip RTP (Comedia mode) but still follow SIP signalling. I'm communicating with a SIP proxy and don't want to force Symmetric SIP, but want to force Symmetric RTP due to the actual media endpoint being behind NAT.

In chan_sip2, many years ago, I had a separate setting for this.

By: Iñaki Baz Castillo (ibc) 2008-07-23 04:34:13

Then we need something as:

- nat=no (default) : Use "rport" just if indicated by client and don't use comedia.

- nat=force_rport : Add "rport" to request even if not present.

- nat=comedia : Symmetric RTP (but don't force "rport").

- nat=yes : force_rport + comedia


This would allow your specific case and wouldn't break current behaviour.

By: klaus3000 (klaus3000) 2008-07-23 17:55:48

@ibc:

> I don't see problem in adding always "rport=SrcPort" to the Via header (so "received" MUST also be added according to RFC 3581). In fact, in OpenSer proxy there is an option "force_rport" and it's safe to use (we assume all the clientes use symmetric SIP signalling).

Always adding rport is NOT save. E.g. Cisco AS5300 gateways are SIP asymmetric. Also some Cisco phones behind Cisco PIX work in asymmetric mode.

@olle&ibc: Yes, symmetric RTP with asymmetric SIP makes sense and IMO the suggestions from ibc or OK.

By: Iñaki Baz Castillo (ibc) 2008-07-24 03:13:20

Thanks for the point, I didn't know about SIP asymmetric clients. So then an option to enable "comedia" mode but not to use "rport" is needed, this is what I suggested as:
 nat=comedia : Symmetric RTP (but don't force "rport")

By: klaus3000 (klaus3000) 2008-12-23 06:11:06.000-0600

will this ever be fixed in 1.4?

By: Olle Johansson (oej) 2009-01-12 09:09:37.000-0600

I think it's too large a change for 1.4 to fix all of it. But that's only my personal opinion.

By: Joshua C. Colp (jcolp) 2009-04-27 15:52:24

I am currently working on this issue in a branch and once I have something I will add a note here!

By: Joshua C. Colp (jcolp) 2009-04-28 08:32:29

I have created a branch at http://svn.digium.com/svn/asterisk/team/file/issue8855 which implements a separate configuration option, symmetric_rtp, to explicitly enable or disable symmetric RTP support regardless of the nat option. All existing options work as they previously did. This should allow the exact behavior that was finally decided upon here.

By: Olle Johansson (oej) 2009-04-29 02:15:05

Well, that's not the original issue, which is much bigger. But an improvement nevertheless.

By: Joshua C. Colp (jcolp) 2009-05-14 11:27:00

I believe I have completed everything now. The nat option has been reworked so that it behaves as discussed. No disables rport unless the remote side has it. force_rport forces it on without symmetric RTP. Yes forces it on and also enables symmetric RTP.

By: Leif Madsen (lmadsen) 2009-06-16 13:44:32

This issue is still in need of testing by the reporter. Please provide feedback if you can! Thanks!

By: klaus3000 (klaus3000) 2009-06-18 08:38:23

Hi!

SIP_PAGE2_SYMMETRICRTP flag can now be set/unset with nat= and symmetricrtp= option. IMO this is bad as it may cause unpredictable behavior. Either symmetricrtp should be completely integrated into nat=... or, if two options are used, nat= should only care about SIP and symmetricrtp should only care about RTP.

For compatibility reasons IMO it might be better to use nat= only, as suggested by ibc.

I tested the branch:  can not simulate asym RTP, but at least the reply is now always sent to the "received" IP.

By: Digium Subversion (svnbot) 2009-06-26 15:19:50

Repository: asterisk
Revision: 203735

U   trunk/CHANGES
U   trunk/channels/chan_sip.c
U   trunk/configs/sip.conf.sample

------------------------------------------------------------------------
r203735 | file | 2009-06-26 15:19:49 -0500 (Fri, 26 Jun 2009) | 6 lines

Fix the 'nat' option to actually do RFC3581 as expected and extend the configurable values for finer control.

(closes issue ASTERISK-8614)
Reported by: mikma
Tested by: klaus3000, file

------------------------------------------------------------------------

http://svn.digium.com/view/asterisk?view=rev&revision=203735

By: Digium Subversion (svnbot) 2009-06-26 15:46:56

Repository: asterisk
Revision: 203741

_U  branches/1.6.2/

------------------------------------------------------------------------
r203741 | file | 2009-06-26 15:46:55 -0500 (Fri, 26 Jun 2009) | 12 lines

Blocked revisions 203735 via svnmerge

........
 r203735 | file | 2009-06-26 17:19:49 -0300 (Fri, 26 Jun 2009) | 6 lines
 
 Fix the 'nat' option to actually do RFC3581 as expected and extend the configurable values for finer control.
 
 (closes issue ASTERISK-8614)
 Reported by: mikma
 Tested by: klaus3000, file
........

------------------------------------------------------------------------

http://svn.digium.com/view/asterisk?view=rev&revision=203741