Subject: small buf in ipf?
To: None <>
From: Andrew Brown <>
List: tech-net
Date: 11/22/2002 13:52:46
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

a few days ago, i found myself in a hotel that offered "free internet"
service.  just plug in, dhcp yourself, and off you go.  but there were

(1) the nameservers given out via dhcp didn't respond because (2) all
outbound port 53 traffic was being redirected to the gateway which (3)
responded from it's own address, not the address to which the original
query was sent.  oh, and any name that it couldn't look up would
elicit an affirmative response containing the external address of the

it sucked.  so i did this:

   # cat > /etc/resolv.conf << EOF
   # cat > /etc/ipnat.conf << EOF
   rdr lo0 port 53 -> port 54 tcp/udp
   map ep0 -> portmap tcp/udp 1025:5300
   # cat > /etc/ipf.conf << EOF
   pass in quick on ep0 to lo0 proto udp from port = 54 to any
   pass in all
   pass out all
   # sysctl -w net.inet.ip.forwarding=1
   net.inet.ip.forwarding: 0 -> 1

that makes my dns traffic go out on lo0, hit the rdr on the way back
in (which retargets it at *my* dns server which is listening on port
54), get forwarded out ep0 (which is why i need the sysctl setting),
hit the map rule (which rewrites the source address to whatever i got
from the dhcp server)...

...hit my server on port 54, which then looks it up properly...

...comes back to me on ep0 where it first hits the map rule (and gets
reset to be from and then the ipf rule that shoves it back
out the loopback interface (so that it can go back through the rdr),
and then we're done.  almost.

first of all, can anyone think of a better way to do this?  i tried
simply running a local name server, but was unable to convince the
local server to forward to a server running on port 54.  the map rule
will only rewrite the source address on the outbound packet (and i
needed the destination rewritten), and the rdr rule will only rewrite
the destination address on an inbound packet (and these are all
outbound queries, since i'm the one generating them), so i figured
that abusing the loopback interface was the easiest way to get both of
those effects.

secondly, the ip checksum on the final packet is invalid, so the
attached patch is required.  it seems that using ipf to "fast-route"
packets skips the checksum adjustment on the subsequent nat

|-----< "CODE WARRIOR" >-----|             * "ah!  i see you have the internet (Andrew Brown)                that goes *ping*!"       * "information is power -- share the wealth."

Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="ip_fil.c.patch"

Index: ip_fil.c
RCS file: /cvsroot/syssrc/sys/netinet/ip_fil.c,v
retrieving revision 1.87
diff -u -r1.87 ip_fil.c
--- ip_fil.c	2002/10/23 09:14:43	1.87
+++ ip_fil.c	2002/11/22 18:51:45
@@ -1713,8 +1713,8 @@
 			(void) fr_checkstate(ip, fin);
 		(void) ip_natout(ip, fin);
 		fin->fin_ifp = sifp;
-	} else
-		ip->ip_sum = 0;
+	}
+	ip->ip_sum = 0;
 	 * If small enough for interface, can just send directly.