Subject: RE: [Capwap] NAT-T

From: "Abhijit Choudhury" <[email-masked]>
Date: Wed, 22 Mar 2006 12:07:48 -0800

Scott,

I am not sure I understand the issue you are raising.
How much of this has to do with the "optional" DTLS
protection of the data channel ? I think we need to
decide as a group whether DTLS protection of the data
channel is even needed before we go ahead and complicate
the state machine further.

That said, a lot of applications use separate TCP or UDP ports
for control and data and they have no issue traversing
NAT. The control channel conveys the data port that
needs to be opened up, and this may require ALG intervention
to set up the data connection in the NAT box.

In CAPWAP, I'm not sure why the first
packet from the client has to initiate the data channel
setup. Clearly, a data channel will be needed, and the
UDP port can be identified during the control channel
setup process. So, when the first data packet shows up,
everything including the NAT session is already in place.
Applications like FTP do this on a command by command basis.
In the case of CAPWAP it's much much simpler; there is
one session that needs to be opened up in advance and
is long-lived.

Thanks,
   Abhijit

-----Original Message-----
From: Scott G. Kelly [mailto:[email-masked]] 
Sent: Wednesday, March 22, 2006 8:53 AM
To: capwap
Subject: [Capwap] NAT-T

Hi All,

A group of us met yesterday to discuss dtls integration, and one related
design point pertains to nat traversal. In particular, how we decide to
handle directly impacts the design for dtls integration, so we want to
get this resolved ASAP.

In the original lwapp-dtls draft, we discussed two options for
differentiation: use a mux header, or use separate UDP ports, one for
data and one for control. Initial agreement seems to be on the two-port
approach, but this has nat-t implications.

Assume we're using two ports; in that case, the problem we have to solve
is many ways similar to the one solved by the ipsec group (I'll use NAT
rather than NAPT, as it's simpler to type :-)):

- the WTP sends a DISCOVER to the AC; note that if this is broadcast, no
reply would be possible using a standard NAT implementation, as the NAT
binding would be to the tuple (WTP-IP, BCAST-IP, UDP, WTP-PORT,
AC-PORT). Since the response would not be from BCAST-IP, standard NAT
implementations would drop it. This implies directed DISCOVER messages

- *if* the AC responds within the NAT binding timeout period (while the
mapping record still exists on the middlebox), the WTP will receive the
response; otherwise, it will be silently dropped

- assuming the WTP receives the response and wants to associate with the
AC, it initiates the JOIN process (yes, the JOIN must be brought back,
more on that later). One or both sides must also start a heartbeat over
this channel in order to keep the NAPT binding(s) active.

- one point we skipped is that of NAT detection. You could always send
heartbeats, regardless of the presence of NAT, but if you use the
two-port method, you must detect NAT in any case (for reasons that will
become obvious soon). The way IPsec handled this is to have the WTP
include it's IP and port in one of the messages (in our case, during the
JOIN), and having the AC compare this to the adress in the packet
header; if they differ, the AC must inform the WTP of this in the
response.

- NAT detection may be used as an indicator that heartbeat messages are
needed. Note that the interval should probably be configurable (with
sensible defaults),  as there is no standard NAT mapping lifetime.

Okay, so now we have the control channel. The first data channel message
must be from a STA trying to associate. The WTP bundles this up and
sends it to the AC - how does the AC associate this with a given WTP?
Note that there is no guarantee the data channel will have the same
source address as the control channel (L3 switching, load balancing), so
we need a binding mechanism to associate the data and control channels,
from the AC's perspective.

We could do this by placing the same session ID as used for the control
channel into the data channel capwap header, but this header will be
encrypted once dtls starts, adding some complexity to packet handling.
Also, we need to manage heartbeats over this channel as well, and since
we're doing dtls on this channel, we have to decide whether to encrypt
these or not. If we don't, we've added new processing coplexity on both
sides. If we do, we're chewing through our counter/iv space, meaning we
have to take the heartbeat interval into rekey consideration for
purposes of lifetime computations.

Okay, so clearly, using separate ports has some complexity associated
with it. What about using a mux header instead? By this, I mean adding a
field between the udp header and the 'data' (capwap header or dtls
record layer header) to distinguish the two:

+----+-----+------+---------+
|  IP | UDP | mux | data    |
+----+-----+------+---------+

Let's say the mux header is 32 bits, and we use only one of these (for
the time being) to indicate control/data (this is  much like the lwapp
'c' bit). What are the differences in this approach? Two issues have
been raised:

- it adds 4 bytes to the packet

- it is unprotected

To the first, I would reply that this is a trade-off, the price you pay
for greatly reduced complexity. But yes, the cost is 4 bytes

To the second point, I would reply that Eric addressed this in the
security considerations of the lwapp-dtls draft: there are two things an
adversary might attempt here: converting protected data into unprotected
data (data channel into control channel), and vice versa. 

Now, keep in mind that an attacker must be a MiM to do this, implying
they can insert and delete packets at will anyway. If the adversary
converts a data packet (unencrypted) to a control packet,
decryption/authentication will fail, and this will be detected. If the
adversary converts a control packet (encrypted, authenticated) to a data
packet, it will be interpreted as garbage - again, it will be detected. 

The bottom line: there is no threat here that does not exist in the
two-port case. They are equivalent in this respect. 

In the plus column, I think we can say that the mux header approach is
simpler, in that the NAT-T concerns only apply to one channel, and the
binding between control and data channels is unambiguous. Further, it
gives the ability to provide a single de-muxing channel in the code for
inbound packet handling, which may be advantageous, depending on
implementation nuances.

We decided at our meeting yesterday that for these reasons, the mux
header approach seems the most sensible. Does anyone object?

--Scott

_________________________________________________________________
To unsubscribe or modify your subscription options, please visit:
http://lists.frascone.com/mailman/listinfo/capwap

Archives: http://lists.frascone.com/pipermail/capwap
_________________________________________________________________
To unsubscribe or modify your subscription options, please visit:
http://lists.frascone.com/mailman/listinfo/capwap

Archives: http://lists.frascone.com/pipermail/capwap