ホームマルチホームサーバーのルーティングセットアップ

現在、ホームサーバーを含む1つに複数のインターネット接続が存在することは珍しくありません。 City lokalka、ADSL、3Gモデム...このネットワークにローカルローカルおよび外部仮想(VPN)を追加し、トラフィックのルーティング、インターネット上の異なるチャネル間のトラフィックのバランス(必要な場合)、非稼働からの切り替えを行う必要のあるインターフェイスの活発な混合を取得します労働者のためのチャネル(彼らが落ちるとき)。

インターネット上の投稿から判断すると、この状況に遭遇したほとんどの人は、これがどのように設定されているかについて非常に悪い考えを持っています。 linuhでは、実際にルーティングを管理することは非常に複雑でわかりにくいことに注意してください-進化的な開発と(部分的な)互換性のサポートの結果です。 特定のかなり複雑な例でマルチホームサーバーのルーティングを構成する原理を説明します。サーバーには、3つの物理ネットワークインターフェイス(1つはホームLAN、2つはADSLモデム)、2つのADSL接続(ブリッジモードのADSLモデム、したがってpppd同じサーバーを別のプロバイダー(1つは静的IP、もう1つは動的IP)に追加し、さらに会社のサーバーにVPNを追加します(合計6つのインターフェース)。

トピックは非常に複雑であるため、資料を理解するには、少なくともルーティング(デフォルトのルートとゲートウェイ)、ファイアウォール(パケットのラベル付け、接続追跡、異なるテーブルとファイアウォールチェーンとルーティング間の通信)、pppd(ip-up /スクリプトip-down)およびIPおよびTCPプロトコル。

一般的な構成と問題の説明


したがって、3つのネットワークインターフェイスがあります。ADSLを介してインターネット接続が確立されると、さらに2つのインターフェイスが表示されます。そして、少なくとも1つのインターネット接続がある場合、もう1つのインターフェイスが追加されます。以下を実装する必要があります。したがって、これらの接続はすべて設定済みであり、一度に1つを上げ下げすることができます。ADSL接続が1つだけ上げられれば、すべてが正常に機能します。マルチホーミングのみを設定します。

理論のビット


以前のルーティングを構成するために(そして今-単純な場合)、routeコマンドが使用されました。 あなたはそれを忘れることができます-そのような設定はipコマンド(iproute2パッケージから)によってのみ行われ、ipとrouteの両方を同時に使用しても問題はありません。 routeコマンドの時点では、 ルーティングテーブルは1つでした。 現在、いくつかのルーティングテーブルがあります(そのうちの1つ、 メインはrouteコマンドが機能するものと同じです)。 これらのテーブルは、/ etc / iproute2 / rt_tablesにリストされています。

# cat /etc/iproute2/rt_tables # # reserved values # 255 local 254 main 253 default 0 unspec # # local # #1 inr.ruhep 

それらの内容は、 ip route list table <table name>コマンドで表示できます。 ローカルテーブルには興味深いものは何もありません-利用可能なインターフェイスを介したリンクローカルルーティングルールがあります。 表mainで、ルーティング基本ルール。 デフォルトのテーブルはデフォルトでは空です。 unspecテーブル( allとしてもアクセス可能)には、既存のすべてのテーブルからのすべてのルーティングルールが表示されます。
新しいテーブルを作成するには、このファイルに名前を追加する必要があります(より正確には、名前でテーブルにアクセスする場合にのみ必要です。番号で参照することもできます)。

 # route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 127.0.0.0 127.0.0.1 255.0.0.0 UG 0 0 0 lo 192.168.0.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 eth1 192.168.2.0 0.0.0.0 255.255.255.0 U 0 0 0 eth2 # ip route list table main 127.0.0.0/8 via 127.0.0.1 dev lo scope link 192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.2 192.168.1.0/24 dev eth1 proto kernel scope link src 192.168.1.2 192.168.2.0/24 dev eth2 proto kernel scope link src 192.168.2.1 

複数のルーティングテーブルがあるとすぐに、使用するルーティングテーブルを選択できるメカニズムも必要になりました。これはルーティングルール(RPDB、ルーティングポリシーデータベース)と呼ばれます 。 このメカニズムの主な利点は、( routeコマンドとip route ...のように )宛先アドレスだけでなく、他の基準(ソースアドレス、インターフェイス、tos、fwmark、...フィールド)に基づいてルーティングを選択できることです。 これは次のように機能します:「 ip rule ...コマンドを使用して」「criteria-> routing table」の形式で任意の数のルールを指定します。 特定のパケットに対してルーティングルールの条件が一致し、指定されたルーティングテーブルに(宛先アドレスに基づいて)このパケットのルートが存在する場合、そのパケットが実行されます。 そうでない場合は、ルーティングルールに戻り、他のオプションを確認します。 デフォルトのルーティングルールは次のようになります。

 # ip rule list 0: from all lookup local 32766: from all lookup main 32767: from all lookup default 

最初の列は優先順位です。 優先度が高い順にルールがスキャンされます。 これらのルールは、最初にローカルテーブル(link-localはルーティングルール)、次にメインテーブル(通常はrouteコマンドで制御)、およびデフォルトルートが通常指定されている場所(つまり、 これにより、ルーティングルールの実行が停止し、(デフォルトルートがmainで指定されなかった場合デフォルトテーブル(デフォルトでは空)になります

以下は、このエコノミーをすべて使用して、ホームLANアドレス192.168.2.100からのパケットがデフォルトルーティングとは異なるルーティングルールを使用して処理される方法の簡単な例です(最初のADSLモデムと最初のプロバイダーを介してインターネットにのみアクセスを許可します) ):

 # echo '100 local100' >> /etc/iproute2/rt_tables # ip route add 192.168.0.0/24 dev eth0 table local100 # ip route add default via <__> dev ppp0 table local100 # ip rule add from 192.168.2.100 lookup local100 priority 5 # ip route list table local100 192.168.0.0/24 dev eth0 scope link default via <__> dev ppp0 # ip rule list 0: from all lookup local 5: from 192.168.2.100 lookup local100 32766: from all lookup main 32767: from all lookup default 

ファイアウォールについて少し説明します。 これにより、ルーティングに影響を与えることもできます。

図からわかるように、たとえばローカルアプリケーションからのパケットは、「ルーティング決定」ステージを2回通過します。 私が理解しているように、これはパッケージの作成時に初めて発生し、発信インターフェイスとその発信IP(ファイアウォールルールを確認できるので、パケットがファイアウォールに到達したときに既知である必要があります)を決定するために、さらに再ルーティングしますファイアウォールのMANGLEチェーンを実行した後にこのパケットのが計算されます。これにより、パケットのフィールドが変更され、このパケットのルーティングに影響する可能性があります。

私たちの場合、ファイアウォールを介したルーティングに影響を与える最も簡単な方法は、MANGLEチェーンのパケットfwmarkフィールドを変更し、ルーティングルールを使用してパケットfwmarkフィールドの値に基づいてルーティングテーブルを選択することです(このため、異なるルールで複数のルーティングテーブルを作成する必要があります-たとえば、 1つのプロバイダーを介して1つのテーブルにデフォルトルートを登録し、別のプロバイダーを介して別のテーブルにデフォルトルートを登録します。

ルーティングのセットアップ:最終結果


この最終結果へのパスは、一部の場所では厄介です(pppdおよびopenvpn機能のバグではリラックスできないため)。以下に説明します。 それまでの間、取得する必要があるものを見てみましょう。

2つのプロバイダー間のバランス

まず、両方のプロバイダーの同時使用を構成し、負荷分散を8対2(それぞれ、チャネル幅)の比率で行います。 この方法は、個々の宛先アドレスごとにルーティングを選択します。 接続が最初に最初のプロバイダーを通過した場合、そのパケットはすべて最初のプロバイダーのみを通過し、 しばらくの間このアドレスへのすべての接続はこのプロバイダーのみを通過します。 接続ではなくパッケージによる分散の方法は異なり、1つのプロバイダーへの接続が複数ある場合にのみ機能します。

 # ip route replace default scope global \ nexthop via <_isp1> dev ppp0 weight 8 \ nexthop via <_isp2> dev ppp1 weight 2 

なぜなら カーネルは、宛先アドレスとそれらに選択されたデフォルトルーティングとの間の接続に関する情報をキャッシュするため、このキャッシュをリセットする必要がある場合があります(カーネルが再び8から2の確率で、この宛先アドレスのデフォルトルーティングを選択するように):

 # ip route flush cache 

特定の接続の手動チャンネル選択

なぜなら 場合によっては、どの外部チャネルを介してパケットを送信するかを制御する必要があります。デフォルトルートを使用して、チャネルごとに個別のルーティングテーブルを作成します。

 # echo '1 isp1' >> /etc/iproute2/rt_tables # echo '2 isp2' >> /etc/iproute2/rt_tables # echo '3 vpn' >> /etc/iproute2/rt_tables # ip route add default via <_isp1> dev ppp0 table isp1 # ip route add default via <_isp2> dev ppp1 table isp2 # ip route add default via <_vpn> dev tun0 table vpn 

次に、ファイアウォールを使用して目的のfwmark値を設定し、目的のルーティングテーブルを選択できるように、ルーティングルールを追加します。

 # ip rule add priority 100 fwmark 0x4/0x4 lookup vpn # ip rule add priority 101 fwmark 0x1/0x1 lookup isp1 # ip rule add priority 102 fwmark 0x2/0x2 lookup isp2 

値0x4 / 0x4(値/マスク)は、0wマスクのビット(つまり、3番目のビットのみ)がfwmarkフィールドから取得されることを意味し、値0x4と一致する必要があります。 つまり fwmarkでは、vpnテーブルのルールが機能するために3番目のビットを設定する必要があり、残りのビットは関係ありません。 このアプローチにより、ファイアウォールのfwmarkにいくつかのビットを設定できるため、このパッケージにいくつかの「適切な」チャネルが示されます。 これらのチャネルの優先度(すべて使用可能な場合)は、ルーティングルールの優先度によって決まります。 チャネルが利用できない場合、対応するルーティングテーブルは引き続き表示されますが、デフォルトルートがないため、次のルーティングルールに戻り、次の適切なチャネルが見つかります。

これらのコマンドはすべて、まだ何にも影響していません-fwmarkファイアウォールは公開しないため、テーブルisp1isp2およびvpnのルーティングルールは機能しません。デフォルトでは、ルーティングは以前のようにメインテーブルによって決定されます。

 # ip route list ### "table main"    <_vpn> dev tun0 proto kernel scope link src <vvvv> <_isp1> dev ppp0 proto kernel scope link src <ssss> <_isp2> dev ppp1 proto kernel scope link src <dddd> 192.168.2.0/24 dev eth2 proto kernel scope link src 192.168.2.1 192.168.1.0/24 dev eth1 proto kernel scope link src 192.168.1.2 192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.2 127.0.0.0/8 via 127.0.0.1 dev lo scope link default nexthop via <_isp1> dev ppp0 weight 8 nexthop via <_isp2> dev ppp1 weight 2 # ip route list table isp1 default via <_isp1> dev ppp0 # ip route list table isp2 default via <_isp2> dev ppp1 # ip route list table vpn default via <_vpn> dev tun0 # ip rule list 0: from all lookup local 100: from all fwmark 0x4/0x4 lookup vpn 101: from all fwmark 0x1/0x1 lookup isp1 102: from all fwmark 0x2/0x2 lookup isp2 32766: from all lookup main 32767: from all lookup default 

これで、統計情報と2番目のプロバイダーのコントロールパネルを使用してWebサイトへのアクセスが2番目のADSLを通過することを示すことができます。

 # iptables -t mangle -A OUTPUT -d <ip__isp2>/32 -j MARK --set-mark 0x2 

これらのルールがサーバーからの送信パケットだけでなく、ホームLANからのパケットでも機能する必要がある場合、これらのすべてのルールをOUTPUTチェーンだけでなくFORWARDチェーンでもファイアウォールに追加する必要があります。

同じインターフェースからの返信

発信接続についてのみ話している限り、これはすべて正常に機能します。 しかし、サーバーがあります...そしてサーバーへの着信接続があります。 静的IP ssss(最初のプロバイダーのチャネル)で作成されたWebサイトがあるとします。 サーバー<ip_site_isp2>の2番目のプロバイダーの管理者が(lynxを介して)Webサイトを検索したい場合、何も機能しません! 実際、彼は最初のプロバイダーのチャネルを介して(Webサイトの)IP ssssに要求を送信し、サーバーは2番目のプロバイダーのチャネルを介して(したがって、ddddアドレスから)この要求に対する応答を送信します。もちろん、SNAT / MASQUERADEはppp0ppp1 、およびtun0インターフェースを通過するパケット用に構成されます )-作成したファイアウォール設定に従って:2番目のプロバイダーのチャネルを介して<ip_site_isp2>のアドレスにパケットを送信します。 要求をssssアドレスに送信した管理Webブラウザーは、ddddアドレスから応答を受信することを想定していないため、これは機能しません。

この問題を解決するには、パケットが最初に受信されたインターフェイスからの着信接続への応答を保証する必要があります。 残念ながら、これを行うには、ファイアウォール(conntrack)で接続追跡を使用してfwmark(connmark)を設定する必要があります。 残念ながら-conntrackは大きく複雑でバグの多いゴミですが、選択の余地はありません。 これは次のように行われます(上記のルールを設定する前に、これらのルールを最初にファイアウォールに追加する必要があります)。

 # iptables -t mangle -A INPUT -i ppp0 -j CONNMARK --set-mark 0x1 # iptables -t mangle -A INPUT -i ppp1 -j CONNMARK --set-mark 0x2 # iptables -t mangle -A INPUT -i tun0 -j CONNMARK --set-mark 0x4 # iptables -t mangle -A INPUT -i eth+ -j CONNMARK --set-mark 0x8 # iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark # iptables -t mangle -A OUTPUT -m mark ! --mark 0x0 -j ACCEPT 

ここで、着信パケット(より正確には、それらが属する接続)を、それらが送信されたインターフェースに従ってマークします。 さらに、fwmark値(より正確には、connmark)は、これらのパケットへの応答を送信する必要があるルーティングテーブルに対応するように選択されます(1,2,4-isp1、isp2、vpnの場合、8-これはfwmarkルーティングルールでは使用されません、t .e。このfwmarkを持つパケットは、 メインテーブルの通常のルーティングに従って送信されます-これはローカルネットワークからのパケットに非常に適しています)。

このラベル付けは、着信パケットのルーティングには影響しませんが、これにより、このラベル付けを実際にこの接続のすべてのパケットに関連付けることができます。 発信パケット。 さらに、同じ接続の発信パケット(着信パケットへの応答)については、fwmark値を着信パケットと同じ値に設定し、この接続に関連付けられています(より正確には、connmark値をfwmarkにコピーします)。 結果として、発信パケットにfwmark値が設定されている場合(0ではない)、次のすべてのfwmarkインストールルールを使用して発信チャネルを選択することはできません-このパケットは、着信パケットが到着したのと同じインターフェイスを介して送信する必要があるため、停止します(-j ACCEPT )

合計すると、問題のステートメントに応じた正しいファイアウォール構成オプションは次のようになります。

 # iptables -t mangle -A INPUT -i ppp0 -j CONNMARK --set-mark 0x1 # iptables -t mangle -A INPUT -i ppp1 -j CONNMARK --set-mark 0x2 # iptables -t mangle -A INPUT -i tun0 -j CONNMARK --set-mark 0x4 # iptables -t mangle -A INPUT -i eth+ -j CONNMARK --set-mark 0x8 # iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark # iptables -t mangle -A OUTPUT -m mark ! --mark 0x0 -j ACCEPT # iptables -t mangle -A OUTPUT -p tcp -m tcp --dport 25 -j MARK --set-mark 0x1 # iptables -t mangle -A OUTPUT -d <ip__vpn>/32 -p udp -m udp --dport 1130 -j MARK --set-mark 0x1 # iptables -t mangle -A OUTPUT -d <ip__isp2>/32 -j MARK --set-mark 0x2 

ルールとルーティングテーブルの設定とともに、必要なものを正確に取得します。 これらの設定をダイナミクスでどのように設定するかは、チャネルが上下する可能性があるという事実を考慮に入れたままです。

最終結果への厄介な道


正直なところ、この記事はかなり大きなものであることが判明したので、私がやろうとしていたip-up / downスクリプトで混乱することはありません。 誰かがコメントを求めたら-後で記事に追加してください。 次に、上記の設定の実装中に発生した主なタスクと問題について簡単に説明します。

Source: https://habr.com/ru/post/J100919/


All Articles