Date: Sat, 20 Apr 2002 01:47:50 -0700 From: Terry Lambert <tlambert2@mindspring.com> To: Brett Glass <brett@lariat.org> Cc: chat@freebsd.org Subject: Re: How to control address used by INADDR_ANY? Message-ID: <3CC12B36.E9DC0040@mindspring.com> References: <4.3.2.7.2.20020419144005.0358c610@nospam.lariat.org> <4.3.2.7.2.20020419152309.035a96d0@nospam.lariat.org>
next in thread | previous in thread | raw e-mail | index | archive | help
Brett Glass wrote: > >INADDR_ANY means "I don't care". FreeBSD's "I don't care" is a > >bit different in implementation than Cisco's "I don't care". 8-(. > > > >Since you apparently *do* care, you must bind a specific address > >for outbound connections. > > Unfortunately, "you" consists of any application that might be > running on the box. Yes. > And few, if any, of the standard apps one is > likely to use in administration offer you the option of specifying > a source address explicitly. For example, suppose I want to bring > in a patch or some code via anonymous FTP. I can't, because the > Berkeley FTP client doesn't let you specify a source address. All FTP servers allow it, and so do "bind" and "sendmail". The code that doesn't allow it could be said to be broken. > >It picks the first address on the first interface on the subnet > >for the destination address in question, > > When the machine is going out to the Internet at large, the > destination isn't on any of those subnets. Then it goes out the interface whose IP address is on the same subnet as the default route. In your case, this will unavoidably be a 10.x address. > >Probably you can make it work by setting the IP address to the > >one for the bridged network, > > I'm not sure I follow. There's no bridged network here. Then I don't understand how the ISP is tunneling packets from the assigned published IP addresses out to the real internet, or back. It *must* be doinging bridging for you. The 10.x addresses you are using are, by definition, non-routable. > >and then setting the 10. address > >to be the alias, instead of the bridged address. > > The only addresses that are "legal" on the ISP's > internal subnet are 10. addresses, by policy. I > could try something like specifying the address as > 127.0.0.2 with the 10. address as an alias.... The > default IPFW rules would keep any packets with a source > address of 127.0.0.2 from actually leaving the interface. > But this is kinda dicey... and I don't know what the > stack will do. Will apps wind up with sockets that have > 127.0.0.2 as a source address? They might. This will not work. I would have to know how your ISP expects things to work, for me to be able to tell you how to configure your FreeBSD box to work they way they expect things to work (if it's even possible). > >Really, this is a bug in the FreeBSD code, in that it is not > >treating the IP address/port pair on the destination as the > >route to choose the "proper" origin address. > > Actually, it may just be an omission. Just as we can set a > default gateway, it might be nice to be able to set a default > IP for outbound sockets. (INADDR_ANY has different semantics when > one is listening, of course, so it's only the outbound case > that we need to worry about.) Or we might be able to set a flag > that disqualifies an interface from having its address(es) used as > the source address when INADDR_ANY is used. (This is probably done > for lo0 now. I don't know for sure, but I'll bet that the code > notices the LOOPBACK flag and disqualifies the interface.) The > new flag could be set and viewed via ifconfig. No. It is a bug. The problem is that the route code does not distinguish multiple default routes, nor does it distinguish aliases from their interfaces. Because of this, you route out an interface, not out a source IP address on an interface. Without routing out a specific source IP, your packets get the first IP address on the interface. It's somewhat more complicated than that because of your use of multiple local routable subnets. Really, the BSD code does two things: 1) Routes packets destined for a local subnet out of the interface whose netmask of the IP address that you are sending too applied to the IP address of the interface result in the "best match". THat is, if you have two interfaces that match, and one is a /24 and the other is a /28, it will pick the /28 to send. For equal interfaces, the one it picks is round-robin'ed. 2) Routes all other packets out the default route (and it has only a single default route, which is not a good thing, in a lot of ways). The easiest way to see the deficiency in the FreeBSD networking code is to ask yourself "If I buy a system, put a single gigabit interface in it, and add 2 4 port 10/100 cards, how can I build a FreeBSD based switch, using this hardware?". The first thing you need to realize is that switches don't have assigned IP addresses to ports; a lot of the obvious problems will fall out at you from that point forward. > >Short of rewriting a lot of the stack to reorder the anonymous > >address handling (e.g. to make it work like Cisco equipment > >does), > > There may be a single assignment statement somewhere that could > be made to grab the address from a sysctl variable. Terry, you > know the network code better than I.... In what file is INADDR_ANY > converted into a specific source address? What logic is used to > determine which addresses are suitable? You could pound on the code, and abuse it in such a way as to make it do what you suggest,at the same time putting enough special cases into the code path that you bloat the normal 94 instructions for the TCP/IP fastpath into some huge number that would prevent your suggested changes ever being committed back to FreeBSD. I would not recommend doing that. The issue is the routing code, which identifies an interface, not an IP address, on the target network, or, if one does not exist, then clones one for the default route. This is ~line 950 of /sys/netinet/ip_output.c; the "ro" is passed in as a parameter, which is sent down as a result of the inp_route element of the inpcb for the tcpcb for the TCP connection (the "internet protocol control block"; see Stevens). Changing this is not easy; you can't "just do it", because there is a pseudo-header in the TCP packet that is considered as part of the checksum, which contains the source and destination addresses. The route selection occurs at the TCP output layer, not the IP. It affects both the TCP and the IP checksums. Therefore, if you wish to interfere with the source IP address selection, you have to do it in the tcp_output code... or, more properly, before the call to tcp_fillheaders(). Probably, it would make the most sense to set it at connection time, which is (and should be) an incredibly difficult thing to do, for an unbound socket. > >it's probably best to just bind outgoing interfaces > >manually, and deal with the netmask in your proxy app. > > I won't want to rewrite every application I might use on the > box! Adding a mod to the stack would be easier... unless there's > some way to get the existing code to do The Right Thing. The suggestion in the "sockets2" working group has been to add a "sendfrom" and "sendfromto" system call to allow specification of a source IP address from which the packet is intended to have originated. For obvious reasons, I think this is a bad idea. But either way has you rewriting applications... -- Terry 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?3CC12B36.E9DC0040>