Re: A dual-ISP hack with jail/vnet and ipfw

2012-02-04 Thread Julian Elischer

On 2/4/12 9:05 AM, Poul-Henning Kamp wrote:

Natd(8) knows how to deal with multiple NAT instances for different
interfaces, which is useful when you have multiple ISPs.

The problem with it, is that it becomes incredibly hairy to configure
your IPFW rules, in particular if you have other policy to implement
too.


this is sort of what I did when I switched ISPs recently, and had a 
transition period..


I had a jail/vnet for each ISP. and just switched at the top level
an unexpected advantage was that sessions from the main machine were 
'one hop'
away from the disruption when I screwed things so instead of getting 
terminated

when teh rules/routes were screwed, they just 'hung' until I fixed things.
Much like they do when there is internet disruption between sites.

I've meant to do something cleaner like this for a while..
good move.



I spent some quality time with a 9.0-Stable nanobsd image today,
and the script below is my proof of concept of a simpler way to
do that.

The idea is to let a jail deal with the two ISPs and use an epair
to deliver a "normal default route interface" to the rest of the
firewall, making its configuration simpler and easier to understand.


[...]


___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


A dual-ISP hack with jail/vnet and ipfw

2012-02-04 Thread Poul-Henning Kamp

Natd(8) knows how to deal with multiple NAT instances for different
interfaces, which is useful when you have multiple ISPs.

The problem with it, is that it becomes incredibly hairy to configure
your IPFW rules, in particular if you have other policy to implement
too.

I spent some quality time with a 9.0-Stable nanobsd image today,
and the script below is my proof of concept of a simpler way to
do that.

The idea is to let a jail deal with the two ISPs and use an epair
to deliver a "normal default route interface" to the rest of the
firewall, making its configuration simpler and easier to understand.

A discard interface is used to hold 127/8 and the default route in
the jail.  If the default route were to one of the ISP interfaces,
and that if_ goes down, you loose the default route, and packets
don't even reach ipfw(8) in the first place.

Depending on how paranoid you are, you can run the natd(8) in an
empty jail, (see last line).

In a sense this is "DMZ-in-a-box", and there are a number of
interesting ideas to explore, for instance running an openvpn
instance in the jail, but put its TUN/TAP interface in the
default (non-jail) vnet.

The only disadvantage I have found yet, is that you see all packets
with EPAIR_IN destination, instead of the physical destination IP,
the source address however is OK.

Another thing I noticed is that we should probably consider giving
tcpdump/pcap in the unjailed part the ability to packet-dump
interfaces in all vnets.  This would match all the other the
"semi-transparent" properties of jails.

NB: This is only a proof of concept, you may want
to think more about the IPFW rules before going live.

Enjoy,

Poul-Henning

PS: feel free to adopt for any purpose you like, including doc/wiki/etc.

#!/bin/sh

set -x

# ISP #1
VR2_IP=192.168.60.101
VR2_GW=192.168.60.1

# ISP #2
VR3_IP=10.0.0.1
VR3_GW=10.0.0.2

# IN/OUT ethernet pair
EPAIR_OUT=192.168.5.2
EPAIR_IN=192.168.5.1
EPAIR_WID=/30

# Kill old jail
jail -r ext > /dev/null 2>&1 || true 

jdir=/var/tmp/jail_ext
rm -rf $jdir
if true ; then
mkdir $jdir
(
cd /
find \
libexec/ld-elf.so.1 \
sbin/ipfw \
sbin/natd \
sbin/dhclient \
sbin/ifconfig \
sbin/sysctl \
lib/libalias.so.7 \
lib/libbsdxml.so.4 \
lib/libjail.so.1 \
lib/libsbuf.so.6 \
lib/libipx.so.5 \
lib/libc.so.7 \
lib/libutil.so.9 \
lib/libalias_*.so \
etc/libalias.conf \
etc/services \
-print | cpio -dumpv $jdir

)
else
jdir=/
fi


# Create new jail
jail -c vnet name=ext path=$jdir persist

F="jexec ext ipfw"
$F -f flush

$F add  1   denyip from any to any

# No filtering on the epair
$F add 100  allow   ip from any to any via epair0b

# Dispatch to proper natd instance
$F add 1200  skipto 22000ip from any to any in via vr2
$F add 1300  skipto 23000ip from any to any in via vr3

# The global instance, outgoing packets
$F add 1400 divert 4ip from any to any
$F add 1410 fwd $VR3_GW ip from $VR3_IP to any

# Non-matched // TRAFIC POLICY //
$F add 1420 skipto 12000ip from any to any prob .5
$F add 1430 skipto 13000ip from any to any

# Outgoing vr2
$F add 12000divert 2ip from any to any
$F add 12100fwd $VR2_GW ip from $VR2_IP to any
$F add 12200denyip from any to any

# Outgoing vr3
$F add 13000divert 3ip from any to any
$F add 13100fwd $VR3_GW ip from $VR3_IP to any
$F add 13200denyip from any to any

# Incoming vr2
$F add 22000divert 2ip from any to any
$F add 22100allow   ip from any to any

# Incoming vr3
$F add 23000divert 3ip from any to any
$F add 23100allow   ip from any to any

# Set up a discard interface to hold the default route
ifconfig disc0 destroy
ifconfig disc0 create
ifconfig disc0 vnet ext
jexec ext ifconfig disc0 127.0.0.1/8
jexec ext route add default -iface disc0

# Create ethernet pair
ifconfig epair0a destroy
ifconfig epair0 create
ifconfig epair0a ${EPAIR_IN}${EPAIR_WID}

# Default route, (not quite default for my tests)
route del -net 10/8
route add -net 10/8 ${EPAIR_OUT}

# Move other end into jail
ifconfig epair0b vnet ext

# Move external interfaces to jail
ifconfig vr2 vnet ext
ifconfig vr3 vnet ext

jexec ext ifconfig epair0b ${EPAIR_OUT}${EPAIR_WID}

# Get addresses from you ISP's (DHCP/static)
jexec ext dhclient -b vr2 
jexec ext ifconfig vr3 10.0.0.1/30

# Enable forwarding in the jail
jexec ext sysctl net.inet.ip.forwarding=1

# Build a natd.conf for the jail, allow inbound ssh
(
echo deny_incoming
echo globalport 4
echo alia