CiscoやYAMAHAのルーターならフィルタなどを利用してポリシーベースルーティングできると思います。
同じようにLinuxでもやりたいと思います。
ポリシーベースルーティングとは、通常のルーティングと違い、ホスト内で完結させるルーティング手法。
特定の動作の時に特定のルートテーブルを使う。といった感じです。(説明難しい。。。)
例えば・・・
- マルチホーム環境で特定のポートにアクセスする場合は、ゲートウェイを変えたい。
- マルチホーム環境で、入ってきたI/Fのアクセスは応答する時も同じI/Fで出したい。
などなど。。。
キモはマルチホーム環境である事。
例題)特定のポートにアクセスする場合にゲートウェイを変えたい
どんなシチュエーションが考えられるか?
・通常はA回線を使っているが、httpアクセスの時はB回線を使いたい。
今回の環境は
・ホストに外線が3本刺さっており(192.168.0.2,192.168.1.2,192.168.2.2)、その先にゲートウェイ(192.168.0.1,192.168.1.1,192.168.2.1)がそれぞれあるとする。
・ホストから12.34.56.78のhttpアクセスはゲートウェイAから。12.34.56.78のhttpsアクセスはゲートウェイBから。12.34.56.78のsshアクセスはゲートウェイCから。それぞれアクセスするようにしたい。
こんな事を叶えるために必要なLinuxの機能は
- iproute2
- iptables
になります。
iptablesで特定のポートに向かうパケットに印を付け(iptables)、印の付いているパケットは指定のルーティングテーブルを使う(iproute2)。
1.iptablesに印を付ける
パケットに印を付けるにはiptablesのmangleテーブルを使用する。
# iptables -t mangle -A OUTPUT -p tcp --dport 80 -j MARK --set-mark 1 ←tcp80に向かって出ていくパケットに「1」をマークする
# iptables -t mangle -A OUTPUT -p tcp --dport 443 -j MARK --set-mark 2 ←tcp443に向かって出ていくパケットに「2」をマークする
# iptables -t mangle -A OUTPUT -p tcp --dport 22 -j MARK --set-mark 3 ←tcp22に向かって出ていくパケットに「3」をマークする
2.iproute2にルールを追加する
印を付けたパケットに対するルールを指定する。
# ip rule add fwmark 1 table 10 ←「1」をマークされているパケットは「table10」を参照する
# ip rule add fwmark 2 table 20 ←「2」をマークされているパケットは「table20」を参照する
# ip rule add fwmark 3 table 30 ←「3」をマークされているパケットは「table30」を参照する
更にゲートウェイ宛のインターフェースが複数あるため、戻りパケットにも指定を入れておく。
# ip rule add from 192.168.0.2 table 10 ←「192.168.0.2」に入ってきたパケットは「table10」を参照する
# ip rule add from 192.168.1.2 table 20 ←「192.168.1.2」に入ってきたパケットは「table20」を参照する
# ip rule add from 192.168.2.2 table 30 ←「192.168.2.2」に入ってきたパケットは「table30」を参照する
3.iproute2にルートを追加する
参照させるルートtableを作成する。
# ip route add default dev eth1 via 192.168.0.1 table 10 ←「table10」のデフォルトゲートウェイはeth1の先の192.168.0.1とする
# ip route add default dev eth2 via 192.168.1.1 table 20 ←「table20」のデフォルトゲートウェイはeth2の先の192.168.1.1とする
# ip route add default dev eth3 via 192.168.2.1 table 30 ←「table30」のデフォルトゲートウェイはeth3の先の192.168.2.1とする
それぞれのtableにローカルリンクを追記しておく方が良いので、適宜対応しましょう。
ローカルリンクの書き方は
# ip route show table main
を参照し、default意外を適用すると良いぞ!
ワンライナーだとこんな感じ
# ip route show table main | grep -Ev ^default | while read ROUTE ; do ip route add table "table名" $ROUTE; done
以上で設定は終わり。実際に検証してみよう。
問題なければ /etc/rc.local
か何か起動スクリプトに追加するといいかもしれない。