web-dev-qa-db-ja.com

複数のインターフェースを持つLinuxへのLinuxルーティング

eth0wlan0ppp0の3つのインターフェースが接続されたRaspberry Piを持っています。私が達成しようとしているのは、すべてのインターフェースを通じてインターネットへのルートを持つことですが、今のところeth0およびppp0はルートを取得します。

ここにroute -nip route showの出力があります(現在、機能しているppp0インターフェースはありませんが、動作することはわかっています)

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

/etc/dhcp/dhclient-exit-hooks.d/からトリガーされるスクリプトを作成したので、インターフェイスが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

この同じスクリプトは、ネットワークセットアップで提供されるすべてのインターフェイスに使用されます。wlan0はインターネットへのルートを取得しません。つまり、ローカルネットワークの外部へのpingには使用できません。誰もがなぜ知っていますか?アイデアが足りません。

2
Tychus

まず、常に ip(8) コマンドを代わりに使用します。 route非推奨にする方法 上のLinuxコマンドの1つです。基本的に、Linuxルートは他のOSから移植されたものであり、Linuxルーティングテーブルスキームでは機能しません(メインテーブルのみが表示されます)。

mainルートテーブルは常に暗黙的です。 mainを介してルーティングする必要があるものと一致する前に、テーブルlocalもカーネルによって検索されます(基本的にすべてのブロードキャスト、ローカルアドレス、ループバックがそこにあります)。これが、各インターフェースにデフォルトルートを設定できない理由です。テーブルmainでルーティングすると、デフォルトの1つだけが他よりも優先されます。 ip rule listを使用して、どのテーブルを持っているかを調べます。

基本的な冗長性を構成するために必要なことは次のとおりです。

  • 2つのルール(たとえば、link01および `link02)とそのルーティングテーブルを作成します。
  • mainテーブルのデフォルトルートを空のままにします。
  • テーブルlink01へのデフォルトルートとlink02へのデフォルトルートの1つを作成します。
  • それらのテーブルにルールを作成するか、各テーブルを照合するときにiptablesルールを作成します
  • Wifiおよびケーブル接続への個別のネットワークIP範囲を作成します。

現在の設定で問題に直面しています:同じゲートウェイで同じテーブル(main)のデフォルトルートを別のインターフェースに繰り返しています(おそらく、「ルートはすでに存在しています」というエラーに直面しています。デフォルトルートは2回目)。これは決して起こらないでしょう。 arpは、2つのインターフェイスで同時に公開されている同じIPをどのように処理することになっていますか?

代替ソリューション:

上記の項目を変更せずにアクティブバックアップソリューションのような冗長性が必要な場合モード1で構成された結合インターフェース を使用して、eth0およびwlan0をスレーブとして配置できます。これは/etc/network/interfacesの-​​ Debianの例 なので、ディストリビューションに合わせる必要があります。

# 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

このようにして、ケーブルとwifiで接続し、両方に「統一された」IPアドレスを設定します。

LACP(IEEE 802.3ad)を実行できるミッドエンド/ハイエンドのネットワークスイッチがある場合、両方のケーブル/接続を同時に使用するリンク集約を実行できます(Linuxのbondモードは4)である。

1
user34720