From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from duke.felloff.net ([216.126.196.34]) by ewsd; Sat Jun 27 11:56:26 EDT 2020 Message-ID: <7AEE26C1A5214C0FB0014A04A715EB28@felloff.net> Subject: Using Plan 9 (9front) as a NAT router. Date: Sat, 27 Jun 2020 17:56:16 +0200 From: cinap_lenrek@felloff.net To: 9front@9front.org MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit List-ID: <9front.9front.org> List-Help: X-Glyph: ➈ X-Bullshit: lossless overflow-preventing proxy element-based CSS locator In my home network, i'v been using 9front as my router for (both v4 and v6) for a while. In a pure Plan 9 network, not having NAT is not an issue as we can import the gateways ip stack over 9p to share a single ip address with multiple machines. But with non-plan9 machines in the network, we need something different. For that, i have been using a unix machine to do the v4 NAT translation. Recently, that machine failed and i had to come up with a work around, which i want to share here. We can actuallly use 9front as a transparent proxy, that looks almost the same as a NAT router from the outside. The key mechanism is that if we can add the magic address 0.0.0.0/0.0.0.0 to an interface, the ip stack will accept any connection as if it was destined to itself. This mechanism is normally only used for the dhcp client and it makes the ip stack useless for outgoing connections as it will put 0.0.0.0 as the source ip address. But if we combine multiple ip stacks, routing and aux/trampoline we can build us a transparent proxy. A script that demonstrates this trick follows: # fist, we need to get us a separate ip stack that we use # *only* for incoming connections. lets bind it to /n/nat: bind -a '#I2' /n/nat # now, we add a packet interface to the /n/nat stack # and hook it up to our primay ip stack on /net < /n/nat/ipifc/clone { nifc=/n/nat/ipifc/`{read} > $nifc/ctl { echo bind pkt # here, we add the magic null address so this stack # will accept any incoming connection. the nexthop # is 0.0.0.1, which will be the interface on the # /net side. echo add 0.0.0.0 0.0.0.0 0.0.0.1 echo iprouting 0 # now, create a new interface on /net that connects # the two ip stacks. < /net/ipifc/clone { oifc=/net/ipifc/`{read} > $oifc/ctl { echo bind netdev $nifc/data echo add 0.0.0.1 255.255.255.255 0.0.0.0 echo iprouting 1 } } } } # now, we can listen on /n/nat ip stack for incoming connections # and relay them to their original destination, but with the source # ip of the router itself. # aux/listen1 sets $net to the new incoming network connection directory. # note that the original destination is found from $net/local: aux/listen1 -t -p 500 '/n/nat/tcp!*!*' /bin/rc -c 'exec aux/trampoline /net/tcp!`{cat $net/local}' & aux/listen1 -t -p 100 '/n/nat/udp!*!*' /bin/rc -c 'exec aux/trampoline -t 5000 /net/udp!`{cat $net/local}' & # the -p flag limits the number of connections active at a time, and # the aux/trampoline -t flag sets a inactivity timeout for udp. # finally we can add a source specific default route with gateway # address of 0.0.0.0 to route traffic from our local network # (192.168.1.0/24) towards our proxy: echo add 0.0.0.0 0.0.0.0 0.0.0.0 192.168.1.0 255.255.255.0 > /net/iproute # end Implementing 464XLAT is left as an exercise to the reader. -- cinap