Subject: RE: [Ietf-behave] NAT Mapping refresh vs NAT filter refresh

From: Pyda Srisuresh <[email-masked]>
Date: Sun, 17 Jul 2005 15:05:15 -0700 (PDT)

--- Saikat Guha <saikat@xxxxxxxxxxxxxx> wrote:

> On Fri, 2005-07-15 at 06:56 -0700, Pyda Srisuresh wrote:
> > In this scenario,
> > the NAPT will have created 4 resources as follows:
> > 
> > a) Port Binding-1:: (X:x, N:Nx)
> > b) NAT Session-1 :: ((X:x->Y1:y1) Xlates to (N:Nx->Y1:y1) using Port
> Binding-1)
> > c) NAT Session-2 :: ((X:x->Y2:y2) Xlates to (N:Nx->Y2:y2) using Port
> Binding-1)
> > d) NAT Session-3 :: ((X:x->Y3:y3) Xlates to (N:Nx->Y3:y3) using Port
> Binding-1)
> 
> This is implementation dependent. I can think of an implementation where
> a) is not created as a separate object but rather inferred from b-d.
> Note that each of b-d have the full information given by a). What data
> structures/organization a NAT uses is, no doubt, up to the vendor.
> 

[suresh] The above illustrates the relationship between Binding and the
associated NAT Sessions, not implementation. The relationship  holds true, no
matter what the implementation is. 

If you can think of implemenations that would not create a) as seperate object,
but infer that from b) through d) - That is fine. I would be curious to know
how you would do this. Do feel free to send this to me on a private e-mail.
Specific implementation ideas may not be of interest to the list.

> 
> > SO, I think, you will agree, there ought to be two requirements, one
> addressing
> > the refresh of "NAT Session" and another addressing the refresh of
> "Bindings". 
> 
> Yes. That has always been the case. 

[suresh] Sounds like we have an agreement here. That is a start. 

>                                      The "Bindings (behave-gen)"
> addresses the same issue as "Mappings (behave-udp)".   "NAT Session
> (behave-gen)" addresses the same issues as "NAT Filter Refresh".
>

[suresh] This seems to be where the disconnect is. Let me for a moment go with
your above assertion. 

a) If "NAT Session", is same is NAT filter, why is there not an idle timeout
not specificed for NAT filter refresh in section 5.2? 

The reality is that the filtering characteristic of a NAT device is to simply
permit packets belonging to only the NAT Sessions it supports in either
direction. The filtering behavior is the same for TCP or UDP and is an inherent
characteristic of a NAT Session, but not the only characteristic. Address/Port
translation is another key charactristic of a NAT Session. 

The filtering behaviors specified in section 5.1 are specific only to UDP and
not aplicable to TCP. This is because what is different with UDP sessions is
that a NAT UDP Session may have wild-card match for external hosts - say
(X:x->Y2:*) for an Address retricted Cone NAT or (X:x-. *:*) for a full Cone
NAt in item c) above. Whereas, TCP is inherently point-to-point and exhibits
just the Address and Port Dependent filtering. 

Bootom line, refresh timing is not restricted to just the filtering behavior.
The refresh timing is applicable to the whole NAT Session. The filtering
behavior is evident so long as a NAT Session is alive. This was why, we
recently agreed to remove section 5.2 from the draft. 

b. If Binding is same as Mapping (in behave-udp), the mapping refresh timer
specified in REQ-5 doesnt make sense. In the above example, say there was no
traffic from X:x to Y2:y2 for 10 mins, but there is continuous ongoing traffic
from X:x to Y1:y1 and X:x to Y3:y3. According to your interpretation, the
Binding (i.e., item a) ) should be alive. And, The Req-5 says nothing about
retiring the NAT Session in item c) after 2 mins. 

In reality, the above is not true. Here is why. Most NAT devices use a Binding
refresh timeout of 0 secs for all kinds of Bindings, including TCP Port
Binding, UDP Port Binding and Address Binding. I.e., as soon as the last NAT
Session using the Binding is freed, the associated Binding is also freed. Very
few NAT devices keep the Binding active longer then 0 secs. Some ALGs (ex: DNS
ALG and some P2P ALGs) may keep specific Bindings  alive without a NAT Session
for longer than 0 secs.

Most people on the list, I believe, understood the refresh timeout of 2 mins in
REq-5 to be the idle timeout for a UDP NAT Session, not the Binding. I.e.,
Folks expect the NAT Session in item c) to be freed at the end of no activity
for 2 mins. But, the Binding remains alive, so do the remaining two NAT Session
in items b) and d).  
 
I believe, you are mistaken in your above interpretation. 

> Your requirement that "Bindings" be refreshed is exactly what
> REQ-1 and REQ-5 say. In particular, REQ-1 says "Bindings must be
> implemented" and REQ-5 says "bindings must be refreshed".
> 
[suresh] That would be true, if your interpretaion were to match what the draft
reads or what the authors intended. But, I dont believe so.  In fact, section 3
of the UDP draft states  the following explicitly.
   
   This document uses the term "address and port mapping" as the
   translation between an external address and port and an internal
   address and port.  Note that this is not the same as an "address
   binding" as defined in RFC 2663.

I am willing to go with your interpreation somewhat relunctantly for REQ-1.
But, the interpretation is just not true for REQ-5. By "Mapping refresh", the
UDP authors are  in fact refering to "NAT Session refresh". This is the sort of
inconsitensy in the draft that worries me. 

And, there is no coverage of Binding refresh anywhere in the document, not even
in the section on filter refresh (Section 5.2). 

> > [suresh] Please refer my text above. I believe, REQ-5 refers to "NAT
> Session".
> 
> I do not believe so. REQ-5 still talks about "mappings (behave-udp)" which is
> similar to 
> "bindings (behave-gen)".
> 
> "NAT sessions (behave-gen)" are introduced in Section 5 (not related
> between REQ-5 by the way). Your requirement that "NAT Sessions" be
> refreshed used to be in Section 5.2 "NAT Filter Refresh (behave-udp)". I
> think 5.2 has since been removed as per your request (July 8 mail). If
> you feel that the July 8 mail was due to a misunderstanding of
> terminology, I am sure François can resurrect the section.   
> 

[suresh] Saikat - Please see my response above. Unfortunately, your
interpretation is far from true. 

As for removing section 5.2, we did agree on this because, filtering is not an
independent resource that a NAT device has. You can only refresh a resource a
NAT device has, not a characteristic. The filtering behavior explained in
section 5.1 refers only to the filtering characteristic, but not a NAT Session
resource.

The real problem, I believe, is the inconsistent use of the "mapping" term in
the UDP draft. That may be why the draft does not have refresh timeouts for
Binding and NAT Session covered as two independet requirements. 

> 
> As for which terminology to use, I strongly prefer the behave-udp
> terminology since it can actually differentiate between the types of
> NATs I actually see in the wild.

[suresh] I strongly recommend otherwise. See my notes above on the
inconsistency in your interpretation.

>                                   The behave-gen terminology shoehorns
> many of them into "symmetric" ... and not all "symmetric" NATs are
> behave the same way. 

[suresh] May be so. I havent reviewed your results yet. More importantly, the
Behave-gen terminology is intended to simply identify what is a Behave
compliant NAt device and what is not. When a NAT device does not support
Bindings, it is simply not Behave compliant. What does it matter, how badly it
does not support Bindings. When a NAT device doesnt support hairpin NAT
function, it is simply nat Behave compliant. What does it matter, ho wbadly a
NAt device does not support hair-pinning. Determining the finer gradation of
how badly a NAT device is behave un-compliant is not the goal of this WG
charter.

>                      Indeed I find that NB=A NATs have a 100% traversal
> success rate when paired up with NB=I NATs, but NB=ADP NATs don't. Both
> NB=A and NB=ADP are "symmetric" and hence it is not possible to make the
> observation above if the old terminology is used. 
> 
[suresh] I havet reviewed your STUNT results yet. I will respond when I do in a
different thread. Like I said earlier, it is not the charter of this WG to
generate terminology so as to analyze the various gradations of un-compliant
NAT devices. The objective is simply be one of of determining whether a NAT
device is Behave compliant or not using consistent terms.

cheers,
suresh
> -- 
> Saikat

---

From: Saikat Guha <[email-masked]>
Date: Sun, 17 Jul 2005 19:16:37 -0700 (PDT)

> not specificed for NAT filter refresh in section 5.2? 

Because, two timers are functionally redundant; a single timer is
equivalent. Assume there were two timers, consider the following three
cases.

Scenario:

A ----- N ----- internet ----- B

N is NAT.

*** Using behave-gen terminology ***
Case 1) Binding Timer (BT) < Session Timer (ST)
- Doesn't make sense. Binding cannot expire before session that uses it.

Case 2) Binding Timer (BT) = Session Timer (ST) = One Timer (OT)
- A sends UDP packet to B. New binding created. New session created.
- idle for OT seconds
- Case 2.1)
     B sends packet to A. Packet dropped. No binding or session matched.
  Case 2.2)
     A sends packet to B. New binding created. New session created.
     New binding can be different from old binding.

Case 3) Binding Timer (BT) > Session Timer (ST)
- A sends UDP packet to B. New binding created. New session created.
- idle for ST seconds
- Case 3.1)
     B sends packet to A. No existing session. NAT can either drop
     the packet. Or perhaps, create a new session since binding matches.
  Case 3.2)
     A sends packet to B. Create new session. Same binding.

The only difference in case 3 is that there is a possibility of ST
expiring before BT in which case the session can be recreated. This is
the same as setting OT = MAX(BT, ST).
*** Done using behave-gen terminology ***

Having one timer is sufficient. If NAT vendors happen to implement
something where "binding (gen)" and "session (gen)" are different
objects as you propose, the requirement translates to saying both should
have a 5 minute timer that should be refreshed.

> not aplicable to TCP. 

Not true. Please refer to
http://nutss.gforge.cis.cornell.edu/pub/draft-imc-stunt.pdf Section 4.2

> b. If Binding is same as Mapping (in behave-udp)

They are not exactly the same; more or less same in the sense that
"binding (gen)" is used to enforce "cone" behavior while "mapping (udp)"
is used to enforce the same behavior.

> the mapping refresh timer

This was discussed earlier on the list (see Yutaka-san's mails on
requirement 5.2). A per, the now-defunct, section 5.2 a "NAT Filter
Scope" of "Per mapping" would describe the behavior you mentioned (where
c) would not be reclaimed) and a "NAT Filter Scope" of "Per Session"
would allow c) to be reclaimed. Both have their advantages and
disadvantages -- the former allowing for a single packet to refresh all
sessions and the latter behind more secure. For that reason, it was left
for vendors to decide (FranÃois's June 9 mail). 

> Session using the Binding is freed, the associated Binding is also freed. 

See my response to Case 3 above; setting the mapping timer value to as
long as you propose a binding should be valid for is functionally
equivalent. 

> for 2 mins. But, the Binding remains alive, so do the remaining two NAT 

Agreed -- except I don't think in terms of "binding" and "session". I
believe c) should expire (in that packets from Y2:y2 may be dropped
after 5 minutes of inactivity) while b) and d) remain alive. And in
addition, I believe a new 
   e) ((X:x->Y4:y4) Xlates to (N:Nx->Y4:y4)
i.e. it uses N:Nx .... and that is *exactly* what the UDP draft says
should happen now!!

In particular:
1) the old requirement recommending "Per Mapping" filter refresh scope
has been removed therefore allowing c) to expire if the vendor wants.
2) the 5-minute requirement prevent b) or d) from being reclaimed before
they have been idle for 5 minutes.
3) the EF=I requirement says that a new session (e) should get the same
mapping as b) or d) and should therefore use N:Nx.

As I see it, both you and the draft are recommending the _exact_ same
thing ... which is fantastic ... but just in different terms.

> independent resource that a NAT device has. 

For each filtering rule, the NAT needs to keep state. Here a filtering
rule corresponds to the familiar 7-tuple (Protocol, internal address and
port, mapped address and port, external address and port) ... which also
goes by the name "NAT Session (gen)". What all amongst these 7-entries
the NAT matches an incoming packet to depends on the EF type of the NAT.

> inconsistency in your interpretation.

The inadequacy of "Cone/Symmetric" in capturing current real-life
behavior has nothing to do with the UDP draft.

> When a NAT device does not support
> does not support Bindings. 

Matters both for legacy NATs and for vendors that refuse to be compliant
with behave.

> Determining the finer gradation of

The finer gradation is not for defining how a device is un-compliant. It
just happens to reflect reality better, and as a side-effect ends up
pinpointing the problem on an un-compliant NAT than just say "bad".

-- 
Saikat
Attachment:
signature.asc

---

From: Saikat Guha <[email-masked]>
Date: Sun, 17 Jul 2005 21:06:38 -0700 (PDT)

On Sun, 2005-07-17 at 15:05 -0700, Pyda Srisuresh wrote: 
> Most NAT devices use a Binding
> refresh timeout of 0 secs for all kinds of Bindings

Can you point me to a study that shows that? What percentage of NATs use
a binding timer of 0? What percentage use a larger value? 

In fact, can you even point me to something that shows that the NATs
that you claim "use a Binding refresh timeout of 0 secs" _even use_
bindings and binding timers in the first place?

Instead, let me point you to the Linux source that:
1. DOES NOT use bindings
2. DOES NOT use a binding timer
3. Is a NAT that is behave compliant
4. Would _appear_ to use bindings and a binding timeout of 0 but DOES
NOT

In the Linux implementation, there _is_ "mapping reuse (behave-udp)".
For each "NAT session (behave-gen)" there is a mapping. That mapping is
reused -- the reuse gives the _illusion_ of a "binding". That mapping
has an associated timer (that would appear as "NAT Session timer
(behave-gen)" in your test). That mapping is refreshed (when a packet is
accepted on that mapping -- i.e. when the packet is not filtered). When
a new connection arrives, existing mappings are checked and their mapped
address and port values _reused_. When a mapping expires -- thats it,
the mapping expires -- nothing else is touched or refreshed. No binding
state is reaped. As long as there is even one live mapping when a new
connection arrives from the same internal endpoint the values from that
mapping are reused. When all the mappings are gone, a new mapping is
created for the new connection and there is no reuse. This gives the
_impression_ of having a "binding refresh timeout of 0" ... but in
reality, there is NO binding timeout. I invite you to reconfirm this in
the Linux 2.6.11 NAT code (annotated below).

Not to be rude, but the fact remains that talking of a "binding timeout"
as something that absolutely MUST exist in a NAT and MUST be
standardized is absurd! A vendor's particular implementation may use
"bindings" and "binding timeouts" to implement the requirements
specified in behave-udp .... but claiming that "bindings" and "sessions"
are the one true terminology that descries what NATs do is unjustified.

---- Linux implementation details / code walkthrough ----

When determining what NAT'ed IP and port to use for a new connection,
Linux does the following:

1. Look through each existing session until it finds one where
   the internal src ip and port matches the new connection.
2. Use the NAT'ed ip and port of that connection.

See:
get_unique_tuple calls (ip_nat_core.c#L230) find_appropriate_src that
iterates over (ip_nat_core.c#L146) existing connections (ip_nat.h#L61)
and for each connection, calls same_src (ip_nat_core.c#L147) that checks
protocol, internal IP and port for equality (ip_nat_core.c#L128).
find_appropriate_src returns after the first match (ip_nat_core.c#L155).

(add http://lxr.linux.no/source/net/ipv4/netfilter/ before the
file#Lline links above to view online)

There is *no table of "bindings"* that it checks. It only checks live
"NAT sessions (behave-gen)". 

When a packet is sent or received:
1. The timer for that connection "NAT session (behave-gen)" is
refreshed. (ip_conntrack_proto_udp.c#L73 for UDP,
ip_conntrack_proto_tcp.c#L972 for TCP)

The connection timer is the only one it ever touches. If there was a
binding timer, then it would require at least two timers to be changed
-- that is not the case.

Further, when a connection expires:
The death_by_timeout(ip_conntrack_core.c#L509) function is called that
only deletes the timer associated with that "NAT
session" (ip_conntrack_core.c#L267). 

It does NOT check whether other "NAT sessions (gen)" with the same
"binding (gen)" are alive or not. It does not refresh or set some new
"binding timeout". There is no binding timeout. 

-- 
Saikat
(huff, pufff)
Attachment:
signature.asc

---

From: Saikat Guha <[email-masked]>
Date: Mon, 18 Jul 2005 03:52:13 -0700 (PDT)

On Sun, 2005-07-17 at 21:06 -0700, Saikat Guha wrote:
> Linux source that:

As a footnote, I'd like to point out any requirement of a non-zero
binding timeout cannot be met without ... well ... actually implementing
a separate binding timer. 

Before you dismiss my argument saying that "bindings" and "binding
timeouts" are an abstract concept and are implementation independent,
consider that recommending any non-zero timeout would necessitate the
implementation you have in mind -- thus making your recommendation very
much implementation dependent. In addition, it would discount the Linux
implementation, which I might add is a just fine and is used in Linksys
NATs (29%).

-- 
Saikat
Attachment:
signature.asc

---

From: Pyda Srisuresh <[email-masked]>
Date: Tue, 19 Jul 2005 07:13:39 -0700 (PDT)

--- Saikat Guha <sg266@xxxxxxxxxxx> wrote:

> Because, two timers are functionally redundant; 

[suresh] Saikat - Idle timeout for a Binding and a NAT Session are two
independent timeouts. There is no need to mix them up. It doesnt make sense to
make a numerical comparison of the two timeouts either. Essentially, a Binding
is alive so long as there is at least one NAT Session using that Binding. A
Binding is idle (i.e., unused) when there isnt a NAT Session using the Binding.

<... stuff deleted> 

> http://nutss.gforge.cis.cornell.edu/pub/draft-imc-stunt.pdf Section 4.2

[suresh] Saikat - Good work characterizing NATs. Had a chance to review section
4.2 of your paper. 9% of the devices tested apparatly fell under one of EF=A or
EF=P in that they accept TCP connection if the external Address or Port alone
match the original outgoign connection. For these accpeted connections, does
A:P translate back to a:p, or, is it some other internal port tuple? Have you
seen any scenario where a NAT device accepts inbound TCP connections, but does
not fall under any of the 4 categories you identified (I, AP, A, P)? I suspect,
there will be a few that fall under miscellaneous, wierd, unknown categories,
if you widen your samples further. 

How consistent are the NAT devices in their EF=A or EF=P behavior? The EF=P
behavior is wierd even for UDP and Cone NATs. The good news is they are less
than 10%.

Bottom line - There are buggy and bad implementations out there. When you
caracterize large samples of implementations, you are bound to run into all
kinds of wierd stuff. From a behave WG persepctive, either a NAT devices passes
the muster or not. In what way a device fails to pass the muster is not
relevant to the WG charter.

> for vendors to decide (François's June 9 mail). 
> 

[suresh] Sorry, I dont parse what you say. The timeout mentioned in REQ-5
refers to NAT Session idle timeout. Not same as idletimeout for Binding.  

> long as you propose a binding should be valid for is functionally
[suresh] See my note above. Idle timeout for Binding and NAT Session are
different.

> thing ... which is fantastic ... but just in different terms.

[suresh] Right. I agree with everything you say if you said mapping in REQ-5
were to be interpreted as "NAT Session" in REQ-5. But, you say, they are not
the same.

> the NAT matches an incoming packet to depends on the EF type of the NAT.
[suresh] NAT keeps state for every NAT Session. The state is required for doing
more than just filtering. The state is used for translation, idle timeout
monitoring and so forth for UDP. The state is used to track even more stuff for
TCP - seq/ack no, TCP connection state etc. If all you wanted to do was
filtering, you would need just a 5-tuple filter for the external realm, just as
a firewall does.

NAT Session is a resource that NAT has. filterign is a behavior this resource
enforces.

> behavior has nothing to do with the UDP draft.

[suresh] I agree, the "Cone/Symmetric" behaviors do not capture all the wierd
behaviors out there. E.g., EF=P characterization in section 4.2 of your paper
proves that. None of the Cone/Symmetric Behaviors explain this. 

Then again, it is not the charter of this WG to identify terminology to capture
all the current real-life behaviors of the NAT devices out there. The charter
of the WG is simply to state compliant behavior for NAT devices.
 
> Matters both for legacy NATs and for vendors that refuse to be compliant
[suresh] It is not the charter of this WG to characterize non-compliant NAT
devices.
> pinpointing the problem on an un-compliant NAT than just say "bad".
[suresh] That is a fine thing to do. All that is required from the WG
standpoint is to characterize requirements for compliance. Either a device
meets the requirement or NOT.
  
cheers,
suresh

---

From: Pyda Srisuresh <[email-masked]>
Date: Tue, 19 Jul 2005 08:00:55 -0700 (PDT)

> bindings and binding timers in the first place?

[suresh] Saikat - I have not done a study characterizing NAT devices to give
you percentages. However, I have done several NAT implementations, know of
several people that did NAT implementations and talked with several customers
that used NAT implementations. So, I do know a little something of what I am
talking about.

> the Linux 2.6.11 NAT code (annotated below).
[suresh] As for the Linux implementation detail - I will take your word for it.
Have you looked at how Linux implements DNS-ALG for idle timeout minitoring of
an Address Binding (refer RFC 2694 for DNS-ALG)? (or) Have you looked at how
Linux implements idle timeout monitoring of Bindings for a P2P ALG or any other
ALG that monitors Binding idle timeout? 

People may choose several ways to implement the Bindings and NAT Sessions. The
specific implementations are not relevant to this discussion. What is relevant
is that a NAT device has these resources reflected in some form, with complaint
relationship and characteristics.

> are the one true terminology that descries what NATs do is unjustified.

[suresh] Saikat -  That a NAT device MUST support Bindings is the most
important requirement coming out of the Behave drafts. Binding as a resourc has
characteristics such as directionality and idle timeout, in addition to
endpoint translation. So,it is only reasonable that it be recognized as a key
NAT resource and specify the compliant requirements of this resource and its
parameters in the Behave drafts. It is absurd to not recognize Binding and not
discuss the behavioral requirements of its idle timeout and directioanlity in
Behave drafts.

> "binding timeout". There is no binding timeout. 

[suresh] Saikat - Thanks for the the Linux implementation details. It seems,
Linux is implementing a Binding timeout of 0 secs. While the implementation
details vary, there are many NAT devices that implement a Binding timeout of 0
secs. 

Q: Do you know how Linux implements non-zero timeout for Bindings - Address
and/or Port Bindings?  

cheers,
suresh
 
> 
> -- 
> Saikat
> (huff, pufff)
> > _______________________________________________
> Ietf-behave mailing list
> Ietf-behave@xxxxxxxxxxxxxxxxxxx
> https://list.sipfoundry.org/mailman/listinfo/ietf-behave
>

---

From: Saikat Guha <[email-masked]>
Date: Tue, 19 Jul 2005 14:42:47 -0700 (PDT)

On Tue, 2005-07-19 at 07:13 -0700, Pyda Srisuresh wrote:
> A:P translate back to a:p, or, is it some other internal port tuple?

Yes. A:P translates back to a:p. For lab NATs, I checked packets on the
wire to discount the second possibility.

>  Have you

I have not seen other behavior. It is conceivable that the NAT accepts
inbound SYN's if the source is on the same /24 subnet as another host to
which it has an established connection for example. If that is the case,
the NAT would show up as EF=I in my test (since the two servers are on
the same /25 subnet); duplicating the test with more diversely located
servers would brand the NAT EF=AP or something. The true type of such a
NAT would indeed be something 'weird'. As for my experiments, I checked
the NATs in the lab for this particular weirdness and didn't find it,
but it is possible some NATs do this.

> behavior is wierd even for UDP and Cone NATs. 

Fairly consistent I recall. I repeated the test about 20 times for the
lab NATs and the results were identical.

-- 
Saikat
Attachment:
signature.asc

---

From: Pyda Srisuresh <[email-masked]>
Date: Wed, 20 Jul 2005 07:27:30 -0700 (PDT)

--- Saikat Guha <sg266@xxxxxxxxxxx> wrote:

> > > > The filtering behaviors specified in section 5.1 are specific only to
> UDP
> > > and
> > > > not aplicable to TCP. 
> > > 
[suresh] OK. Thanks for the clarification.
> but it is possible some NATs do this.
[suresh] Right. It certainly is a hard problem to identify the various wierd
behaviors, some of which may be consistent and some not.

> lab NATs and the results were identical.
[suresh] OK, Thanks.

---

From: Bryan Ford <[email-masked]>
Date: Thu, 28 Jul 2005 03:33:26 -0700 (PDT)

Trying to catch up after several weeks of Internet-less travel, I notice that 
Linux seems to be getting thrown around as an example of "good" NAT...

> 4. Would _appear_ to use bindings and a binding timeout of 0 but DOES

Perhaps your information is newer than mine, but at least as of a few months 
ago, the Linux NAT implementation is actually *NOT* BEHAVE-compliant; it only 
pretends very hard to be so, and thus usually passes as "Cone NAT" in 
STUN-like behavior tests.  But it does not always exhibit cone NAT behavior - 
i.e., it is one of our hated nondeterministic beasts, only it's a little more 
subtle than most nondeterministic NATs.

Here is what Linux actually does, according to what I was told a while ago 
directly by one of the developers of Linux's NAT implementation.  When an 
outgoing packet causes a new NAT session A to be set up from internal 
address/port X:x to external endpoint Y:y, the NAT more-or-less arbitrarily 
chooses a public port X':x' for the new session such that the external 
session tuple (X':x',Y:y) is not already in use.  Linux DOES NOT however 
_reserve_ the public port x' for exclusive use as the public endpoint 
corresponding to private endpoint X:x - i.e., it does not create a binding.

Now when the NAT sees another outgoing packet from the same internal endpoint 
X:x to a new external endpoint Z:z, the NAT _tries_ to re-use the 
previously-allocated public port X':x' in creating the new NAT session 
between X:x and Z:z, but only succeeds if the external session tuple 
(X':x',Z:z) does not already happen to be in use.  USUALLY, this external 
session tuple will not already be in use, and so Linux's NAT generally looks 
like a Cone NAT to testing tools.  But it's also entirely possible that some 
completely unrelated NAT session, say from internal endpoint Q:q to external 
endpoint Z:z, has already been assigned public port X':x' and hence has 
allocated the external session tuple (X':x',Z:z), making it unavailable for 
the new session X:x is attempting to open to Z:z.  In this case Linux chooses 
a new random public port X':x'' for the new session from X:x, and suddenly 
starts behaving like a Symmetric NAT (i.e., bad).

Note that this particular form of bad (non-BEHAVE-compliant) behavior will not 
typically show up except when the NAT is under heavy load, and as far as I 
can tell there is easy "black-box" test for this kind of behavior other than 
by deliberately putting the NAT box under heavy load for some period of time 
using a large number of simultaneous connections.  Furthermore, from an 
application's perspective, the Linux NAT's behavior is about as evilly 
nondeterministic as imaginable: an application might successfully use its 
internal UDP port to hole-punch fifteen connections to different external 
hosts, and then fail on the sixteenth (i.e., our "unlucky" external host Z).  
Furthermore, even after failing to connect with host Z, the application might 
still go on and successfully hole-punch to many other hosts - but Z will 
remain persistently inaccessible as long as the particular external session 
tuple needed (X':x',Z:z) is still in use by that unrelated NAT session 
between Q:q and Z:z.

In other words, when the Linux NAT falls into "symmetric mode" due to port 
allocation conflicts, it appears to the application as if certain external 
hosts are (inexplicably) inaccessible via hole punching, even if they are 
known to be alive via other information channels and hole punching works fine 
for many other hosts.  And since the NAT behaves like a Cone NAT "most of the 
time", even a "smart" application that tries to work around typical (dumb, 
predictable) Symmetric NAT implementations will not be able to work around 
Linux's Symmetric NAT.

As I said above, perhaps my information about Linux's NAT is outdated and this 
behavior has subsequently been fixed in the last few months - if so, I would 
appreciate a pointer to any relevant information.  But assuming the above 
description of Linux's behavior is still accurate, it is certainly not 
appropriate to hold up Linux as a model for a "binding-free BEHAVE-compliant 
NAT".  In fact, it reinforces the reasons why the BEHAVE documents NEED to 
talk explicitly about bindings - because NOT talking about them and NOT 
explicitly defining a clear operational model for NAT is just asking for all 
kinds of "near-compliant but nondeterministic" implementations similar to 
Linux's NAT.

To reiterate: to my knowledge Linux's NAT is _NOT_ fully BEHAVE-compliant, 
precisely because it DOES NOT use port bindings to reserve public ports to 
the exclusive use of particular internal endpoints when the first outgoing 
connection is seen from that endpoint.

Bryan

---

From: Saikat Guha <[email-masked]>
Date: Thu, 28 Jul 2005 04:15:30 -0700 (PDT)

On Thu, 2005-07-28 at 12:33 +0200, Bryan Ford wrote:
> When an 

If it does not reserve x' as you say, then it violates REQ-3 ... i.e. it
performs port overloading where an external port already allocated to a
particular internal endpoint may potentially be used for a different
endpoint.

But as far as I understand, Linux does NOT do port overloading and the
external port can indeed be used only by the internal endpoint that
caused its creation (as long as there is one live connection from that
internal endpoint). See (ip_nat_core.c#L248 => ip_nat_core.c#L86 =>
ip_conntrack_core.c#L396 => ip_conntrack_core.c#L291 =>
ip_conntrack_core.c#L281 => ip_conntrack_tuple.h#L127) where it
explicitly makes sure it doesn't overload a port. In fact, going back in
the kernel source to more than 2 years (version 2.4.18), I still see the
same behavior -- no overloading (#L435). So either your information is
really outdated or your friend didn't understand your question.

Here is what I think your friend could have meant:

1. Linux allocates X':x' when the internal port X:x connects to Y:y
2. As long as any such above mapping is alive, Linux is _guaranteed_ to
   allocate X':x' to all new connection initiations form internal port
   X:x
3. But if all the above mappings expire, Linux does not reserve X':x'
   for X:x per say.
4. It uses consistent hashing so most of the time, later on, when X:x 
   initiates a new connections it gets X':x' (mind you X:x has no live 
   connections before this). 
5. Sometimes there can be a collision where another external host A:a 
   hashes to X':x' as well. Since no connection is using X':x', linux
   will allocate that. After this, if X:x initiates a connection, the
   hash will collide and it'll be allocated something else.

Perhaps you can reconfirm this interpretation from your friend.

But as the source looks now (and even 2 years ago), the condition you
mentioned where suddenly your 16th connection may get a different
address is simply NOT possible ... as long as any one of the previous 15
connections is still alive. 

Given the necessity of some non determinism needed to avoid port
overloading, Linux IS behave compliant as far as port allocation is
concerned.

-- 
Saikat 
Attachment:
signature.asc

---

From: Remi Denis-Courmont <[email-masked]>
Date: Thu, 28 Jul 2005 04:25:10 -0700 (PDT)

Hello,

> predictable) Symmetric NAT implementations will not be able to work around 

FYI, my personal experience with Linux/NetFilter was that it also showed
this symmetric behavior on an almost systematic basis when the firewall
part of NetFilter was configured to "accept" unexpected UDP traffic from
the outside, and that traffic happened to have the allocated port as a
destination. Linux would then reject the packet with ICMP Port
Unreachable and record a conflicting association of this port with
itself (ie. the NAT box) as a destination, instead of the user behind
the NAT.

In particular, this is particularly problematic with STUN or Teredo
where the outside server typically (purposedly) sends packets to the
same UDP port on the NAT, but from different IP addresses.

In other words, one should always set up a Linux NAT to DROP incoming
UDP unknown traffic to ports that can be used for MASQUERADE.

-- 
Rémi Denis-Courmont <remi.denis-courmont@xxxxxxxxx>
Nokia Summer Trainee
Nokia-NRC/Helsinki

---

From: Saikat Guha <[email-masked]>
Date: Thu, 28 Jul 2005 16:07:48 -0700 (PDT)

Hi,

On Thu, 2005-07-28 at 14:25 +0300, Remi Denis-Courmont wrote:
> when the firewall
> the outside

I am not sure I understand this. By accept, do you mean that inbound
traffic would sent up the UDP stack of the NAT when there was no mapping
at that port? 

> , and that traffic happened to have the allocated port as a
> Unreachable 

So if internal X:x (mapped to X':x') sent a packet to Y':y' and Z':z'
sent a packet to X':x', then it would cause a ICMP Port Unreachable
because the NAT checks for local apps running on x' and does not check
the mappings? Wouldn't that appear as an EF=AP NAT (or a restricted
NAT); I think Bryan's UDP measurements put Linux in the Full Cone/EF=I
category? Then again I wouldn't be surprised if there was some compile
time/runtime config option that could change this behavior.

> UDP unknown traffic to ports that can be used for MASQUERADE.

Interesting. Thanks.

cheers,
-- 
Saikat
Attachment:
signature.asc

---

From: "Cullen Jennings" <[email-masked]>
Date: Sun, 31 Jul 2005 03:31:25 -0700 (PDT)

Interesting - seem like it would be pretty easy to set up a test for that.
Perhaps we should add that to the test draft. I'm thinking of a test like
two inside IP I1:p, and I2:p. and two stun servers on outside O1:p, and
O2:p. The p are the port and all the same.
I1 does stun with 01. Now I2 does stun with 02. Then I1 does stun with O2
and check that mapping has not changed. Would this catch it ?

Can anyone confirm how Linux chooses the X':x' mapping? If it was random,
this test would not work.

Cullen (as individual)

-----Original Message-----
From: ietf-behave-bounces@xxxxxxxxxxxxxxxxxxx
[mailto:ietf-behave-bounces@xxxxxxxxxxxxxxxxxxx] On Behalf Of Bryan Ford
Sent: Thursday, July 28, 2005 12:34 PM
To: ietf-behave@xxxxxxxxxxxxxxxxxxx
Subject: Re: [Ietf-behave] NAT Mapping refresh vs NAT filter refresh

Trying to catch up after several weeks of Internet-less travel, I notice
that Linux seems to be getting thrown around as an example of "good" NAT...

Perhaps your information is newer than mine, but at least as of a few months
ago, the Linux NAT implementation is actually *NOT* BEHAVE-compliant; it
only pretends very hard to be so, and thus usually passes as "Cone NAT" in
STUN-like behavior tests.  But it does not always exhibit cone NAT behavior
- i.e., it is one of our hated nondeterministic beasts, only it's a little
more subtle than most nondeterministic NATs.

Now when the NAT sees another outgoing packet from the same internal
endpoint X:x to a new external endpoint Z:z, the NAT _tries_ to re-use the
previously-allocated public port X':x' in creating the new NAT session
between X:x and Z:z, but only succeeds if the external session tuple
(X':x',Z:z) does not already happen to be in use.  USUALLY, this external
session tuple will not already be in use, and so Linux's NAT generally looks
like a Cone NAT to testing tools.  But it's also entirely possible that some
completely unrelated NAT session, say from internal endpoint Q:q to external
endpoint Z:z, has already been assigned public port X':x' and hence has
allocated the external session tuple (X':x',Z:z), making it unavailable for
the new session X:x is attempting to open to Z:z.  In this case Linux
chooses a new random public port X':x'' for the new session from X:x, and
suddenly starts behaving like a Symmetric NAT (i.e., bad).

Note that this particular form of bad (non-BEHAVE-compliant) behavior will
not typically show up except when the NAT is under heavy load, and as far as
I can tell there is easy "black-box" test for this kind of behavior other
than by deliberately putting the NAT box under heavy load for some period of
time using a large number of simultaneous connections.  Furthermore, from an
application's perspective, the Linux NAT's behavior is about as evilly
nondeterministic as imaginable: an application might successfully use its
internal UDP port to hole-punch fifteen connections to different external
hosts, and then fail on the sixteenth (i.e., our "unlucky" external host Z).

Furthermore, even after failing to connect with host Z, the application
might still go on and successfully hole-punch to many other hosts - but Z
will remain persistently inaccessible as long as the particular external
session tuple needed (X':x',Z:z) is still in use by that unrelated NAT
session between Q:q and Z:z.

In other words, when the Linux NAT falls into "symmetric mode" due to port
allocation conflicts, it appears to the application as if certain external
hosts are (inexplicably) inaccessible via hole punching, even if they are
known to be alive via other information channels and hole punching works
fine for many other hosts.  And since the NAT behaves like a Cone NAT "most
of the time", even a "smart" application that tries to work around typical
(dumb,
predictable) Symmetric NAT implementations will not be able to work around
Linux's Symmetric NAT.

As I said above, perhaps my information about Linux's NAT is outdated and
this behavior has subsequently been fixed in the last few months - if so, I
would appreciate a pointer to any relevant information.  But assuming the
above description of Linux's behavior is still accurate, it is certainly not
appropriate to hold up Linux as a model for a "binding-free BEHAVE-compliant
NAT".  In fact, it reinforces the reasons why the BEHAVE documents NEED to
talk explicitly about bindings - because NOT talking about them and NOT
explicitly defining a clear operational model for NAT is just asking for all
kinds of "near-compliant but nondeterministic" implementations similar to
Linux's NAT.

Bryan