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