Bug 17606

Summary: traceroute vs. IPSEC surprise
Product: Base System Reporter: Louis Mamakos <louie>
Component: binAssignee: Hajimu UMEMOTO <ume>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 5.0-CURRENT   
Hardware: Any   
OS: Any   

Description Louis Mamakos 2000-03-26 20:10:01 UTC
When doing a traceroute to a destination host, the packets emitted are
subject to whatever the default IPSEC policy is.  If the default
policy is to use an encrypted payload for all traffic to the
destination, the intermediate hops are unable to return an ICMP time
exceeded error.

Fix: 

I dunno.  This could be a documentation bug.  This might be solved
by having traceroute supply it's own IPSEC policy to not send encrypted
traffic as long as reponses are being returned by intermediate hops.
It's unclear if this is a bug or a feature.
How-To-Repeat: 
As described.
Comment 1 Louis Mamakos 2000-03-28 05:52:10 UTC
>Submitter-Id:   current-users
>Originator:     Louis Mamakos
>Organization:   
>Confidential:   no
>Synopsis:       traceroute and kernel-IPSEC policy can interact badly
>Severity:       non-critical
>Priority:       medium
>Category:       bin
>Release:        FreeBSD 5.0-CURRENT i386
>Class:          sw-bug
>Environment: 

FreeBSD 5.0-current, as of 25 March or so.  Kernel configured with
IPSEC.

>Description: 

When the default kernel IPSEC policy (as configured with setkey(8)) 
includes all the traffic to a particular host, then attempting a
traceroute to that host fails.  The packets being sent are encrypted,
and thus the ICMP time exceeded message cannot be returned.

This is a follow-up to PR bin/17606

>How-To-Repeat: 

As described.

>Fix: 

Steal the same sort of fix done in traceroute6, and apply to the IPv4
"standard" traceroute in FreeBSD.  Patch could be as attached.  
Surprisingly, the ipsec.h file is in sys/netinet6 rather than sys/netinet.


Index: contrib/traceroute/traceroute.c
===================================================================
RCS file: /usr/local/FreeBSD/cvs/src/contrib/traceroute/traceroute.c,v
retrieving revision 1.11
diff -u -r1.11 traceroute.c
--- contrib/traceroute/traceroute.c	1999/06/25 21:48:40	1.11
+++ contrib/traceroute/traceroute.c	2000/03/28 04:38:10
@@ -24,7 +24,7 @@
     "@(#) Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996\n\
 The Regents of the University of California.  All rights reserved.\n";
 static const char rcsid[] =
-    "@(#)$Header: /home/ncvs/src/contrib/traceroute/traceroute.c,v 1.10 1999/05/12 17:28:31 archie Exp $ (LBL)";
+    "@(#)$Header: /usr/local/FreeBSD/cvs/src/contrib/traceroute/traceroute.c,v 1.11 1999/06/25 21:48:40 archie Exp $ (LBL)";
 #endif
 
 /*
@@ -217,6 +217,11 @@
 
 #include <arpa/inet.h>
 
+#ifdef	IPSEC
+#include <net/route.h>
+#include <netinet6/ipsec.h>	/* XXX */
+#endif	/* IPSEC */
+
 #include <ctype.h>
 #include <errno.h>
 #ifdef HAVE_MALLOC_H
@@ -322,6 +327,9 @@
 char	*getaddr(u_int32_t *, char *);
 char	*getsin(struct sockaddr_in *, char *);
 char	*savestr(const char *);
+#ifdef	IPSEC
+int	setpolicy __P((int so, char *policy));
+#endif
 void	send_probe(int, int);
 void	tvsub(struct timeval *, struct timeval *);
 __dead	void usage(void);
@@ -718,6 +726,14 @@
 #endif
 	}
 
+#if	defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
+	if (setpolicy(sndsock, "in bypass") < 0) 
+		errx(1, ipsec_strerror());
+
+	if (setpolicy(sndsock, "out bypass") < 0) 
+		errx(1, ipsec_strerror());
+#endif	/* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
+
 	Fprintf(stderr, "%s to %s (%s)",
 	    prog, hostname, inet_ntoa(to->sin_addr));
 	if (source)
@@ -884,6 +900,28 @@
 
 	return(cc);
 }
+
+#if	defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
+int
+setpolicy(so, policy)
+	int so;
+	char *policy;
+{
+	char *buf;
+
+	buf = ipsec_set_policy(policy, strlen(policy));
+	if (buf == NULL) {
+		warnx(ipsec_strerror());
+		return -1;
+	}
+	(void)setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY,
+		buf, ipsec_get_policylen(buf));
+
+	free(buf);
+
+	return 0;
+}
+#endif
 
 void
 send_probe(int seq, int ttl)
Index: usr.sbin/traceroute/Makefile
===================================================================
RCS file: /usr/local/FreeBSD/cvs/src/usr.sbin/traceroute/Makefile,v
retrieving revision 1.11
diff -u -r1.11 Makefile
--- usr.sbin/traceroute/Makefile	1999/08/28 01:20:22	1.11
+++ usr.sbin/traceroute/Makefile	2000/03/28 04:33:17
@@ -4,7 +4,7 @@
 MAN8=	traceroute.8
 BINMODE=4555
 CFLAGS+=-DHAVE_SYS_SELECT_H=1 -DHAVE_SETLINEBUF=1 -DHAVE_RAW_OPTIONS=1 \
-	-DSTDC_HEADERS=1 
+	-DSTDC_HEADERS=1 -DIPSEC
 # RTT Jitter on the internet these days means printing 3 decimal places on
 # > 1000ms times is plain useless.  Uncomment this to enable variable precision
 # reporting, ie: print a variable precision from 0.001ms through 1000ms
@@ -12,6 +12,8 @@
 
 SRCS=	version.c traceroute.c
 CLEANFILES+=	version.c
+DPADD=	${LIBIPSEC}
+LDADD=	-lipsec
 
 TRACEROUTE_DISTDIR?= ${.CURDIR}/../../contrib/traceroute
Comment 2 Sheldon Hearn freebsd_committer freebsd_triage 2000-03-29 11:27:43 UTC
Responsible Changed
From-To: freebsd-bugs->shin

Inoue-san, could you take a look at this one? 
Comment 3 Sheldon Hearn freebsd_committer freebsd_triage 2000-07-18 15:24:36 UTC
Responsible Changed
From-To: shin->ume

shin seems unavailable at the moment.
Comment 4 Hajimu UMEMOTO freebsd_committer freebsd_triage 2000-07-18 20:07:33 UTC
State Changed
From-To: open->closed

This PR is already applied by shin (traceroute.c rev 1.12) and MFCed. 
Maybe, shin forgot to close. 
Thank you!