NAT-T
From: Scott G. Kelly (s.kellyix.netcom.com)
Date: Wed, 22 Mar 2006 08:53:27 -0800 (PST)
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


  • NAT-T Scott G. Kelly, March 22 2006

Results generated by Tiger Technologies using MHonArc.