Subject: more IPsec NAT-T problems
To: None <tech-net@netbsd.org>
From: Emmanuel Dreyfus <manu@netbsd.org>
List: tech-net
Date: 11/24/2004 00:21:21
Hi

Summary: NAT-T is about encapsulating ESP in UDP. It's done in the
kernel for sockets that required it. While the code is not in tree yet
(IPR issue pending in the US), I did most of it. It can be obtained from
here:
http://ipsec-tools.sourceforge.net/netbsd_nat-t.diff

Now I discovered an outstanding problem. Let's look at the following
scenario:

katabatic is a roadwarrior. transpalette is the VPN gateway. katabatic
negociated an IPsec SA that uses NAT-T with transpalette. katabatic
starts sending ping -s 1500 to dol-guldur.

The ping goes through the VPN gateway, in two UDP:ESP:frag(ICMP)
packets. 

When the packet reaches transpalette, ESP decryption is done, and we get
two ICMP fragments: 

katabatic            transpalette                  dol-guldur
     --- udp 1388 ---->        ---- icmp 1336@0 ----->
     --- udp 228 ----->        ---- icmp 172@1336 --->
     <-- udp 1480@0 ---        <--- icmp 1480@0 ------
     <-- udp 60@1480 --        <--- icmp 28@1480 -----  

dol-guldur replies by two ICMP fragments. transpalette reassemble them
before ESP encryption, and sends two frag(UDP:ESP:ICMP) packets. 

And here is the problem: most DSL routers are broken and block
fragmented UDP packets. The goal is therefore to not send two
frag(UDP:ESP:ICMP), but to send two UDP:ESP:frag(ICMP) instead. 

That does not seems easy. I guess it should take place in esp_output(),
where the packet should be fragmented before undergoing ESP encryption.
I can call esp_output several times from esp_output, handing the
fragments. Does that seem reasonable?

Another problem is how to choose the fragment size? I think about using
a fixed value that would just work, for instance 1300. Unfortunately
that would not match any setup. I can also record the fragment size used
by the roadwarrior, but I suspect there would be some situation where
the maximum size would be different. 

Maybe the only way to go is to use the maximum size of a DNS request,
which should work on any broken DSL router? It's 552 bytes. 

-- 
Emmanuel Dreyfus
Il y a 10 sortes de personnes dans le monde: ceux qui comprennent 
le binaire et ceux qui ne le comprennent pas.
manu@netbsd.org