Subject: fixing NAT-T and multiple clients behind the NAT
To: None <tech-net@netbsd.org>
From: Emmanuel Dreyfus <manu@netbsd.org>
List: tech-net
Date: 04/12/2005 15:54:00
Hi

NAT-T does not work if we have multiple hosts behind the same NAT, because
our kernel has no way to select a different security association for each 
hosts.

The information required to distinguish between NATed peers is available in 
src/netinet/udp_usrreq.c:udp4_espinudp(), where we receive ESP over UDP
packets: it's the UDP source port of the ESP over UDP packet.

Unfortunately, after udp4_espinudp() has done its job, this information
is lost. udp4_espinudp() strips the UDP header and reinject the packet 
in esp4_input().

How to properly keep track of the UDP source port? Reading existing code, 
I have the feeling that m_tag is the right way, but I'm not sure I 
properly understand how it works. That can be used to add random data
to the mbuf, right?

So in udp4_espinudp(), I'd add a m_tag type PACKET_TAG_IPSEC_NAT_T_PORT, 
containing a uint16_t with the source UDP port. Does that makes sense?


Now, using the information: I have to modify esp4_input(). It uses 
key_allocsa() with source IP, destination IP and ESP SPI.

In order to fix the problem, it seems we need to pass the remote port 
to key_allocsa(), and then match not only against the source address but 
also against the source port, which is available in struct secasvar. 
Is it okay to add the port argument to key_allocsa()?


It seems there is no real problem for outgoing packets in tunnel mode 
since the security policies use the tunnel remote address, which is 
unique for each remote host. Finding the right entry in the SPD leads 
to the right entry in the SAD with the right UDP port.

Transport mode is a whole different story, because all NATed hosts will
have the same address in the SPD. This is probably where the ISAKMP NAT-OA 
payload (OA: Original Address) should be used. But that's for another day.

Comments?


While I'm there, I think it would make sense to dump the NAT port when
doing setkey -D. For NAT-T enabled SA, that would modify the first line 
of the output from 
192.0.2.3 192.0.2.240
to
192.0.2.3[30023] 192.0.2.240

20023 being the NAT port in this example. But I'm concerned it could 
confuse existing scripts that parse setkey output.

-- 
Emmanuel Dreyfus
manu@netbsd.org