Date: Tue, 7 Oct 2003 12:50:21 -0700 From: Wes Peters <wes@softweyr.com> To: Nick Rogness <nick@rogness.net> Cc: freebsd-hackers@freebsd.org Subject: Re: Changing the NAT IP on demand? Message-ID: <200310071250.21692.wes@softweyr.com> In-Reply-To: <20031005193343.F47183-100000@skywalker.rogness.net> References: <20031005193343.F47183-100000@skywalker.rogness.net>
next in thread | previous in thread | raw e-mail | index | archive | help
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@softweyr.com
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200310071250.21692.wes>