Re: selecting interface for traffic

Marius Tomaschewski <[email protected]> Fri, 19 Jul 2002 04:21:39 +0200
Newsgroups gmane.linux.suse.proxy-suite
Organization MaT's Home
Message-ID <[email protected]>
On Thu, Jul 18, 2002 at 06:17:58PM +0100, David Watson wrote:
> 
> 
> 	I run proxy-suite on my firewall, it listens on the inside 
> 	(192.168.1.1 eth0 ) and works great as a transparent proxy.
> 
> 	The firewall has 2 external interfaces (eth1 and eth2) which both 
> 	connect to the internet over different links. I would like to have all the 
> ftp traffic go over eth2 but ftp-proxy uses eth1, is there any way to 
> control this without resorting to iptables (MARK) and ip rules ?

No, there is currently no option to setup this, but it is
possible to bind a particular device using setsockopt(2).

see socket(7):

       SO_BINDTODEVICE
              Bind  this  socket  to  a  particular  device  like
              "eth0",  as specified in the passed interface name.
              If the name is an empty string or the option length
              is  zero, the socket device binding is removed. The
              passed option is a variable-length null  terminated
              interface  name  string  with  the  maximum size of
              IFNAMSIZ.  If a socket is bound  to  an  interface,
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
              only  packets  received from that particular inter­
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
              face are processed by the socket.  Note  that  this
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
              only  works  for  some  socket  types, particularly
              AF_INET sockets. It is  not  supported  for  packet
              sockets (use normal bind(8) there).

So if the data goes out via eth2 and comes back via eth1,
the transfer will fail if the socket is bound to device...

Are you using one IP address on both interfaces (some kind
of multipath configuration) or two different IP's?

In Attachement you can find a patch (against v1.9, but may
work also with v1.8.x) you can try out...
It binds the control connection socket to the interface
set using DestinationInterface in config file...:

DestinationInterface  eth2
# to see messages about successfull binding to interface:
LogLevel DBG

The data connection sockets are using the IP address from
the control connection socket (on the server's side)...

> 	My config is below, any help is greatly appreciated.
> 
> [-Global-]
> AllowMagicUser  yes
> AllowTransProxy yes
> DestinationTransferMode passive
> Group                   nobody
> Listen          192.168.1.1
> LogDestination  /var/log/ftp-proxy/ftp-proxy.log
> MaxRecvBufSize  8192
> PidFile         /var/run/ftp-proxy.pid
> ServerType              standalone
> User                    ftp-proxy
> _____________________________________________________________

Kind regards,
 Marius Tomaschewski <[email protected]>
--
 SuSE Linux AG, NÃŒrnberg - SuSE Labs, Product Developement
 PGP public key available:   http://www.suse.de/~mt/mt.pgp
 Fprint:  EA 1F 92 75 1A F9 82 07  A1 28 DE 7A 32 E8 97 18

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
bind_to_device.dif (text/plain, 1.2 KB)
--- proxy-suite-1.9/ftp-proxy/ftp-client.c
+++ proxy-suite-1.9/ftp-proxy/ftp-client.c	Fri Jul 19 03:58:24 2002
@@ -64,6 +64,7 @@
 #include <netinet/in.h>
 #include <sys/socket.h>
 #include <arpa/inet.h>
+#include <net/if.h>
 
 #include "com-config.h"
 #include "com-debug.h"
@@ -1171,6 +1172,7 @@
 	struct sockaddr_in saddr;
 	u_int16_t          lprt, lowrng, res;
 	int                sock, incr, retry;
+	char              *ifptr;
 
 	/*
 	** should we bind a rand(port-range) or increment?
@@ -1198,6 +1200,26 @@
 		}
 		socket_opts(sock, SK_CONTROL);
 
+#if defined(SO_BINDTODEVICE)
+		ifptr = config_str(NULL, "DestinationInterface", NULL);
+		if(NULL != ifptr && ifptr[0]) {
+			char ifname[IFNAMSIZ] = {'\0'};
+
+			misc_strncpy(ifname, ifptr, sizeof(ifname));
+			if(0 == setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
+			                   ifname, sizeof(ifname)))
+			{
+				syslog_write(T_DBG,
+				             "Srv-Ctrl: socket bound to '%s'",
+				             ifname);
+			} else {
+				syslog_write(T_WRN,
+				             "Srv-Ctrl: can't boind to '%s'",
+				             ifname);
+			}
+		}
+#endif
+
 		/*
 		** check if we have to take care to a port range
 		*/