Subject: Re: more IPsec NAT-T problems
To: None <tech-net@netbsd.org>
From: Emmanuel Dreyfus <manu@netbsd.org>
List: tech-net
Date: 11/27/2004 19:57:21
Emmanuel Dreyfus <manu@netbsd.org> wrote:
> 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.
Here is the patch to fix that behavior.
That depends on the other NAT-T patch. Briefly, sp->req->sav->natt_type holds
the NAT-Traversal method. UDP_ENCAP_ESPINUDP_MAXFRAGLEN is defined as 552: the
maximum length of a DNS request.
It seems to work, does it looks reasonable?
Index: sys/netinet/ip_output.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_output.c,v
retrieving revision 1.136
diff -U4 -r1.136 ip_output.c
--- sys/netinet/ip_output.c 6 Oct 2004 05:42:24 -0000 1.136
+++ sys/netinet/ip_output.c 27 Nov 2004 18:29:02 -0000
@@ -138,8 +138,9 @@
#ifdef IPSEC
#include <netinet6/ipsec.h>
#include <netkey/key.h>
#include <netkey/key_debug.h>
+#include <netinet/udp.h> /* For NAT-T */
#endif /*IPSEC*/
#ifdef FAST_IPSEC
#include <netipsec/ipsec.h>
@@ -182,8 +183,9 @@
struct socket *so;
va_list ap;
#ifdef IPSEC
struct secpolicy *sp = NULL;
+ int natt_frag = 0;
#endif /*IPSEC*/
#ifdef FAST_IPSEC
struct inpcb *inp;
struct m_tag *mtag;
@@ -505,8 +507,22 @@
printf("ip_output: Invalid policy found. %d\n", sp->policy);
}
/*
+ * NAT-T fragmentation: don't do IPSec processing now,
+ * we'll do it on each fragmented packet.
+ */
+ if (sp->req->sav &&
+ ((sp->req->sav->natt_type & UDP_ENCAP_ESPINUDP) ||
+ (sp->req->sav->natt_type & UDP_ENCAP_ESPINUDP_NON_IKE))) {
+ if (ntohs(ip->ip_len) > UDP_ENCAP_ESPINUDP_MAXFRAGLEN) {
+ natt_frag = 1;
+ mtu = UDP_ENCAP_ESPINUDP_MAXFRAGLEN;
+ goto skip_ipsec;
+ }
+ }
+
+ /*
* ipsec4_output() expects ip_len and ip_off in network
* order. They have been set to network order above.
*/
@@ -825,13 +841,26 @@
#endif
#ifdef IPSEC
/* clean ipsec history once it goes out of the node */
ipsec_delaux(m);
+
+ /*
+ * If we get there, the packet has not been handeld by
+ * IPSec whereas it should have. Now that it has been
+ * fragmented, re-inject it in ip_output so that IPsec
+ * processing can occur.
+ */
+ if (natt_frag) {
+ error = ip_output(m, opt,
+ ro, flags, imo, so, mtu_p);
+ } else
#endif
- KASSERT((m->m_pkthdr.csum_flags &
- (M_CSUM_UDPv4 | M_CSUM_TCPv4)) == 0);
- error = (*ifp->if_output)(ifp, m, sintosa(dst),
- ro->ro_rt);
+ {
+ KASSERT((m->m_pkthdr.csum_flags &
+ (M_CSUM_UDPv4 | M_CSUM_TCPv4)) == 0);
+ error = (*ifp->if_output)(ifp, m, sintosa(dst),
+ ro->ro_rt);
+ }
} else
m_freem(m);
}
--
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