Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 20 Apr 2002 22:20:41 -0600
From:      Brett Glass <brett@lariat.org>
To:        Terry Lambert <tlambert2@mindspring.com>
Cc:        chat@freebsd.org
Subject:   Re: How to control address used by INADDR_ANY?
Message-ID:  <4.3.2.7.2.20020420205440.021f37b0@nospam.lariat.org>
In-Reply-To: <3CC2255D.6C9B4453@mindspring.com>
References:  <4.3.2.7.2.20020419144005.0358c610@nospam.lariat.org> <4.3.2.7.2.20020419152309.035a96d0@nospam.lariat.org> <4.3.2.7.2.20020420112056.021aaec0@nospam.lariat.org>

next in thread | previous in thread | raw e-mail | index | archive | help
At 08:35 PM 4/20/2002, Terry Lambert wrote:

>No, you are talking about a program that operates as a proxy;

Only in the particular case of the caching proxy. I want to
be able to run other programs there that are not proxies at
all and have them communicate properly with the Net.

>How about this: if you can come up with an algorithm that will
>"do what I want" for you for all cases, without crippling the
>fast path, how about you tell us, and we can think about
>implementing it?

OK, here goes. First, let's restate the problem. The stack is 
choosing a source address for an outbound socket opened with
a source address of INADDR_ANY based on the routing table at
the time the socket is opened. It's saying, "Let's use one of
our addresses on the subnet to which we'd route outbound packets
which are headed for the destination address."

This is normally not a bad idea, since it saves a bit of
routing overhead within the system. But we need to be able to
disqualify a subnet or interface from this process in situations
where this algorithm would produce an undesirable result.

As I understand it, you can do this on a Cisco router by saying
that the interface is up but "unnumbered." But this isn't a
perfect solution either. (For example, in my case, when
I want to send a packet to a device inside the ISP's intranet,
I want my machine to know that it has an address on that 
subnet, respond to ARP "who-has" requests, be able to treat 
them as local, etc.) What I want is to specify that processes on 
my local machine not use source addresses from that subnet even
if they specify INADDR_ANY. To do this, I want to be able 
to do one of three things:

1) Tag an address assigned to an interface as being disqualified
from the selection process. (It might be useful to turn this bit
on by default when one assigns an unregistered address 
to an interface.) This would solve the problem automagically
in the case of intranets that use unregistered addresses (such
as many corporate WANs or the network of the ISP I'm dealing with).
But it wouldn't interfere with NAT.

2) Specify a default source address for processes on the local
machine that is independent of the routing table. (An "auto" option,
indicated by an address of 0.0.0.0, would bring back the old 
algorithm.) This would actually speed up the opening of sockets, 
since no scan of the routing table would be required to pick a 
source address for the socket. And it wouldn't violate the 
semantics of INADDR_ANY.... The process opening the socket has 
indicated no preference, so why not let the administrator specify 
one?)

3) Do both of the above, since each might be useful in specific
situations.

>> It's doing hierarchical routing on 10.x. Their internal 10.x.x.x
>> network is broken up into /24 subnets, one of which exists here.
>> (They have a little router here, and a few other routers tie
>> into it.) Packets for the "real" addresses are to be routed to
>> a specific 10.x address which will be owned by the router I'm
>> putting up.
>
>So you are trying to make the FreeBSD box act like a Cisco router.

Not really. But why should there be things that a Cisco router
can't do that a FreeBSD router can't?

>As I said before, FreeBSD only considers the destination address
>when deciding on a route, and this is technically the wrong thing
>to do for this particualr weird setup you have.

It's really doing something different than deciding on a route.... 
It's deciding what source address to drop into the socket. Again, 
since a socket is defined by the tuple {source address, source 
port, destination address, destination port} and the source address
must be one to which the other machine can reply (it can't
be INADDR_ANY, which is zero), the machine must pick something
at the time the socket is opened and then stick with it,
come what may. Even if the routing table changes so that a
different address would have been picked at a later time.

>Another thing that would likely work is to not try to run the
>proxy services on the same machine that's acting as the router.

It's the best place to run them, especially when one is doing
interception caching. The CPU load from the routing is relatively
light, so there are plenty of resources available for the caching.
Didn't the InterJet do this?

>Your information is insufficient.  A block diagram, with a dotted
>line around the blocks you expect to jam into a single FreeBSD
>box would be useful.

                        +-----------------+
                        |  Router         |    Routable
Rest of world (via  ----| +--------------+|--- Subnet 1
Subnet 10 intranet)     | |Interception  || 
                        | |  caching     ||
                        | |--------------||--- Routable
                        | | RBL zone xfer||    Subnet 2
                        | |--------------||      etc.
                        | | DNS, DHCP    ||
                        | |--------------||
                        | |   sshd       ||
                        | |--------------||
                        | | Utilities for||
                        | | maintenance  ||
                        | | (e.g. ftp,   ||
                        | |CVSup, scp    ||
                        | +--------------+|
                        +-----------------+

In other words, really just some basic firewall functions and
interception caching. The box might not actually be running
DNS or DHCP in all cases, but it'd be nice to be able to, so
I've added them to the diagram. Note that to do DNS zone 
transfers, CVSup, FTP, or scp as a client, the box will need to 
be able to get to the rest of the world from local processes.

>It really feels like you want something to work that we will all
>say "you can't expect that to work!", 

It's perfectly reasonable to expect it to work. The only curve
I've thrown it that it has not been able to handle is that its
upstream network is an intranet with unroutable addresses. Not
unusual either within ISPs or within corporate WANs.

>Arrrrrrrrgh!  Why don't you just post what I post back at
>me, instead of saying the same thing, and spin-doctoring it?

You're annoyed that I agree with you? ;-)

>> Would it affect the "fastpath?" As I understand it, a socket's source
>> address is defined when it's opened and stays that way thereafter.
>> (Correct me if I'm wrong there, but isn't a socket uniquely defined during
>> its lifetime by the tuple of {source address, source port, destination
>> address, destination port}?) All that would need to be altered would be
>> the *initial* decision about the source address used. Right?
>
>Not as such.  It's uniquely identified at the host by the IP/port
>destination tuple, *NOT* by *both* the source and destination
>tuples.

This can't be. When several clients connect to a server's well-known
port at the server, the sessions must be distinguished by the source
addresses and ports. If the source addresses are allowed to change,
the server won't know which client (or session) is which!

>In order to hack this properly, you would have to put two more
>compares in the tcp_output and ip_output code, 

An option that assigned a fixed source address couldn't help but be
a net win, because it would avoid a traversal of a linked list of
routing table entries. Likewise, disqualifying an address would mean 
having a flag or leaving that routing table entry off a linked list. 
The latter would actually speed up the scan of the list because the 
list would be shorter! And one way to implement the fixed source address 
would be to aim the pointer to the linked list at a list with exactly 
one entry: one specifying the fixed address. This would introduce no 
more compares. So, you see, there's no need to add cycles. It's just
a matter of determining whether adding a compare would be a net win. (It 
might be, if it shortened the code path most of the time.)

>or you would have
>to hack up the "clone" route to have different precedence ordering
>of the IP addresses associated with the interface.  The new SYN
>cache code complicates this type of hack considerably.

I don't understand. Why would this be? The SYN cache code deals with 
sockets on which the machine is listening, not outbound sockets.

--Brett


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-chat" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4.3.2.7.2.20020420205440.021f37b0>