Date: 21 Jan 2004 20:03:16 -0000 From: Manuel Kasper <mk@neon1.net> To: FreeBSD-gnats-submit@FreeBSD.org Subject: kern/61685: [patch] ipnat + dummynet on same interface broken Message-ID: <20040121200316.10828.qmail@s0.m0n0.ch> Resent-Message-ID: <200401212010.i0LKAA72042177@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>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 <mk@neon1.net> >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. <unimp.> */ -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:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040121200316.10828.qmail>