Changing the NAT IP on demand?
Wes Peters
wes at softweyr.com
Tue Oct 7 12:50:31 PDT 2003
On Sunday 05 October 2003 19:11, Nick Rogness wrote:
> On Sun, 5 Oct 2003, Wes Peters wrote:
> > On Sunday 05 October 2003 01:02 am, Nick Rogness wrote:
> > > On Sat, 4 Oct 2003, Leo Bicknell wrote:
> > > > I'm considering options for a new project, and I think I've
> > > > discovered what I think is the best idea, but I don't think
> > > > current software supports the config. I'd like to get some
> > > > confirmation, and comments on if it would be hard to implement.
> > > >
> > > > Consider:
> > > >
> > > >
> > > > ISP #1-------\
> > > > \
> > > > FreeBSD Box----LAN
> > > > /
> > > > ISP #2-------/
> > > >
> > > > In this case the LAN would be 1918 space, the two ISP's would
> > > > each provide a public IP for the FreeBSD box.
> > > >
> > > > Now, NAT would be required. What I want to do is write an
> > > > external application to decide the performance of ISP #1 and
> > > > ISP#2, and somehow tell NAT which outside address to use.
> > > >
> > > > That, by itself, is not hard. Here's the trick. I want the
> > > > switch to be seamless. That is, if NAT is translating to ISP
> > > > #1 and the application says switch to #2 the existing
> > > > translations to #1 (until they go away naturally) should be
> > > > kept, while new ones go to #2.
> > > >
> > > > The only ways I know to change the outside address seem to tear
> > > > down all existing connections.
> > > >
> > > > Is it possible to make this work today? Would it be hard to
> > > > fix if it doesn't work today?
> > >
> > > This can simply not work without resetting connections. The
> > > socket pair on the "outside" would break as your outside traffic
> > > switches from one to the other (src/dst would change). There is
> > > no fix, as this breaks basic IP principals.
> >
> > That's not at all what Leo was asking.
>
> Sorry bout that, didn't read carefully enough. I understand the
> question now after more careful reading.
>
> > Leo, you may be able to do this with ipfilter's ipnat. Nat rules
> > are traditionally processed with 'ipnat -CF', the -C clears the
> > rules and the -F option clears the currently active NAT mappings.
> > You should experiment with rewriting the rules and instantiating
> > them with -C only. This should leave the existing stateful mappings
> > to the formerly preferred interface while creating all new mappings
> > on the newly preferred interface.
>
> In addition to keeping your NAT translations (as suggested by
> Wes), you need to also keep routes for those entries as well, so
> that preserved traffic remains to route out the right ISP even if
> a switch occurs.
Ah, yes, another sticky bit of the problem. It seems you could do a
least a partial workaround by creating and maintaining a host route for
each active NAT mapping. The NAT engine would have to reference-count
the routes it is maintaining.
This *is* a simpler alternative than hacking source routing into FreeBSD
at this point.
> The reason for this is simple.
> When you switch the route(s) to the other ISP (which you would
> have to do), your existing translations would get routed out to
> the wrong ISP. You would need to keep routes for existing
> translations to make sure they leave the proper 'old' interface.
> This would not be necessary if each ISP allowed you to use either
> public IP on each others network (not likely).
>
> Nat (AFAIK) does not determine which interface to leave. You can
ipnat operates quite differently from natd; it bears looking into. It's
been a while since I was intimate with ipnat, so I can't say off the
top of my head how hard this might be.
> change the source address in the packet to anything you want, this
> will not tell it to leave 'interace_to_ISP#1' or
> 'interface_to_ISP#2'. That is a decision made using the routing
> table.
ipnat redirections already have a limited sort of round-robin load
balancing capability. A quick read through ipnat(5) may enlighten. It
would be instructive to search out the round-robin code and think about
how to extend it into a mechanism to do failover or smarter load
balancing.
> Your app would have to keep track of these NAT things and
> also add and remove routes from the routing table.
Nat mappings are already available, via the /dev/ipnat device and
ioctl's, with ipnat.
> That is, if everything is going out ISP#1 and you decide to switch
> to ISP#2 you would need to:
>
> 1) Keep exisiting NAT translation(s) like suggested by
> Wes.
> 2) Add routing table entry for each of the NAT
> translations you want to preserve to ISP#1
> 3) Switch default routing to ISP#2
> 4) When sessions are finsihed and NAT translations
> removed to ISP#1, the route(s) that pertain to those
> NAT translations would need to be removed.
Yeah, conceptually it's pretty simple isn't it? The devil is, as
always, in the details. ;^)
--
"Where am I, and what am I doing in this handbasket?"
Wes Peters wes at softweyr.com
More information about the freebsd-hackers
mailing list