Linux roteando para internet com múltiplas interfaces

1

Eu tenho um pi de framboesa com três interfaces conectadas, eth0 , wlan0 e ppp0 , o que estou procurando é ter rotas para a internet em todas as interfaces, mas até agora só eth0 e ppp0 obtém uma rota.

aqui estão as saídas de route -n e ip route show (não tem uma interface ppp0 funcionando agora, mas sei que ela funciona)

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.1.1     0.0.0.0         UG    0      0        0 eth0
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 wlan0

default via 192.168.1.1 dev eth0
192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.39
192.168.1.0/24 dev wlan0  proto kernel  scope link  src 192.168.1.243

Eu escrevi um script que é acionado a partir de /etc/dhcp/dhclient-exit-hooks.d/ , assim que a interface recebe uma oferta do dhcp.

#!/bin/bash

calculateCIDR() {
    nbits=0
    IFS=.
    for dec in $1 ; do
        case $dec in
            255) let nbits+=8;;
            254) let nbits+=7;;
            252) let nbits+=6;;
            248) let nbits+=5;;
            240) let nbits+=4;;
            224) let nbits+=3;;
            192) let nbits+=2;;
            128) let nbits+=1;;
            0);;
            *) 
                echo "Error calulating CIDR exiting."; 
                exit 1
            ;;
        esac
    done
    echo $nbits
}

calculateSubnet() {
    IFS=. read -r i1 i2 i3 i4 <<< $1
    IFS=. read -r m1 m2 m3 m4 <<< $2
    echo "$((i1 & m1)).$((i2 & m2)).$((i3 & m3)).$((i4 & m4))"
}

# check if all parameters are there
# expected parameters 
# $1 = iface
# $2 = ip
# $3 = mask
# $4 = gateway
if [ $# -ne 4 ]
  then
    echo "Illegal number of arguments"
    exit 2
fi

# assign variables
IFACE=$1
IP=$2
MASK=$3
GATEWAY=$4

# extract inface number and calculate table number 
case $IFACE in
    eth*)
        TABLEID=$(( 10 + 'echo $IFACE | grep -o -E '[0-9]+''))
        METRIC=0
    ;;
    wlan*)
        TABLEID=$(( 30 + 'echo $IFACE | grep -o -E '[0-9]+''))
        METRIC=$(( 50 + 'echo $IFACE | grep -o -E '[0-9]+''))
    ;;
    ppp*)
        TABLEID=$(( 90 + 'echo $IFACE | grep -o -E '[0-9]+''))
        METRIC=$(( 100 + 'echo $IFACE | grep -o -E '[0-9]+''))
    ;;
    *)
        echo "Bad interface exiting"
        exit 1
    ;;
esac

# create new table for interface only if not existing there already
grep -q -F "$TABLEID $IFACE" /etc/iproute2/rt_tables || echo "$TABLEID $IFACE" >> /etc/iproute2/rt_tables

# remove previous rules
while ip rule delete table $IFACE 2>/dev/null; do true; done

# flush previous table
ip route flush table $IFACE

# calculate CIDR from
CIDR=$(calculateCIDR $MASK)

# calculate subnet address
SUBNET=$(calculateSubnet $IP $MASK)

# create route for local network
ip route add $SUBNET/$CIDR dev $IFACE src $IP metric $METRIC table $IFACE

# create route for internet
ip route add default via $GATEWAY dev $IFACE metric $METRIC table $IFACE

# set rules for the interface
ip rule add from $IP/32 table $IFACE
ip rule add to $IP/32 table $IFACE

# done 
exit 0

esse mesmo script é usado para todas as interfaces fornecidas com a configuração da rede, o wlan0 nunca obtém uma rota para a internet, o que significa que não posso usá-lo para pingar qualquer coisa fora da rede local. Alguém sabe por quê? Estou ficando sem ideias.

    
por TheBrash 01.03.2018 / 12:00

1 resposta

0

Primeiro: sempre use o comando ip(8) . route é um daqueles comandos do Linux em depreciação . Basicamente, a rota do Linux foi portada de outro sistema operacional e não funciona com o esquema de tabela de roteamento do Linux (ela mostra apenas a tabela principal).

A tabela de rotas

main está sempre implícita. Antes de corresponder ao que precisa ser roteado através de main , a tabela local também é analisada pelo Kernel (basicamente, todas as transmissões, endereço local e loopback estão lá). É por isso que você não pode ter uma rota padrão em cada interface, porque ao rotear na tabela main apenas um dos padrões terá precedência sobre os outros. Veja quais tabelas você tem com ip rule list .

O que você terá que fazer para configurar a redundância básica é:

  • Crie duas regras (por exemplo, link01 e 'link02) e suas tabelas de roteamento
  • Mantenha a rota padrão vazia na tabela main .
  • Crie uma rota padrão para a tabela link01 e outra para link02 .
  • Crie regras para essas tabelas ou iptables regras quando você corresponder a cada tabela
  • Crie intervalos de ip de rede separados para conexões Wi-Fi e por cabo.

Você enfrenta um problema em sua configuração atual: Você está repetindo uma rota padrão no mesmo gateway e na mesma tabela ( main ) para interfaces diferentes (provavelmente enfrentando o erro "rota já existe" ao tentar adicionar o rota padrão na segunda vez). Isso nunca vai acontecer. Como o arp deve lidar com o mesmo IP sendo publicado em duas interfaces ao mesmo tempo?

Solução alternativa:

Se você quiser alguma redundância como uma solução de backup ativo sem ter que alterar os itens que eu listei acima , você poderia usar um interface de ligação configurada no modo 1 , coloque eth0 e wlan0 como escravos. Este é um exemplo Debian de /etc/network/interfaces , então você terá que se adaptar à sua distribuição:

# Slaves   
auto eth0
iface eth0 inet manual
    bond-master bond0
    bond-primary eth0
    bond-mode active-backup

auto wlan0
iface wlan0 inet manual
    wpa-conf /etc/network/wpa.conf
    bond-master bond0
    bond-primary eth0
    bond-mode active-backup

# Master
auto bond0
iface bond0 inet dhcp
    bond-slaves none
    bond-primary eth0
    bond-mode active-backup
    bond-miimon 100

Dessa forma, você se conectará por cabo e Wi-Fi e terá um endereço IP "unificado" para ambos.

Se você tiver um switch de rede mid / high end que é capaz de fazer LACP (IEEE 802.3ad) você pode fazer uma agregação de link que usará ambos os cabos / conexões ao mesmo tempo (e bond do Linux seja 4).

    
por 01.03.2018 / 13:07