IMPORTANT: Per accedir als fitxer de subversion: http://acacha.org/svn (sense password). Poc a poc s'aniran migrant els enllaços. Encara però funciona el subversion de la farga però no se sap fins quan... (usuari: prova i la paraula de pas 123456)

TwoISPs.png

Understanding Linux network internals

Introducció

Consideracions sobre les limitacions del balanceig de càrrega

Quan es balanceja transit els administradors sovint desitgen evitar haver de reordenar frames Ethernet. Per exemple, el protocol TCP sofreix una certa sobrecàrrega si ha de lidiar amb paquets desordenats. Aquest objectiu se sol assolir enviant tots els frames associats a una sessió particular a través del mateix link físic (el mateix port i cable). La implementació més comuna és utilitzar hashes de nivell 3 (L3 hashes), per exemple basats en la adreça IP, de forma que s'assegura que el mateix fluxe de dades és sempre enviat sencer pel mateix enllaç físic. El principal problema és però que depenent del transit, això pot resultar que no hi haguí distribució de la càrrega real entre els enllaços físics ja que de fet l'ampla de banda no es suma, sinó que per a un mateix client i sessió el màxim de velocitat que es pot obtenir està limitat a la velocitat màxima de l'únic l'enllaç físic que acaba utilitzant aquell client i aquella sessió.

Aquesta és la raó principal per la que normalment una distribució de la carrega 50/50 no s'assoleix gaire bé mai si no més aviat un 70/30 és més habitual.

Alguns switchos avançats poden utilitzar un L4 hash (p.ex. els números de port TCP/UDP) que permet millorar l'experiència de balanceigi apropar-la al 50/50.

Balanceig de càrrega ip2route i iptables

La clau és remarcar els paquets que són d'una mateixa connexió!!!:

Trànsit de sortida a diferents gateways!!!:

-A PREROUTING          -m state --state ESTABLISHED,RELATED -j CONNMARK --restore-mark

Trànsit d'entrada a un servidor, sempre s'ha de tornar per la mateixa connexió d'entrada:

-A OUTPUT              -m state --state ESTABLISHED,RELATED -j CONNMARK --restore-mark

Compte amb rp_filter:

echo 0 > /proc/sys/net/ipv4/conf/YOURINTERFACE/rp_filter 

Consulteu rp_filter.


Multirouter rules are a tool that enables PCs in a network to use several Internet connections transparently. This is useful if, for example, an office has several ADSL connections and the entire bandwidth available is to be used without having to worry about distributing the work of the hosts manually between both routers, so that the load is shared automatically between them.

Basic load balancing evenly distributes the packets transferred from eBox to the Internet. The simplest form of configuration involves establishing different weights for each router so that, if the connections available have different capacities, they can be used optimally.

Multirouter rules allow for certain traffic types to be sent permanently by the same router, where required. Common examples include sending emails through a certain router or ensuring that a certain subnet is always routed from the Internet through the same router.

eBox uses the iproute2 and iptables tools for the configuration required for the multirouter function. iproute2 informs the kernel of the availability of several routers. For multirouter rules, iptables is used to mark the packets of interest. These marks can be used from iproute2 to determine the router through which a packet must be sent.

There are several possible problems that must be considered. Firstly, the connection concept does not exist in iproute2. Therefore, with no other type of configuration, the packets belonging to the same connection could end up being sent by different routers, making communications impossible. To solve this, iptables is used to identify the different connections and ensure that all the packets of a connection are sent via the same router.

The same applies to any incoming connections established. All response packets for a connection must be sent using the same router through which that connection was received.

To establish a multirouter configuration with load balancing in eBox, as many routers as required must be defined in Network ‣ Routers. Using the weight parameter when configuring a router, it is possible to determine the proportion of packets that each one will send. Where two routers are available and weights of 5 and 10, respectively, are established, 5 of every 15 packets will be sent through the first router, while the the remaining 10 will be sent via the second.

Interfícies dummy

És necessària una ruta tonta a la taula per defecte?

ifconfig dummy0 1.2.3.4
ip route add default dev dummy0

rp_filter

Disable rp_filter

Why aren't the packets coming back? I was scratching my head for a little while with this one. Correctly addressed packets going out the interface, yet nothing coming back. Setting the default route of the main table to point out the interface instantly fixes this, but that sort of defeats the purpose really, doesn't it? If I've understood correctly, this problem happens because the test done on incoming packets as to whether they are bogus is applied from the main table, and no others. Your main table will point to at most one place, so the others won't, by default, work. Here's how you fix it:


echo 0 > /proc/sys/net/ipv4/conf/YOURINTERFACE/rp_filter

Load Balancing Linux

http://blog.taragana.com/index.php/archive/how-to-load-balancing-failover-with-dual-multi-wan-adsl-cable-connections-on-linux/

Balance

$ sudo apt-get install balance

Exemple d'ús

$ balance smtp host1.test.net host2.test.net
             Connection to the local SMTP port will be forwarded alterating to the SMTP port on host1 and host2.  Balance runs  automatically  in  back‐
             ground.

Vegeu:

$ man balance

Provat a guifi.net per crear un proxy virtual que balanceja la connexió a diferents proxies:


Kilian ha configurado un balanceo sobre una ip virtual con una
> aplicacion llamanda balance, que se desprende de una suite de balanceo
> mas compleja llamada balanceng.
>
> Si tu apuntas a esa ip virtual y a ese puerto , por detras hay un
> algoritmo de reparticion de conexiones (round robin) entre varios proxys
> de Terrassa y si alguno cae, de manera transparente te conectas al
> siguiente.
>
> De esta manera no has de recordar todas las ips, y con que te sepas la
> virtual ya te vale (aunque esta claro que puedes seguir conectandote
> directamente a un proxy determinado si asi lo quieres)
>
> Slds!

Microtik

Recursos:

Linux. Taules de rutes

Planteemos la situación:

Mi empresa tiene 2 adsl, repartidos como dios le dio a entender, es decir, cada uno tiene configurado de puerta de enlace uno de los dos pero de manera aleatoria. Como os podeis imaginar esto no es solución, ya que cuando se caia un adsl todo el mundo que tubiera ese adsl como puerta de enlace dejaba de tener internet. Tenemos un adsl de 4 megas y otro de 20 megas (bueno teoricos).

Bien, la solución fue el balanceo de carga con los dos adsl, y que ademas asignara diferentes pesos a cada una de las conexiones, para dar mas carga a un adsl que otro. No me voy a parar mucho en explicar los conceptos de redes, asi que puede ser algo "duro" de leer...

Yo pense que esto iba a ser complicado, pero no fue asi. Cogi una maquina antigua, un Pentium III a 733 con 1 Gb y 3 tarjetas ethernet. Instalé una ubuntu como servidor (al final usaremos Debian, ya que recomiendan un Kernel 2.4 para la estabilidad o algo asi... pero con Ubuntu funciona igual de bien). Hay que instalar el paquete "iproute2", con esto tendremos un monton de comandos nuevos que permiten trastear a nivel 3, vamos a nivel IP, con tu linux. A destacar el comando "tc" que te permite hacer un QoS de manera muy sencillita.

Bueno a lo que ibamos:

1.) Tenemos 3 tarjetas ethernet: eth0, eth1, eth2. donde:

eth0 (192.168.0.x) -> red privada (192.168.0.0/24)
eth1 (10.10.10.2) -> adsl1 (10.10.10.1)
eth2 (10.10.11.2) -> adsl2 (10.10.11.1)

Mi maquina que funcionara para balancear carga tiene esta topologia de red, como veis usa 3 subredes. Hay que destacar que la conexion entre los routers de adsl y la maquina, pueden ser cables directamente conectados, o usar un switch... eso depende de los cacharros que tengas por alli algooooo

2.) Comprobamos que tenemos el comando "ip", si no es asi, mira si has instalado el paquete "iproute". Este comando nos permitirá hacer las rutas y el balanceo de carga.

3.) Inserta esto:

# echo 200 adsl1 >> /etc/iproute2/rt_tables
# echo 201 adsl2 >> /etc/iproute2/rt_tables

Esto nos introduce dos nuevas tablas de enrutamiento llamadas "adsl1" y "adsl2", con esos numeros asociados (mira los que ya estan en uso haciendo un "more /etc/iproute2/rt_tables" y asi no machacar ninguna tabla). Asi podremos definir reglas diferente para cada uno de los adsl sin hacer todo un lio, y ademas poder saber en todo momento que estamos haciendo.

4.) Definimos el enrutamiento de adsl1:

# ip route add 10.10.10.0/24 dev eth1 src 10.10.10.2 table adsl1
# ip route add default via 10.10.10.1 table adsl1

Esto le dice que la red 10.10.10.0 es la red de mi interfaz eth1 con la salida por el adsl. Compruebalo mediante: ip route show table adsl1

5.) Definimos el enrutamiento del adsl2:

# ip route add 10.10.11.0/24 dev eth2 src 10.10.11.2 table adsl2
# ip route add default via 10.10.11.1 table adsl2

Idem a lo anterior.

6.) Poner las rutas principales:

# ip route add 10.10.10.0/24 dev eth1 src 10.10.10.2
# ip route add 10.10.11.0/24 dev eth2 src 10.10.11.2

Date cuenta que ahora no decimos en que tabla meterlo, por lo que se mete en la tabla principal. Lo anterior era para cuando el trafico ya esta en una de las dos subredes de salida y necesitamos saber como enrutarlo. En cambio las segundas son las primeras reglas para que funcione y las envie dondo debe.

7.) ¿Donde mando esto?

# ip rule add from 10.10.10.2 table adsl1
# ip rule add from 10.10.11.2 table adsl2

Esto sirve para aplicar las reglas almacenadas en cada una de las tablas cuando se cumple que vienen de esas ips.

8.) La madre del cordero: Balanceo de carga.

ip route add default scope global nexthop via 10.10.10.2 dev eth1 weight 1 nexthop via 10.10.11.2 dev eth2 weight 2

Como ves, le he dicho: "Usa eth1 1 de cada 3 veces, sino usa eth2 2 de cada 3 veces".

Solo existe un problema. Las rutas son cacheadas, es decir, si tu pides "www.google.es" y se enruta por adsl1, la siguiente vez, hasta que caduque el cacheo, ira por adsl1... Esto es malo... Ya que si adsl1 se cae, las rutas cacheadas fallaran, aunque adsl2 este disponible, si no estan cacheadas iran por adsl2.

Para solucionarlo, habria que parchear el kernel, segun estos parches: http://www.ssi.bg/~ja/#routes Aunque con hacer: ip route flush se podria arreglar de manera manual.

Solució sense parxejar el kernel

#!/bin/bash
#Copyright Angsuman Chakraborty, Taragana. Permission is granted for personal, non-commercial use.
#The script may not be re-distributed in any form without written permission from Angsuman Chakraborty ( angsuman@taragana.com ).
#The script may be modified for personal use.
#THIS SOFTWARE IS PROVIDED ``AS IS AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF   
MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHOR ACCEPTS NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.

# Conventionally 0 indicates success in this script.

# Time between checks in seconds
SLEEPTIME=10

#IP Address or domain name to ping. The script relies on the domain being 
#pingable and always available
TESTIP=www.yahoo.com

#Ping timeout in seconds
TIMEOUT=2

# External interfaces
EXTIF1=eth1
EXTIF2=eth2

#IP address of external interfaces. This is not the gateway address.
IP1=192.168.1.10
IP2=192.168.0.10

#Gateway IP addresses. This is the first (hop) gateway, could be your router IP 
#address if it has been configured as the gateway
GW1=192.168.1.1
GW2=192.168.0.1
 
# Relative weights of routes. Keep this to a low integer value. I am using 4
# for TATA connection because it is 4 times faster
W1=1
W2=4
 
# Broadband providers name; use your own names here.
NAME1=BSNL
NAME2=TATA 

#No of repeats of success or failure before changing status of connection
SUCCESSREPEATCOUNT=4
FAILUREREPEATCOUNT=1  

# Do not change anything below this line 

# Last link status indicates the macro status of the link we determined. This is down initially to force routing change upfront. Don't change these   
values .
LLS1=1
LLS2=1 

# Last ping status. Don't change these values.
LPS1=1
LPS2=1  

# Current ping status. Don't change these values.
CPS1=1
CPS2=1 

#   Change link status indicates that the link needs to be changed. Don't change these values.
CLS1=1
CLS2=1

# Count of repeated up status or down status. Don't change these values.
COUNT1=0
COUNT2=0 

while : ; do
        ping -W $TIMEOUT -I $IP1 -c 1 $TESTIP > /dev/null  2>&1
        RETVAL=$?  

        if [ $RETVAL -ne 0 ]; then 
		echo $NAME1 Down
		CPS1=1
       else
		CPS1=0
       fi

if [ $LPS1 -ne $CPS1 ]; then

		echo Ping status changed for $NAME1 from $LPS1 to $CPS1
		COUNT1=1
	else
		if [ $LPS1 -ne $LLS1 ]; then
			COUNT1=`expr $COUNT1 + 1`
		fi
	fi

       if | ($LLS1 -eq 0 && $COUNT1 -ge $FAILUREREPEATCOUNT) ; then
		echo Uptime status will be changed for $NAME1 from $LLS1
		CLS1=0
		COUNT1=0
		if [ $LLS1 -eq 1 ]; then
			LLS1=0
		else
			LLS1=1
		fi
	else 
		CLS1=1
        fi

	LPS1=$CPS1

	ping -W $TIMEOUT -I $IP2 -c 1 $TESTIP > /dev/null  2>&1
       	RETVAL=$?

	if [ $RETVAL -ne 0 ]; then
		echo $NAME2 Down
                CPS2=1
        else
                 CPS2=0
       fi

       if [ $LPS2 -ne $CPS2 ]; then
		echo Ping status changed for $NAME2 from $LPS2 to $CPS2
               COUNT2=1
       else
               if [ $LPS2 -ne $LLS2 ]; then
                       COUNT2=`expr $COUNT2 + 1`
               fi
       fi

       if | ($LLS2 -eq 0 && $COUNT2 -ge $FAILUREREPEATCOUNT) ; then
		echo Uptime status will be changed for $NAME2 from $LLS2
		CLS2=0
		COUNT2=0
                if [ $LLS2 -eq 1 ]; then
                       LLS2=0
               else
                       LLS2=1
               fi
	else
		CLS2=1
       fi

	LPS2=$CPS2

	if | $CLS2 -eq 0 ; then
		if  $LLS1 -eq 1 && $LLS2 -eq 0 ; then 
			echo Switching to $NAME2
                        ip route replace default scope global via $GW2 dev $EXTIF2
		elif  $LLS1 -eq 0 && $LLS2 -eq 1 ; then
			echo Switching to $NAME1
                        ip route replace default scope global via $GW1 dev $EXTIF1
		elif  $LLS1 -eq 0 && $LLS2 -eq 0 ; then
			echo Restoring default load balancing
                        ip route replace default scope global nexthop via $GW1 dev $EXTIF1 weight $W1 nexthop via $GW2 dev $EXTIF2 weight $W2
 		fi
	fi
        sleep $SLEEPTIME
done

Vegeu també

IPCOP

PFSENSE

Consulteu l'article sobre PFSENSE

Shorewall

DD-WRT

RouterOS

Linkat

Script de comprovació i baixa de rutes

#!/bin/bash
#
# Autor: Victor Carceler
#
# Licencia: GPLv3 o posterior
#
# Función:
#
#    Monitorizar el estado de los diferentes enlaces y dar de baja/alta
#    routers en la ruta por defecto de forma dinámica

PROGNAME=`basename $0`
#
# TESTIP: IP objectiu que s'utilitza per saber si han caigut els gateways
#         213.176.161.13 es la IP associada a: www.xtec.cat
#
TESTIP=213.176.161.13
PINGTIMEOUT=20

#
# IPs i portes de sortida del balancejador
#
IP1=192.168.0.33
IP2=192.168.1.33
GTW1=192.168.0.1
GTW2=192.168.1.1

GATEWAY_PING_SRC=($IP1 $IP2)
GATEWAY_LIST=($GTW1 $GTW2)
GATEWAY_WEIGHT_LIST=(1 1)

SLEEP=60

N_GATEWAYS=`echo ${GATEWAY_LIST[@]} | wc -w`
N_GATEWAYS=`expr $N_GATEWAYS - 1`

last_hopes=""

while true
do
hopes=""
for x in `seq 0 1 $N_GATEWAYS`
do
    ping -W $PINGTIMEOUT -I ${GATEWAY_PING_SRC[$x]} -c 1 $TESTIP >/dev/null 2>/dev/null

        RETVAL=$?

    if [ $RETVAL -eq 0 ]
    then
        hopes="$hopes nexthop via ${GATEWAY_LIST[$x]} weight ${GATEWAY_WEIGHT_LIST[$x]}"
    fi
done

if [ "$last_hopes" != "$hopes" ]
then
    logger "$PROGNAME: Cambiamos la ruta por defecto a: $hopes"

    logger "$PROGNAME: Valor anterior:  $last_hopes"

    logger "$PROGNAME: ip route replace default scope global $hopes"
    ip route replace default scope global $hopes
    last_hopes=$hopes
fi

sleep $SLEEP
done


Consulteu també

Consulteu els següents articles:



Squid i tcp_outgoing address

Vegeu també Xarxes_Linux#DNAT_i_multigateway i RouterOS_Policy_routing#Policy_routing.2C_combinant_Squid.2C_routerOS.2FROuterboard_i_varies_ADSLs_o_sortides_a_Internet._Projecte_OpenFPnet

Amb la directiva tcp_outgoing_address, podem canviar la IP d'origen del paquet que surt de l'Squid a l'hora de buscar una pàgina d'Internet. Combinant-ho amb Policy Routing (Source Policy Routing), podem encaminar per diferents gateways diferents peticions a un servidor Squid.

IMPORTANT: Si teniu un encaminador sense squid podeu utilitzar directament Policy Routing. Si utilitzeu Squid heu de recordar que qui es connecta a Internet no són mai els clients, sinó que és el proxy Squid qui fa de intermediari (d'aquí que Proxy es tradueixi habitualment com a servidor intermediari). Per tant el policy routing si és per Ip d'origen no s'aplica (totes les peticions de l'squid tenen la mateixa Ip d'origen: la de la targeta de xarxa del servidor squid que està connectada a Internet!)

A /etc/squid3/squid.conf cal posar quelcom similar a (cal adaptar l'exemple al vostre cas):

acl prova src 127.0.0.1
tcp_outgoing_address 80.32.57.101 prova

acl in_192_168_11_2 myip 192.168.11.2
tcp_outgoing_address 192.168.11.2 in_192_168_11_2
acl in_80_32_57_101 myip 80.32.57.101
tcp_outgoing_address 80.32.57.101 in_80_32_57_101
acl in_192_168_1_5 myip 192.168.1.5
tcp_outgoing_address 192.168.1.5 in_192_168_1_5

On

acl prova src 127.0.0.1
tcp_outgoing_address 80.32.57.101 prova

Tots els clients que compleixen la ACL prova (és a dir tinguin la IP d'origen 127.0.0.1, en aquest cas localhost!) utilitzaran com IP d'origen 80.32.57.101 (aquesta IP ha de ser un IP correcta d'alguna de les targetes de xarxa de l'squid)

On:

  • 192.168.11.2: Ip de la interficie connectada a internet1
  • 80.32.57.101: Ip de la interficie connectada a internet2
  • 192.168.1.5: Intranet

Fa que les peticions demanades des de localhost, es posi com a IP d'origen la IP 80.32.57.101. Si ara no canviem res mes una petició des de 127.0.0.1 no funcionarà ja que la taula de rutes per defecte és:

$ sudo route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
80.32.57.64     0.0.0.0         255.255.255.192 U     0      0        0 internet2
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 intranet
192.168.11.0    0.0.0.0         255.255.255.0   U     0      0        0 internet1
0.0.0.0         192.168.11.1    0.0.0.0         UG    0      0        0 internet1

És a dir s'enviarà un paquet amb la IP d'origen 80.32.57.101 per la targeta de xarxa internet1! El que tocaria és que fos internet2. Cal tenir en compte però que les decisions de rutes es prenen segons la IP de destinació i no pas la d'origen. Com la IP de destinació és una màquina d'Internet aleshores surt per la targeta on esta el default gateway (internet1).

Podeu comprovar que surt per una targeta o que surt per un altre amb:

$ sudo tcpdump -n -i internet1
$ sudo tcpdump -n -i internet2

Ara cal configurar Policy routing:

A Policy routing cal dos taules de rutes extres (internet1 i internet2) i tenir les normes:

$ sudo ip rule list
0:	from all lookup local 
32758:	from 80.32.57.101 lookup internet2 
32759:	from 192.168.11.2 lookup internet1
...

Les podeu afegir amb:

$ sudo ip rule add from 80.32.57.101 table internet2
$ sudo ip rule add from 192.168.11.2 table internet1

Cal que també configureu les rutes de les taules internet1 i internet2 per tal de tenir:

$ sudo ip route list table internet1
192.168.1.0/24 dev intranet  scope link  src 192.168.1.5 
default via 192.168.11.1 dev internet1 
$ sudo ip route list table internet2
192.168.1.0/24 dev intranet  scope link  src 192.168.1.5 
default via 80.32.57.65 dev internet2 





Consulteu també Squid.

Enllaços externs