From owner-freebsd-bugs@FreeBSD.ORG Wed Jan 21 12:10:14 2004 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 22B0116A4CE for ; Wed, 21 Jan 2004 12:10:14 -0800 (PST) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 4EA5B43D45 for ; Wed, 21 Jan 2004 12:10:11 -0800 (PST) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) i0LKAAFR042178 for ; Wed, 21 Jan 2004 12:10:10 -0800 (PST) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.10/8.12.10/Submit) id i0LKAA72042177; Wed, 21 Jan 2004 12:10:10 -0800 (PST) (envelope-from gnats) Resent-Date: Wed, 21 Jan 2004 12:10:10 -0800 (PST) Resent-Message-Id: <200401212010.i0LKAA72042177@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Manuel Kasper Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 1FBA916A4CE for ; Wed, 21 Jan 2004 12:04:08 -0800 (PST) Received: from s0.m0n0.ch (s0.m0n0.ch [80.238.135.125]) by mx1.FreeBSD.org (Postfix) with SMTP id 25E4843D82 for ; Wed, 21 Jan 2004 12:03:21 -0800 (PST) (envelope-from root@s0.m0n0.ch) Received: (qmail 10829 invoked by uid 0); 21 Jan 2004 20:03:16 -0000 Message-Id: <20040121200316.10828.qmail@s0.m0n0.ch> Date: 21 Jan 2004 20:03:16 -0000 From: Manuel Kasper To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: kern/61685: [patch] ipnat + dummynet on same interface broken X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: Manuel Kasper List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 21 Jan 2004 20:10:14 -0000 >Number: 61685 >Category: kern >Synopsis: [patch] ipnat + dummynet on same interface broken >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Jan 21 12:10:10 PST 2004 >Closed-Date: >Last-Modified: >Originator: Manuel Kasper >Release: FreeBSD 4.9-RELEASE i386 >Organization: >Environment: System: FreeBSD nb.neon1.net 4.9-RELEASE FreeBSD 4.9-RELEASE #0: Thu Oct 30 20:20:56 CET 2003 root@nb.neon1.net:/usr/src/sys/compile/EVON600 i386 with ipfilter, ipfw and dummynet compiled into the kernel >Description: If ipfilter with ipnat is active on a particular interface and the ipfw ruleset contains rules that send inbound packets on the same interface to dummynet, they actually pass through ipnat twice, creating a bogus NAT table entry, which later causes all outbound packets belonging to the same connection to leave that interface effectively un-NATed (in the common case of that interface being the external interface of a firewall with NAT, they leave it with a private source IP address). >How-To-Repeat: Try to setup a firewall using ipfilter/ipnat and ipfw with dummynet rules for inbound packets on the external interface at the same time. Create an ipnat rdr rule to redirect traffic on some port on the external interface to a host on the internal network. Notice that you cannot establish any connection to it from the outside. If you have a look with tcpdump, you will find that the internal host's reply packets (e.g. TCP SYNACK) leave the external interface with an internal (i.e. un-NATed) source IP address. >Fix: Packets that enter ip_input() in sys/netinet/ip_input.c are first passed through ipfilter (and NATed) before they reach ipfw. If a packet is sent to dummynet, it later re-enters ip_input(), where it is decided right at the beginning that this packet has come from dummynet. Execution then jumps to the label "iphack:", which is right before the ipfilter section, so the packet is NATed for the second time on the same interface. Fix: jump after the ipfilter section instead of in front of it. The following patch seems to fix the problem: --- ip_input.c.patch begins here --- --- sys/netinet/ip_input.c.orig Tue Jan 20 20:53:51 2004 +++ sys/netinet/ip_input.c Tue Jan 20 21:00:59 2004 @@ -340,7 +340,7 @@ if (args.rule) { /* dummynet already filtered us */ ip = mtod(m, struct ip *); hlen = IP_VHL_HL(ip->ip_vhl) << 2; - goto iphack ; + goto ipfw; /* skip ipfilter now (already passed it)! */ } ipstat.ips_total++; @@ -451,7 +451,6 @@ * - Encapsulate: put it in another IP and send out. */ -iphack: /* * Check if we want to allow this packet to be processed. * Consider it to be bad if not. @@ -463,6 +462,7 @@ return; ip = mtod(m = m1, struct ip *); } +ipfw: if (fw_enable && IPFW_LOADED) { /* * If we've been forwarded from the output side, then --- ip_input.c.patch ends here --- >Release-Note: >Audit-Trail: >Unformatted: