> I have no idea how to control which address is used for outgoing 
> communications other than by configuring your network gateway to go through 
> the preferred device, which may not do exactly what you want.  

I've just read through the whole thread.  People seems to be getting
confused about a couple of concepts.

        Firstly, consider the need to be able to manually specify the outbound
IPv4 address of "Client" connections from a daemon _as well_ as the
inbound address on which to listen for incoming service requests.

        In most shops, in almost all but the most basic configurations, the
generally accepted practice is to create abstraction between the
"system" and the "service" provided by it.  Even if a system has a
single service/function, it still binds the service to a "Service VIP",
or "IP Alias (BSD)".

        I.e., almost all machines have a "Management Address" and "Service
VIP", especially in non-RFC1918-space-only shops.

        To give you an idea why this is a policy in most places: For example,
if a system crashes, you can pick up the VIP and move it to a different
system in the same VLAN.

...OR, if that service VIP has a CNAME pointing to it, you can simply
cut over the CNAME destination to a service VIP in a different VLAN
without breaking all your clients.

Thus, "System-Service Abstraction"

        This becomes especially paramount in High Availability configurations
where at service VIP dangles between two or more servers.  Consider the
Linux-HA system.

        It is also extremely important when you're trying to manage firewall
rule growth.   At present, if you have multiple VIPs/IP Aliases on
Bacula, you can control which one "Listening Sockets" bind to, but say
for example, when writing rules that would permit the Director to send
control messages to File Daemons, or Storage Daemons to send messages to
Directors, or Consoles to Directors, you want your rules to reflect the
source address of the service VIP for "new client sockets".

        Consider ISC BIND named(8): It's got all kinds of crazy options for
binding listening sockets for incoming requests and specifying the
source _port_ and _address_ for outbound connections the daemon is
making in the capacity of a "client":

Example:

options {
        directory "/";
        listen-on { 1.2.3.4/32; };
        query-source address 2.4.5.6 port 12346; 
        transfer-source 7.8.9.1; 
        notify-source 2.3.3.5;
        ....
}

All kinds of control.


-----------------

Secondly, "Socket Source Address/Port" v.s. "Routing"

These are *completely autonomous concepts*.  I just went through this
bringing "-b" from FreeBSD syslogd(8) over to NetBSD(8):

http://cvsweb.netbsd.org/bsdweb.cgi/src/usr.sbin/syslogd/syslogd.c.diff?r1=1.78&r2=1.79&f=h

Check out lines 2107->2111

This is an example with UDP, but the song remains the insane for TCP.

When you bind(2)/listen(2) a socket(2), there are two modes: Passive and
active.

The address which a socket listens/binds is wildcard by default.  You
can set it though with getaddrinfo(2)...intuitive function call name,
huh?!  >:}

Another good example are present in Apache's HTTP CVS:
     srclib/apr/network_io/unix/sockaddr.c

There's no reference to any of this in any of Stevens` because those
were all written before the advent of HA and Distributed Systems,
possibly even IP Aliases/VIPs.

Per my notes on "Service/System" abstraction, if a system has multiple
interfaces, there are two possibilities:

*) The interfaces could have addresses in different subnets
*) The interfaces could have addresses in the same subnets

        A system could also have multiple VIPs or "IP Aliases" (BSD) on the
same interface within the same Subnet (the most likely scenario).

        When you specifically bind the source address of an outgoing TCP socket
to a specific VIP or Primary IP on an interface, the decision as to
which interface to transmit the outgoing packets is not made in the TCP
code, it is made at the next layer down on the OSI model --  the
underlying IPv4/IPv6 protocol. 

        Example, if a system has two NICs.  One within a management subnet with
RFC1918 address space, we'll say 10.0.0.100, and another with two IPs, a
primary IP and a service VIP in a public subnet, we'll say 216.239.37.99
and 216.239.37.100.  
Consider the routing:

        Assume for the sake of sanity that the subnet masks on both interfaces
are /25 on the public interface and /23 on the RFC1918 interface.  Via
"Directly Connected Interfaces", the system knows about 216.239.37.0/25
via "Ext", and 10.0.0.0/23 via "Int".  It may also have a "Default
Gateway" configured of 215.239.37.1/32.  He may also know about a
greater 10.0.0.0/8 via a "Static Route" via some internal
router/firewall at 10.0.0.1 -- manually configured "route add -net
10.0.0.0/8 gw 10.0.0.1".

Obviously, the default semantics apply to most modern operating systems:

*) A layer 4 socket number discriminator is of course always required
for UDP/TCP, but not for ICMP/TCP/ESP/AH/etc.

*) For outbound UDP/ICMP/TCP/ESP/AH etc layer 3 protocols
(/etc/protocols) sockets, if the source address is not specified, the
layer 4 default address of the interface "closest" to the remote address
is used.

*) The layer 2 interface used for transmission is that of the one used
in the default layer 3 protocol address acquisition algorithm.  The
kernel makes this decision though based on the routing table and
weighted priories and metrics. I.e, connected > static > null > learned
via IGP/BGP (2)

*) The layer 3 address could be specified in the code / by the user, in
which case, a one of many VIPs within the same subnet on the same
interface could be used, but the layer 2 transmit interface remains the
same.

*) The exception to the previous two rules are as follows:

   -) The remote address of the outbound TCP socket is in a subnet
      known via "Directly Connected Route" on an interface other than
      the source address the user specified the local socket

   -) The remote address of the outbound TCP socket is in a subnet
      known by "Static Route" via a gateway/interface on an
      interface in a subnet other than the address of the local socket.

     In these instances, the behavior is OS independent, but connect(2)
     or bind(2) should fail miserably, even if functions themselves
     return successfully. (1)

*) For incoming passive listen sockets, if no bind address is specified,
it becomes a wildcard bind (examples: vintage inetd(8), etc.) --
unintelligent daemons like this were the reasons behind tcpwrappers.

1. Consider the routing:

        Assume for the sake of sanity that the subnet masks on the interfaces
are /25 on the public interface and /23 on the RFC1918 interface.  Via
"Directly Connected Interfaces", the system knows about 216.239.37.0/25
via "Ext", and 10.0.0.0/23 via "Int".  It may also have a "Default
Gateway" configured of 215.239.37.1/32.  He may also know about a
greater 10.0.0.0/8 via a "Static Route" via some internal
router/firewall at 10.0.0.1 -- manually configured "route add -net
10.0.0.0/8 gw 10.0.0.1".

        On this system, a random client program ("foo") could very easily bind
it's TCP socket source address to the VIP 216.239.37.100, then
connect(2) in active mode to a foreign destination address 10.0.3.101.
Or maybe tries to "ping -B 216.239.37.100 10.0.3.100".

        The operating system will very happily transmit that IPv4 packet
containing the TCP/ICMP packet out of the "Int" private interface with
the "Ext" VIP address as the source address.  That datagram makes its
way onto the ethernet segment.  As long as router 10.0.0.1/32, and all
of the corresponding routers en route to 10.0.3.101/32 are willing to
forward the packet (i.e., they know a return route to 216.239.37.100/32
via 10.0.0.100/32), it will actually work.

If they dont, the socket will time out tranmitting IPv4 packets (which
contain a TCP SYN packet) that 10.0.0.1/32 will discard due to perhaps a
BOGON list.

        Next, vanquish all thoughts about using a Linux kernel specific kernel
hacks like IPCHAINs.  Obviously a OS kernel-specific solution is not
optimal.  There are some cheap tricks that you could do with OpenBSD's
pf(4) as well, but I certainly wouldn't go recommending those to anyone.

Background on that:  

        A lot of this confusion is Linux's fault.

        I've seen some Linux-specific hacks that like to accept command line
arguments for "Transmit Interface", like "./foo.bar -interface=eth0".
This has a lot to do with the fact that Linux considers VIPs separate
logical interface structures, thus verily easily blurring the
distinction.

        Clearly, this is just a lot of smoke and mirrors around choosing a
proper source address for the socket/ICMP/ESP/layer 3 datagram.  

In summary: You cant control the "Transmit Interface", you can control
the layer 4 socket number and the layer 3 transmit address; -- the
kernel will make the outbound layer 2 physical interface encapsulation
for you, based on your directly connected routes, static routes, default
gateway, IGPs, etc.


2. See table: http://www.cisco.com/warp/public/105/21.html#building



Finally,  consider the practical examples:

*) Bconsole will almost always run on a workstation with a single IP
address with a single default gateway.  Outbound TCP connection source
address auto-determination applies 99% of time.  However, if for some
internal security policy compels it, the Administrator would certainly
enjoy the ability to source the Concsole->Dir socket from an alternative
VIP.

*) The FileDaemon running on a workstation will only use one source
address available to talk to Dir and StorageD.

*) The FileDaemon running a HA or multi-homed server will almost always
want to use it's "Management" address on a private/RFC1918 network to
initiate outbound TCP connections for:

- Messages from FileDir->Director (logs)
- Backup date from FileDir->StorageDir

However, there is always the remote but entirely reasonable possibility
that the server has a dedicated backup network interface in a subnet
that overlaps with a static route assigned to the Management network.
Example:  

"Ext0": 1.2.3.4/25.
"Default gw": 1.2.3.1/32
"Mngmnt0" 10.0.100.200/24"
"Static 10.0.0.0/8 via 10.0.100.1"
"Backup0":  10.0.200.200/24
"Storage Dir": 10.0.200.100/32

In this complicated but entirely possible scenario, being able to
specify the source address of the backup network interface helps the
kernel pick the proper transmit interface by allowing it to discriminate
the route known via directly connected over the metric/weight of the
static route.

*) And of course, the StorageDir->Director and Director->StorageDir
connections, which could reside in HA/Load-Balanced configurations, rely
on the source address of the remote host to authenticate.

Consider:

192.168.100.0/23

    [B-SD-Active .101][B-SD-Standby .102]
             [B-SD-HA VIP .100]
                     |
                     |
                    \ /
     Router   {192.168.100.1/32}
              {192.168.200.1/32}
                    / \
                     |
                     |
             [B-Dir-HA .100]
     [B-Dir-Active .101][B-Dir-Standby .102]
             


In this config, the HA VIP for both is an IfAlias on the active system.
When it transmits to the configured HA address of the SD or Dir
resource, the remote active will fail to authenticate because the source
address will be that of the Active "Primary IP" and not the service VIP.

Another great example of the need for source address specification is a
POSIX/Linux/BSD/UNIX system deployed as a remote VPN tunnel termination
point / router appliance.

Details:

- The remote private RFC1918 subnet is 172.16.100.0/24 at the branch
office.
- The local subnet at the HQ where the Dir/StorageD is is 172.16.99.0/24
- The HQ has a WAN connection 1.2.3.4, the Branch has a WAN connection
2.3.4.5
- The IPSEC/ISAKMP ACLs will stipulate 172.168.0.0/12 on the HQ side and
172.16.100.0/24 on the branch.
- When the branch office receives packets on it's internal interface
from LAN hosts matching 172.16.100.0/24 destined for 172.16.0.0/12, it
knows to ESP/AH them and transmit them out it's Ext., if not, NAT/PAT to
2.3.4.5/32
- However, the remote branch machine/router/appliance whatever, when
generating packets itself destined for 172.16.0.0/12 will not attempt to
ESP/AH encapsulate unless you specify a source address of it's internal
interface.  By default, kernel routing semantics will attempt to
transmit those packets out the Ext interface using NAT/PAT via the
default gateway.

Consider it: The kernel has no way of knowing any kind of inverse /
reverse routing decision such as: "Hey Locally initiated traffic
destined for a subnet I know via an ESP/GRE tunnel, use this source
address if you wish to qualify for the VPN ACL and reach your
destination." 

That simply doesn't work.

~BAS

> 
> In any event, unless I am misunderstanding something, Bacula has no mechanism 
> for controlling outgoing addresses.



-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Bacula-users mailing list
Bacula-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bacula-users

Reply via email to