Subject: small buf in ipf?
To: None <tech-net@netbsd.org>
From: Andrew Brown <atatat@atatdot.net>
List: tech-net
Date: 11/22/2002 13:52:46
--UugvWAfsgieZRqgk
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
problems.

(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
gateway.

it sucked.  so i did this:

   # cat > /etc/resolv.conf << EOF
   nameserver 127.0.0.1
   EOF
   # cat > /etc/ipnat.conf << EOF
   rdr lo0 127.0.0.1/32 port 53 -> 166.84.189.72 port 54 tcp/udp
   map ep0 127.0.0.1/32 -> 0.0.0.0/32 portmap tcp/udp 1025:5300
   EOF
   # cat > /etc/ipf.conf << EOF
   pass in quick on ep0 to lo0 proto udp from 166.84.189.72 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 127.0.0.1) 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
manipulation.

-- 
|-----< "CODE WARRIOR" >-----|
codewarrior@daemon.org             * "ah!  i see you have the internet
twofsonet@graffiti.com (Andrew Brown)                that goes *ping*!"
werdna@squooshy.com       * "information is power -- share the wealth."

--UugvWAfsgieZRqgk
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.
 	 */

--UugvWAfsgieZRqgk--