From owner-freebsd-net Wed Nov 14 16: 5:49 2001 Delivered-To: freebsd-net@freebsd.org Received: from mail.vicor-nb.com (bigwoop.vicor-nb.com [208.206.78.2]) by hub.freebsd.org (Postfix) with ESMTP id 94CAE37B416 for ; Wed, 14 Nov 2001 16:05:38 -0800 (PST) Received: from vicor-nb.com (julian.vicor-nb.com [208.206.78.97]) by mail.vicor-nb.com (Postfix) with ESMTP id 6D2931B219 for ; Wed, 14 Nov 2001 16:05:38 -0800 (PST) Message-ID: <3BF306D2.3A50C4AF@vicor-nb.com> Date: Wed, 14 Nov 2001 16:05:38 -0800 From: Julian Elischer Organization: VICOR X-Mailer: Mozilla 4.76 [en] (X11; U; FreeBSD 4.3-RELEASE i386) X-Accept-Language: en, hu MIME-Version: 1.0 To: net@freebsd.org Subject: Re: RFC: ipfirewall_forward patch References: <3BF30699.E8CC9857@vicor-nb.com> Content-Type: multipart/mixed; boundary="------------57D10815F8353059B9D7304D" Sender: owner-freebsd-net@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org This is a multi-part message in MIME format. --------------57D10815F8353059B9D7304D Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Oops forgot the patch.. here it is... Julian Elischer wrote: > > The following patch is expected to > allow the forwarding of INCOMING packets to an arbitrary next hop > controlled by the ipfw fwd command.. > > Ipfw 'fwd' at present has teh following restriction: > > only packets already leaving the system can be hijacked and forwarded > to a 2nd machine. Incoming packets can only be forwarded to local > addresses/port combinations. > > This patch would allow a sequence of mchines to hijack > a particular conforming packet and pass it allong a chain of > these machine sot make it fall out somewhere else.. > > the particular example I have in mind: > > [internet]---[A.b.c.d]-------[10.2.3.4] > \---------[10.2.3.5] > \---------[10.2.3.6] > \---------[10.2.3.7] > > on A.b.c.d: > ipfw add 1000 fwd 10.2.3.4 tcp from 0.0.0.0:0.0.3.0 to A.b.c.d 80 in > recv fxp0 > ipfw add 1000 fwd 10.2.3.5 tcp from 0.0.1.0:0.0.3.0 to A.b.c.d 80 in > recv fxp0 > ipfw add 1000 fwd 10.2.3.6 tcp from 0.0.2.0:0.0.3.0 to A.b.c.d 80 in > recv fxp0 > ipfw add 1000 fwd 10.2.3.7 tcp from 0.0.3.0:0.0.3.0 to A.b.c.d 80 in > recv fxp0 > > and on each of the four machines: > ipfw add 1000 fwd localhost tcp from any to A.b.c.d 80 in recv fxp0 > > this is a 4 -way load sharing setup sharing > http load across 4 machines (in our case proxies) > > implemented in 5 lines of ipfw. > > To the external world it would look as if all requests are being > satisfied > by A.b.c.d:80. --------------57D10815F8353059B9D7304D Content-Type: text/plain; charset=us-ascii; name="thedifff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="thedifff" diff -u ./ip_input.c /sys/netinet/ip_input.c --- ./ip_input.c Wed Aug 29 14:41:37 2001 +++ /sys/netinet/ip_input.c Wed Nov 14 15:41:20 2001 @@ -1587,21 +1587,29 @@ int error, type = 0, code = 0; struct mbuf *mcopy; n_long dest; + struct in_addr pkt_dst; struct ifnet *destifp; #ifdef IPSEC struct ifnet dummyifp; #endif dest = 0; + /* + * Cache the destination address of the packet; this may be + * changed by use of 'ipfw fwd'. + */ + pkt_dst = ip_fw_fwd_addr == NULL ? + ip->ip_dst : ip_fw_fwd_addr->sin_addr; + #ifdef DIAGNOSTIC if (ipprintfs) printf("forward: src %lx dst %lx ttl %x\n", - (u_long)ip->ip_src.s_addr, (u_long)ip->ip_dst.s_addr, + (u_long)ip->ip_src.s_addr, (u_long)pkt_dst.s_addr, ip->ip_ttl); #endif - if (m->m_flags & (M_BCAST|M_MCAST) || in_canforward(ip->ip_dst) == 0) { + if (m->m_flags & (M_BCAST|M_MCAST) || in_canforward(pkt_dst) == 0) { ipstat.ips_cantforward++; m_freem(m); return; @@ -1620,14 +1628,14 @@ sin = (struct sockaddr_in *)&ipforward_rt.ro_dst; if ((rt = ipforward_rt.ro_rt) == 0 || - ip->ip_dst.s_addr != sin->sin_addr.s_addr) { + pkt_dst.s_addr != sin->sin_addr.s_addr) { if (ipforward_rt.ro_rt) { RTFREE(ipforward_rt.ro_rt); ipforward_rt.ro_rt = 0; } sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); - sin->sin_addr = ip->ip_dst; + sin->sin_addr = pkt_dst; rtalloc_ign(&ipforward_rt, RTF_PRCLONING); if (ipforward_rt.ro_rt == 0) { @@ -1674,7 +1682,7 @@ if (rt->rt_ifp == m->m_pkthdr.rcvif && (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 && satosin(rt_key(rt))->sin_addr.s_addr != 0 && - ipsendredirects && !srcrt) { + ipsendredirects && !srcrt && !ip_fw_fwd_addr) { #define RTA(rt) ((struct in_ifaddr *)(rt->rt_ifa)) u_long src = ntohl(ip->ip_src.s_addr); @@ -1683,7 +1691,7 @@ if (rt->rt_flags & RTF_GATEWAY) dest = satosin(rt->rt_gateway)->sin_addr.s_addr; else - dest = ip->ip_dst.s_addr; + dest = pkt_dst.s_addr; /* Router requirements says to only send host redirects */ type = ICMP_REDIRECT; code = ICMP_REDIRECT_HOST; diff -u ./ip_output.c /sys/netinet/ip_output.c --- ./ip_output.c Wed Jul 18 23:37:26 2001 +++ /sys/netinet/ip_output.c Wed Nov 14 15:41:14 2001 @@ -135,6 +135,7 @@ struct sockaddr_in *dst; struct in_ifaddr *ia = NULL; int isbroadcast, sw_csum; + struct in_addr pkt_dst; #ifdef IPSEC struct route iproute; struct socket *so = NULL; @@ -154,6 +155,9 @@ divert_cookie = 0; #endif + pkt_dst = ip_fw_fwd_addr == NULL + ? ip->ip_dst : ip_fw_fwd_addr->sin_addr; + #if defined(IPFIREWALL) && defined(DUMMYNET) /* * dummynet packet are prepended a vestigial mbuf with @@ -227,14 +231,14 @@ * and is still up. If not, free it and try again. */ if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 || - dst->sin_addr.s_addr != ip->ip_dst.s_addr)) { + dst->sin_addr.s_addr != pkt_dst.s_addr)) { RTFREE(ro->ro_rt); ro->ro_rt = (struct rtentry *)0; } if (ro->ro_rt == 0) { dst->sin_family = AF_INET; dst->sin_len = sizeof(*dst); - dst->sin_addr = ip->ip_dst; + dst->sin_addr = pkt_dst; } /* * If routing to interface only, @@ -279,7 +283,7 @@ else isbroadcast = in_broadcast(dst->sin_addr, ifp); } - if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) { + if (IN_MULTICAST(ntohl(pkt_dst.s_addr))) { struct in_multi *inm; m->m_flags |= M_MCAST; @@ -325,7 +329,7 @@ } } - IN_LOOKUP_MULTI(ip->ip_dst, ifp, inm); + IN_LOOKUP_MULTI(pkt_dst, ifp, inm); if (inm != NULL && (imo == NULL || imo->imo_multicast_loop)) { /* @@ -575,8 +579,9 @@ /* * Check with the firewall... + * but not if we are already being fwd'd from a firewall. */ - if (fw_enable && ip_fw_chk_ptr) { + if (fw_enable && ip_fw_chk_ptr && !ip_fw_fwd_addr) { struct sockaddr_in *old = dst; off = (*ip_fw_chk_ptr)(&ip, @@ -767,6 +772,7 @@ goto done; } + ip_fw_fwd_addr = NULL; pass: m->m_pkthdr.csum_flags |= CSUM_IP; sw_csum = m->m_pkthdr.csum_flags & ~ifp->if_hwassist; --------------57D10815F8353059B9D7304D-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-net" in the body of the message