Alejandro Vargas
2010-12-02 09:38:19 UTC
Les quiero pasar pro si a alguien le sirve, un script que estuve haciendo.
Primero les cuento de qué se trata:
Resulta que Linux decide, como es razonable, por donde sacar los
paquetes en función de las tablas de ruteo. Supongamos que tenemos la
eth0 con la dirección 1.2.3.4. Si llega un paquete proveniente de
5.6.7.8, dirigido a la 1.2.3.4, cuando lo vaya a responder buscará la
ruta por defecto y enviará un paquete con IP de origen=1.2.3.4
destinado a la ruta por defecto. Eso lo sabemos todos.
Ahora bien, supongamos que tenemos la eth1 con ip 192.168.1.1 y por
algún motivo, llega un paquete proveniente de 5.6.7.8 destinado a
192.168.1.1. Esto puede ocurrir, por ejemplo, porque tengamos un
segundo acceso a internet. O, por ejemplo, porque tengamos una VPN
establecida contra otro lugar, y desde ese otro lugar nos redirijan un
puerto. Qué pasará con la respuest a ese paquete? Nos llegó por la
eth1, pero la respuesta tratará de salir, tal como dice la tabla de
ruteo, por la 5.6.7.8. Cosa que obviamente no funcionará porque saldrá
con IP de origen 192.168.1.1 por una red que no maneja esas
direcciones.
Gráficamente:
caso 1 (ok):
5.6.7.8 ------eth0---> 1.2.3.4
1.2.3.4 ------eth0---> 5.6.7.8
Caso 2 (fala):
5.6.7.8 -----eth1---> 192.168.1.1
192.168.1.1 ----eth0----> 5.6.7.8
Para evitar esto, podemos hacer ruteo avanzado creando varias tablas
de ruteo diferentes en lugar de usar una sola. Seleccionamos la tabla
de ruteo en función de la IP de origen del paqute. En este caso, como
la IP de origen era 192.168.1.1, no se usaría la tabla que dice que la
ruta por defecto es por la eth0 sino la que corresponda.
Lo que a mi me extraña es por qué las distribuciones no hacen esto por
defecto. Al menos hasta donde yo he visto no hay una configuración o
un paquete que reemplace los scripts normales que configuran la red.
Estaba pensando en modificar por ejemplo el
/etc/sysconfig/network-scripts/network-functions que contiene las
funciones que se usan para crear las rutas y configurar las IPs en
función de los arhcivos de configuración
(/etc/sysconfig/network-scripts/ifcfg-* pero lo que he hecho primero
es un script sencillo que crea las rutas automáticamente.
Se los paso por si a alguien le sirve, y de paso para iniciar una
charla al respecto y ver cómo está la situación en otras
distribuciones.
A continuación mi script "rc.autoadvrouting". Este script lo que hace
es recorrer los archivos ifcfg-xxxx y para cada uno de ellos crea una
tabla nueva de ruteo. Las genera con el número 1001, 1002, 1003, etc.
En cada una de ellas pone las reglas necesarias para acceder a todas
las redes que haya disponibles, y una ruta por defecto. Con este
script se resuelve la situación que planteé antes y otras parecidas.
NO agrega balanceo por las diferentes rutas por defecto sino que usa
la que esté en la talbla main.
En este ejemplo, tengo 3 placas de red, una con 1.2.3.4 (eth0), otra
con 192.168.100.1 (eth1) y otra con 192.168.101.1 (eth2) a demás de la
loopback.
Ejemplo de /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=static
IPADDR=1.2.3.4
NETMASK=255.255.255.240
GATEWAY=1.2.3.5
ONBOOT=yes
METRIC=10
MII_NOT_SUPPORTED=no
USERCTL=no
DNS1=127.0.0.1
RESOLV_MODS=no
IPV6INIT=no
IPV6TO4INIT=no
ACCOUNTING=no
Tabla resultante:
# ip route show table 1001
1.2.3.0/28 dev eth0 scope link src 1.2.3.4
192.168.100.0/24 dev eth1 scope link
192.168.101.0/24 dev eth2 scope link
127.0.0.0/8 dev lo scope link
default via 1.2.3.4 dev eth0
También se agregan las siguientes reglas de ruteo:
# ip rule show
0: from all lookup local
32752: from all fwmark 0x3ec lookup 1004
32753: from 127.0.0.1 lookup 1004
32754: from all fwmark 0x3eb lookup 1003
32755: from 192.168.101.1 lookup 1003
32756: from all fwmark 0x3ea lookup 1002
32757: from 192.168.100.1 lookup 1002
32758: from all fwmark 0x3e9 lookup 1001
32759: from 1.2.3.4 lookup 1001
32766: from all lookup main
32767: from all lookup default
Las tablas 1002, 1003 y 1004 tienen algo parecido sólo que o no tienen
default o lo tienen por un camino diferente.
Como se puede ver, agrega reglas que dicen from (ip de la placa)
lookup (tabla hecha para esa placa de red) pero a demás agrega unas
reglas que filtran por la marca del paquete, por ejemplo from all
fwmarc 1001 lookup 1001 (en el ip rule show sale en hexadecimal). Esto
lo puse por si queremos usar iptables para forzar el uso de alguna de
estas tablas Por ejemplo algo así:
iptables -A PREROUTING -i eth2 -t mangle -s 192.168.100.123 -j MARK
--set-mark 1002
iptables -A PREROUTING -i eth2 -t mangle -s ! 192.168.100.234 -p tcp
--dport 25 -j MARK --set-mark 1001
A continuación el script (necesita ipcalc para funcionar).
¿Comentarios, sugerencias? ¿alguna idea de cómo limpiar las "ip rules"
agregadas previamente para que si se vuelve a ejecutar el script no
las agregue de nuevo? Tal vez borrar todo y crear de nuevo las talbas
local, main y default...
--------------------
cuenta=0
for ifcfg in /etc/sysconfig/network-scripts/ifcfg-*
do
cuenta=$(( cuenta + 1 ))
TABLE=100$cuenta
. $ifcfg
#echo "DEVICE=$DEVICE"
export `ipcalc -n $IPADDR $NETMASK`
NET=$NETWORK/$NETMASK
ip route flush table $TABLE
ip route add $NET dev $DEVICE src $IPADDR table $TABLE
if [ "$GATEWAY" != "" ]
then
ip route add default via $GATEWAY table $TABLE
fi
ip route add $NETWORK dev $DEVICE src $IPADDR
#ip rule flush >=0 y <=32766??
ip rule add from $IPADDR table $TABLE
ip rule add fwmark $TABLE table $TABLE
tables="$tables $TABLE"
if [ "$GATEWAY" != "" ]
then
ip route add default via $GATEWAY table $TABLE
fi
done
for TABLE in $tables
do
for ifcfg in /etc/sysconfig/network-scripts/ifcfg-*
do
. $ifcfg
export `ipcalc -n $IPADDR $NETMASK`
NET=$NETWORK/$NETMASK
ip route add $NET dev $DEVICE table $TABLE
done
done
echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter
ip route flush cache
------------------------
Primero les cuento de qué se trata:
Resulta que Linux decide, como es razonable, por donde sacar los
paquetes en función de las tablas de ruteo. Supongamos que tenemos la
eth0 con la dirección 1.2.3.4. Si llega un paquete proveniente de
5.6.7.8, dirigido a la 1.2.3.4, cuando lo vaya a responder buscará la
ruta por defecto y enviará un paquete con IP de origen=1.2.3.4
destinado a la ruta por defecto. Eso lo sabemos todos.
Ahora bien, supongamos que tenemos la eth1 con ip 192.168.1.1 y por
algún motivo, llega un paquete proveniente de 5.6.7.8 destinado a
192.168.1.1. Esto puede ocurrir, por ejemplo, porque tengamos un
segundo acceso a internet. O, por ejemplo, porque tengamos una VPN
establecida contra otro lugar, y desde ese otro lugar nos redirijan un
puerto. Qué pasará con la respuest a ese paquete? Nos llegó por la
eth1, pero la respuesta tratará de salir, tal como dice la tabla de
ruteo, por la 5.6.7.8. Cosa que obviamente no funcionará porque saldrá
con IP de origen 192.168.1.1 por una red que no maneja esas
direcciones.
Gráficamente:
caso 1 (ok):
5.6.7.8 ------eth0---> 1.2.3.4
1.2.3.4 ------eth0---> 5.6.7.8
Caso 2 (fala):
5.6.7.8 -----eth1---> 192.168.1.1
192.168.1.1 ----eth0----> 5.6.7.8
Para evitar esto, podemos hacer ruteo avanzado creando varias tablas
de ruteo diferentes en lugar de usar una sola. Seleccionamos la tabla
de ruteo en función de la IP de origen del paqute. En este caso, como
la IP de origen era 192.168.1.1, no se usaría la tabla que dice que la
ruta por defecto es por la eth0 sino la que corresponda.
Lo que a mi me extraña es por qué las distribuciones no hacen esto por
defecto. Al menos hasta donde yo he visto no hay una configuración o
un paquete que reemplace los scripts normales que configuran la red.
Estaba pensando en modificar por ejemplo el
/etc/sysconfig/network-scripts/network-functions que contiene las
funciones que se usan para crear las rutas y configurar las IPs en
función de los arhcivos de configuración
(/etc/sysconfig/network-scripts/ifcfg-* pero lo que he hecho primero
es un script sencillo que crea las rutas automáticamente.
Se los paso por si a alguien le sirve, y de paso para iniciar una
charla al respecto y ver cómo está la situación en otras
distribuciones.
A continuación mi script "rc.autoadvrouting". Este script lo que hace
es recorrer los archivos ifcfg-xxxx y para cada uno de ellos crea una
tabla nueva de ruteo. Las genera con el número 1001, 1002, 1003, etc.
En cada una de ellas pone las reglas necesarias para acceder a todas
las redes que haya disponibles, y una ruta por defecto. Con este
script se resuelve la situación que planteé antes y otras parecidas.
NO agrega balanceo por las diferentes rutas por defecto sino que usa
la que esté en la talbla main.
En este ejemplo, tengo 3 placas de red, una con 1.2.3.4 (eth0), otra
con 192.168.100.1 (eth1) y otra con 192.168.101.1 (eth2) a demás de la
loopback.
Ejemplo de /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=static
IPADDR=1.2.3.4
NETMASK=255.255.255.240
GATEWAY=1.2.3.5
ONBOOT=yes
METRIC=10
MII_NOT_SUPPORTED=no
USERCTL=no
DNS1=127.0.0.1
RESOLV_MODS=no
IPV6INIT=no
IPV6TO4INIT=no
ACCOUNTING=no
Tabla resultante:
# ip route show table 1001
1.2.3.0/28 dev eth0 scope link src 1.2.3.4
192.168.100.0/24 dev eth1 scope link
192.168.101.0/24 dev eth2 scope link
127.0.0.0/8 dev lo scope link
default via 1.2.3.4 dev eth0
También se agregan las siguientes reglas de ruteo:
# ip rule show
0: from all lookup local
32752: from all fwmark 0x3ec lookup 1004
32753: from 127.0.0.1 lookup 1004
32754: from all fwmark 0x3eb lookup 1003
32755: from 192.168.101.1 lookup 1003
32756: from all fwmark 0x3ea lookup 1002
32757: from 192.168.100.1 lookup 1002
32758: from all fwmark 0x3e9 lookup 1001
32759: from 1.2.3.4 lookup 1001
32766: from all lookup main
32767: from all lookup default
Las tablas 1002, 1003 y 1004 tienen algo parecido sólo que o no tienen
default o lo tienen por un camino diferente.
Como se puede ver, agrega reglas que dicen from (ip de la placa)
lookup (tabla hecha para esa placa de red) pero a demás agrega unas
reglas que filtran por la marca del paquete, por ejemplo from all
fwmarc 1001 lookup 1001 (en el ip rule show sale en hexadecimal). Esto
lo puse por si queremos usar iptables para forzar el uso de alguna de
estas tablas Por ejemplo algo así:
iptables -A PREROUTING -i eth2 -t mangle -s 192.168.100.123 -j MARK
--set-mark 1002
iptables -A PREROUTING -i eth2 -t mangle -s ! 192.168.100.234 -p tcp
--dport 25 -j MARK --set-mark 1001
A continuación el script (necesita ipcalc para funcionar).
¿Comentarios, sugerencias? ¿alguna idea de cómo limpiar las "ip rules"
agregadas previamente para que si se vuelve a ejecutar el script no
las agregue de nuevo? Tal vez borrar todo y crear de nuevo las talbas
local, main y default...
--------------------
cuenta=0
for ifcfg in /etc/sysconfig/network-scripts/ifcfg-*
do
cuenta=$(( cuenta + 1 ))
TABLE=100$cuenta
. $ifcfg
#echo "DEVICE=$DEVICE"
export `ipcalc -n $IPADDR $NETMASK`
NET=$NETWORK/$NETMASK
ip route flush table $TABLE
ip route add $NET dev $DEVICE src $IPADDR table $TABLE
if [ "$GATEWAY" != "" ]
then
ip route add default via $GATEWAY table $TABLE
fi
ip route add $NETWORK dev $DEVICE src $IPADDR
#ip rule flush >=0 y <=32766??
ip rule add from $IPADDR table $TABLE
ip rule add fwmark $TABLE table $TABLE
tables="$tables $TABLE"
if [ "$GATEWAY" != "" ]
then
ip route add default via $GATEWAY table $TABLE
fi
done
for TABLE in $tables
do
for ifcfg in /etc/sysconfig/network-scripts/ifcfg-*
do
. $ifcfg
export `ipcalc -n $IPADDR $NETMASK`
NET=$NETWORK/$NETMASK
ip route add $NET dev $DEVICE table $TABLE
done
done
echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter
ip route flush cache
------------------------
--
Qapla'
Alejandro Vargas
Qapla'
Alejandro Vargas