Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 3 Mar 2001 18:30:18 -0800
From:      Don Lewis <Don.Lewis@tsc.tdk.com>
To:        Chris Johnson <cjohnson@palomine.net>, Don Lewis <Don.Lewis@tsc.tdk.com>
Cc:        stable@FreeBSD.ORG
Subject:   Re: Did ipfw fwd just break?
Message-ID:  <200103040230.SAA25152@salsa.gv.tsc.tdk.com>
In-Reply-To: <20010303211958.A50525@palomine.net>
References:  <20010303203733.A49750@palomine.net> <200103040211.SAA24825@salsa.gv.tsc.tdk.com> <20010303211958.A50525@palomine.net>

next in thread | previous in thread | raw e-mail | index | archive | help
On Mar 3,  9:19pm, Chris Johnson wrote:
} Subject: Re: Did ipfw fwd just break?
} 
} Now, is it possible to protect myself from whatever evil check_interface is
} supposed to protect me from, while still doing my transparent proxying? Or =
} do I
} have to choose one or the other?

Try this patch.  You might still have to disable check_interface if
your host is multi-homed and net.inet.ip.forwarding is 0, but even
so, you should be better protected than with the older code.

Your bug report pointed out problem in the code, which I believe
I have corrected in this patch.  You can be the first to try it ;-)


Index: sys/netinet/ip_input.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.130.2.17
diff -u -u -r1.130.2.17 ip_input.c
--- sys/netinet/ip_input.c	2001/03/02 20:55:14	1.130.2.17
+++ sys/netinet/ip_input.c	2001/03/04 02:23:23
@@ -124,6 +124,12 @@
 	&ip_keepfaith,	0,
 	"Enable packet capture for FAITH IPv4->IPv6 translater daemon");
 
+/*
+ * XXX - Setting ip_checkinterface mostly implements the receive side of
+ * the Strong ES model described in RFC 1122, but since the routing table
+ * and transmit implementation do not implement the Strong ES model,
+ * setting this to 1 results in an odd hybrid.
+ */
 static int	ip_checkinterface = 1;
 SYSCTL_INT(_net_inet_ip, OID_AUTO, check_interface, CTLFLAG_RW,
     &ip_checkinterface, 0, "Verify packet arrives on correct interface");
@@ -258,7 +264,7 @@
 	struct ip *ip;
 	struct ipq *fp;
 	struct in_ifaddr *ia;
-	int    i, hlen, mff;
+	int    i, hlen, mff, checkif;
 	u_short sum;
 	u_int16_t divert_cookie;		/* firewall cookie */
 	struct in_addr pkt_dst;
@@ -482,6 +488,31 @@
 	pkt_dst = ip_fw_fwd_addr == NULL ?
 	    ip->ip_dst : ip_fw_fwd_addr->sin_addr;
 
+	/*
+	 * Don't accept packets with a loopback destination address
+	 * unless they arrived via the loopback interface.
+	 */
+	if ((ntohl(ip->ip_dst.s_addr) & IN_CLASSA_NET) ==
+	    (IN_LOOPBACKNET << IN_CLASSA_NSHIFT) && 
+	    (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
+		m_freem(m);
+#ifdef IPFIREWALL_FORWARD
+		ip_fw_fwd_addr = NULL;
+#endif
+		return;
+	}
+
+	/*
+	 * Enable a consistency check between the destination address
+	 * and the arrival interface for a unicast packet (the RFC 1122
+	 * strong ES model) if IP forwarding is disabled and the packet
+	 * is not locally generated and the packet is not subject to
+	 * 'ipfw fwd'.
+	 */
+	checkif = ip_checkinterface && (ipforwarding == 0) && 
+	    ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) &&
+	    (ip_fw_fwd_addr == NULL);
+
 	TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) {
 #define	satosin(sa)	((struct sockaddr_in *)(sa))
 
@@ -490,17 +521,22 @@
 			goto ours;
 #endif
 		/*
-		 * check that the packet is either arriving from the
-		 * correct interface or is locally generated.
+		 * If the address matches, verify that the packet
+		 * arrived via the correct interface if checking is
+		 * enabled.
 		 */
-		if (ia->ia_ifp != m->m_pkthdr.rcvif && ip_checkinterface &&
-		     (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0)
-			continue;
-
-		if (IA_SIN(ia)->sin_addr.s_addr == pkt_dst.s_addr)
+		if (IA_SIN(ia)->sin_addr.s_addr == pkt_dst.s_addr && 
+		    (!checkif || ia->ia_ifp == m->m_pkthdr.rcvif))
 			goto ours;
-
-		if (ia->ia_ifp && ia->ia_ifp->if_flags & IFF_BROADCAST) {
+		/*
+		 * Only accept broadcast packets that arrive via the
+		 * matching interface.  Reception of forwarded directed
+		 * broadcasts would be handled via ip_forward() and
+		 * ether_output() with the loopback into the stack for
+		 * SIMPLEX interfaces handled by ether_output().
+		 */
+		if (ia->ia_ifp == m->m_pkthdr.rcvif &&
+		    ia->ia_ifp && ia->ia_ifp->if_flags & IFF_BROADCAST) {
 			if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr ==
 			    pkt_dst.s_addr)
 				goto ours;

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-stable" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200103040230.SAA25152>