FreeBSDの複数経路について
FreeBSD7.1系以降複数経路(マルチホーミング)についてカーネルでサポートがされるようになったようです。
このことは、FreeBSDが苦手としていたプロセスレベルでの複数経路が簡単にできるということらしいです。
firewall各種で複数経路についての方法はpfやipfwの解説を参考にしてください。
ipfwやpfとの連携も可能です。PPPoEなどFletsでの複数経路制御も基本的には同じで、NIC名称などが変更すれば応用できると思います。
概要
この説明では以下のようなネットワークを想定しています。
ルーターとなるサーバ側には5枚のNICがささっており、4つが外部との経路があり1個が内部向け(自身がルーター)です。
図にすると以下のようなになります。
このとき、nic0がデフォルトゲートウェイで、nic1がNAT向けで、nic2とnic3はその他の外部とやり取りするためので、nic4が内部向けです。
※以後カード名はすべてnic?に統一してあります。適宜em0やfxp0などに置き換えてください。
導入&設定編
カーネルで複数経路を扱うにはカーネルリメイクが必要です。
以下の行を記述すれば現在標準値でサポートされている最大値の16経路1)が管理できます。
options ROUTETABLES=16
カーネルリメイク後インストールし以下のように設定をrc.localに追加します。
このとき/etc/rc.confにdefaultgatewayを指定しても意味がなくなるそうなので、消してもOKらしいです。
- /etc/rc.local
# /etc/rc.local /usr/sbin/setfib 0 /sbin/route add default 10.0.0.1 /usr/sbin/setfib 1 /sbin/route add default 192.0.2.1 /usr/sbin/setfib 2 /sbin/route add default 198.51.100.1 /usr/sbin/setfib 3 /sbin/route add default 203.0.113.1
そのあと再起動すればとりあえずは通常通り使えるはずです。
確認編
% setfib 0 ping -c1 www.yahoo.co.jp PING www.g.yahoo.co.jp (124.83.203.233): 56 data bytes 64 bytes from 124.83.203.233: icmp_seq=0 ttl=49 time=24.208 ms --- www.g.yahoo.co.jp ping statistics --- 1 packets transmitted, 1 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 24.208/24.208/24.208/0.000 ms % setfib 1 ping -c1 www.yahoo.co.jp PING www.g.yahoo.co.jp (124.83.203.233): 56 data bytes 64 bytes from 124.83.203.233: icmp_seq=0 ttl=50 time=25.595 ms --- www.g.yahoo.co.jp ping statistics --- 1 packets transmitted, 1 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 25.595/25.595/25.595/0.000 ms % setfib 2 ping -c1 www.yahoo.co.jp PING www.g.yahoo.co.jp (124.83.203.233): 56 data bytes 64 bytes from 124.83.203.233: icmp_seq=0 ttl=51 time=27.825 ms --- www.g.yahoo.co.jp ping statistics --- 1 packets transmitted, 1 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 27.825/27.825/27.825/0.000 ms % setfib 3 ping -c1 www.yahoo.co.jp PING www.g.yahoo.co.jp (124.83.203.233): 56 data bytes 64 bytes from 124.83.203.233: icmp_seq=0 ttl=51 time=25.706 ms --- www.g.yahoo.co.jp ping statistics --- 1 packets transmitted, 1 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 25.706/25.706/25.706/0.000 ms
のようにsetfibの後の数字を設定した経路に応じて変更すれば、ICMPパケットがそれぞれのゲートウェイ宛にパケットが流れ応答が返ってくるはずです。
% setfib 1 traceroute www.yahoo.co.jp
などとすれば、さらに経路が確認できるはずです。
問題があればtcpdumpを使ってパケットをトレースすれば、どこ宛に流れているか確認できると思います。
実践応用編
Standaloneアプリを制御編
setfibを使って先ほど編集した/etc/rc.confに以下のように記述すれば、スタンドアローン型デーモンアプリがプロセスレベルでの経路制御が可能になります。
/etc/rc.confからサービスを起動する場合、基本は明記しない場合0での通信を行うことになるようです。2)
そのため、sshdを外部向けNICでやり取りしたいなどいう場合は以下のように書き換えてみてください。
- /etc/rc.local
# /etc/rc.local /usr/sbin/setfib 0 /sbin/route add default 10.0.0.1 /usr/sbin/setfib 1 /sbin/route add default 192.0.2.1 /usr/sbin/setfib 2 /sbin/route add default 198.51.100.1 /usr/sbin/setfib 3 /sbin/route add default 203.0.113.1 # 以下を追加 /usr/sbin/setfib 0 /usr/sbin/sshd -f /etc/sshd/sshd_config.nic0 #for nic0 /usr/sbin/setfib 1 /usr/sbin/sshd -f /etc/sshd/sshd_config.nic1 #for nic1 /usr/sbin/setfib 0 /usr/sbin/sshd -f /etc/sshd/sshd_config.nic4 #for nic4 (Internal) # 以上
ipfw
ipfwでは、setfib ?を使った構文によって制御できます。
# ipfw add 1100 setfib 1 from any to any
これを使えば先ほどのsshdも個別に起動するのではなく送信先と送信元のIPアドレスを記述しておけば制御できます。
# ipfw add 1100 setfib 1 from any to 192.0.2.10 # ipfw add 1100 setfib 1 from 192.0.2.10 to any
pf
pfでもipfwと同様にrtable ?で制御できます。
参考サイト
Source Based Routing With FreeBSD Using Multiple Routing Tables » mmacleod.ca(英語) pfでの設定値やsshdの分け方などが解説されています。
HRS's Web Page - The Design and Implementation of the Gracious Days 挙動や設定方法などを詳細に解説されています。