ネットワークの二重化

以下のテキストは、執筆時当時の情報を元に書いたものであり、 現在の情勢にそぐわないことを含む場合があるので注意されたい。 また、テキストは最終提出原稿で校正を経る前のものなので、実際にUNIXUSER 本誌に記載されたものとは異なる。誤字脱字等そのままである。

致命的な誤り以外は加筆修正等は行なわないので情報の鮮度に気をつけつつ 利用して欲しい。

目次


●●●● すぐにできる障害対策 ●●●●


サーバを運用する上でトラブルは避けられない。中でも回線断、HDD故障、停電、
は人為的なミスとは無関係に発生する。それぞれ頻度的には年に一度あるかない
か程度だが、実際にトラブルが発生したときときに事前の備えがあるかどうかで
復旧までにかかる時間が格段に違って来る。

今回は、自宅やオフィスLANといった規模を想定し、低価格で構築できる
障害対策を紹介する。

===========================================
Part 1 ネットワークの二重化
===========================================

なんらかのサーバマシンを運用中、ネットワークが断絶してしまった、あるいは
ルータの設定を誤ってサーバと通信できなくなった、などの経験はないだろうか。
そうした障害発生時にはいつでもその場にいるとは限らない。Part1 ではネット
ワーク回線を二重化し、障害からの復旧をどこからでも行なえるようにするため
のネットワーク環境の構築を考えよう。

■
■安全なネットワークとは
■


道路の場合、ある地域に行く道はほとんどの場合複数の経路がある。しかし土地
条件の厳しい集落などは、そこに行く道が1本しかないこともあり、そのような場
合、大きな震災などにより、道路が寸断され「陸の孤島」と化してしまうことが
ある。

自宅に通ずる道を想像してみて欲しい。日常生活では自宅への経路が必ず複数あ
るはずで、たとえば駅までの道の一本が通行止めになっても、必ず回り道がある
はずだ。そうでなければいざというときに生活に支障を来たす。

これと同じことがネットワークにもいえる。もし自宅などで運用するサーバがあ
るとして、長期出張時にネットワークが切れたら、いつ復旧できるのだろう。
「ルータをリセットすれば済む」程度のことが、外出先では行なえない。そのた
めだけに遠方から一時帰宅する労力と費用を考えると、「副回線」としてADSLラ
インなどを余分に引いておくのはけっして無駄ではない。

■
■光ファイバー時代の到来
■

ここ数年、本誌の特集を執筆するにあたって「Mbps単位の常時接続環境が安価に
提供されるようになり……」という文言をしばしば用いてきた。最近では光ファ
イバーによる100Mbpsでの接続も十分に安価になり、多くの人がADSLなどのメタ
ル接続から光接続に乗り換え始めている。

執筆時現在の価格を【表 た】に示した。これを見ても分かるように一般家庭向け
のものであれば、おこづかいで十分手がとどく範囲にまで下りて来ている。

---[表 た]------------------------------------------------------------
一般家庭向け光接続サービス諸費用(2005年6月上旬時点のもの)
月額費用は機器利用料配線使用料を含む

			初期費用※1	月額費用(税込み)
--------------------------------------------------------
NTT-東日本		14227円		5460円
ハイパーファミリー
--------------------------------------------------------
NTT-西日本		29295円		5218.5円
ファミリー100
--------------------------------------------------------
TEPCOひかり		29000円前後※2	6000円前後※2
ひかり100Mbps
--------------------------------------------------------
中部電力		26250円		3990円
アクセスコミュファホーム
--------------------------------------------------------
YAHOO			2100円※3	7234円
Yahoo! BB光
--------------------------------------------------------

※1 初期費用については全学または一部を免除する加入方法を
    各社用意していることが多い

※2 プロバイダ料金とのセット払いなので加入プロバイダによって
    大きく異なる。

※3 工法や施工日により異なる。
----------------------------------------------------------------------

さて、これまでメタル接続だった回線下でなんらかのサーバを運用していたサイ
トが光回線に移行する場合、たとえメタル接続を継続契約しない場合でも、ある
一定の「移行期間」が必要だろう。期間中は2回線のどちらからでもアクセスでき
るようにしたいところだ。回線契約が変わる場合、当然グローバルIPアドレスも
変わる。このため、Webサーバ等のホスト名のDNSレコードを変更することになる
が、変更が全域に伝播する間は新旧どちらのIPアドレスにアクセスしに来るか分
からない。このようなときに、新旧回線どちら経由でアクセスしに来ても問題な
くサービス供給できるのであればそれに越したことはない。


■
■ADSLと光によるネットワークの二重化
■


●想定ストーリー

ADSLを利用している場所で光接続プランが利用可能になったときにどうするか。
純粋にADSL回線を廃止して、光接続回線に乗り換えるのも手だが、ADSL接続料金
だけを見ると十分に安価であるため、光接続を「追加」してネットワークの二重
化を行なうのも手である。

ここでは、そのようなケースを想定して主回線と副回線どちらからもアクセスで
きるような環境を構築しよう。

●目標とする二重化の範囲

一口に「二重化」といってもピンからきりまであるが、ここでは、

	「あるサーバに到達する経路(主回線)が遮断されたときに
	  副回線からサーバにアクセスできるようにすること」

を目標とする。理想を言えば主回線による通信が跡絶えたときに、動的ルーティ
ングプロトコルにより自動的に副回線側にデフォルトルートが向くようなネット
ワークが望ましいのだが【コラム 参照】、個人あるいは小規模オフィスLANで手
の届く範疇を超えるのでここでは

   「外部から副回線経由でサーバにSSHログインできること」

を目標とする。この目標が達せられれば内部から主回線のルータにログインしルー
タのリセット等も可能となる。さらに、同じ設定方法をSSH以外のサービスに適用
することで任意のサービスを二重化することもできる。

なお、今回は主に利用している回線が遮断された場合の備えを考慮するので、
主たるサーバマシンが落ちたときのことは考慮しない。



●想定するネットワーク構成

ここでは、【図 ろ】に示すようなネットワーク接続を想定する。

---[図 ろ]------------------------------------------------------------

   /光用 ISP1/      /ADSL用 ISP2/
        |a1.a2.a3.a4      |b1.b2.b3.b4
    +---+---+         +---+---+
    | 市販  |         | 市販  |
    | PPPoE |         | PPPoE |
    |ルータA|	      |ルータB|
    +---+---+	      +---+---+
        |10.1.1.254       | 10.2.2.254
         \               /
          \             /
           \           /
            \         /
    default  \       /
    10.1.1.10 |     | 10.2.2.10
          +---+-----+----+
	  |    サーバ    |
	  |    venus     |
	  +------+-------+
		 |192.168.1.254
		 |
                 |          LAN 192.168.1.0/24
     o-----------+--------------------------------o

----------------------------------------------------------------------

設定例を単純化するために、ISPへのPPPoE接続は市販の廉価版ルータ専用機で行
なっているものとするが、以下の設定ができていればPCルータでも構わない。

	* ルータAに来たSSH(及びその他)接続は venus に向けられる
	* ルータBに来たSSH(及びその他)接続は venus に向けられる
	* venus のデフォルトルートは ルータA に設定されている
	* venus から ルータA、ルータB にログインできるよう設定されている


●副回線利用の考え方

複数の対外接続回線を利用する場合、デフォルトルートとなっている回線以外を
利用した通信を行なうよう設定するとき、こんな言葉を思い浮かべるとよい。

	「行きは良い良い帰りはこわい」

パケットは行って帰って初めて通信が成り立つのだが、慌てて設定するとパケッ
トの往路だけ設定して、復路のことを忘れがちということを戒めた言葉である。

【図 ろ】の場合で考えてみよう。外部ネットワークからルータBに届いたパケッ
トをvenusにリダイレクトしただけではほとんどの場合通信できない。これは
venusから外部ネットワーク宛のパケットが出ていく規則に原因がある。つまり、

---[図 は]------------------------------------------------------------
  x1.x2.x3.x4                    b1.b2.b3.b4
 +----------+                             +-------+
 |外部ホスト|-->〜〜インターネット〜〜 -->|ルータB|
 +----------+			    ISP2  +---+---+
 					      |10.2.2.254
					      |
 					      |10.2.2.10
		ISP1	+-------+	  +-------+
		 X <--<-|ルータA|<--<--<--| venus |
			+-------+	  +-------+

----------------------------------------------------------------------

外部ホストからルータBのアドレスに向けて発信されたパケットに対する返りパ
ケットが、venusのデフォルトルート規則にしたがってルータAに向けられる。結
果として、外部ホストがルータBのアドレスに接続要求を投げかけても、その答
えがルータBから返って来ないのでいつまで待っても接続が確立しない。

外部ホストがルータBのアドレスに発したパケットが

	始点アドレス	x1.x2.x3.x4
	終点アドレス	b1.b2.b3.b4
	終点ポート	22

だと仮定する。ルータBがSSHポートをvenusにリダイレクトすると、venusに届く
ときのパケットは

	始点アドレス	x1.x2.x3.x4
	終点アドレス	10.2.2.10
	終点ポート	22

となっている。venusでは、このパケットに対する返事を始点アドレスと終点アド
レスを逆の組み合わせにして送出するのだが、x1.x2.x3.x4 へのパケットは
デフォルトルートに従いルータAにいく【図 は】。では、x1.x2.x3.x4 に対する
ルーティングを「ルータB」に設定すれば良いかというと、それではx1.x2.x3.x4
から主回線経由のアクセスができなくなってしまう。これを解決するために、
venusから出るパケットの始点アドレスによってルーティングを切り替える。

●ポリシールーティング

特有の性質を持つパケットを、あらかじめ指定した(ルーティング規則とは別の)
ゲートウェイに送るように設定できる。これをポリシールーティング(Policy
Based Routing)といい、負荷分散や【図 は】の問題を解決するために利用できる。
今回のケースの場合「始点アドレスが10.2.2.10であるもの」は、ルータBが
venusに向けてリダイレクトしたものへの返答、と考えられるので、そのようなパ
ケットは全てルータB(10.2.2.254)に転送する、と設定すると良い。

FreeBSD(IPFW2)とLinux(iproute2)のそれぞれについて、上記のポリシールーティ
ングの設定を紹介しよう。

●IPFW2によるポリシールーティング

FreeBSDでは、特定のパケットを指定した隣接ホストにフォワードすることでポリ
シールーティングが可能だ。ここでいう「フォワード」とは、IPヘッダの始点ア
ドレス、終点アドレス等をいっさい書き換えずに別ホストに転送することである。
もちろん転送先のホスト(またはルータ)でそのパケットの終点アドレスへのルー
トを持っている必要がある。

---[図 に]------------------------------------------------------------
FreeBSDサーバのインタフェース接続例

    【主回線】          【副回線】
   10.1.1.254へ        10.2.2.254へ
        |                 |
         \               /
          \             /
           \           /
            \         /
    default  \       /
    10.1.1.10 |     | 10.2.2.10
       fxp0   |     |   fxp1
          +---+-----+----+
	  |    FreeBSD   |
	  +------+-------+
		 |192.168.1.254
		 | vr0
                 |          LAN 192.168.1.0/24
     o-----------+--------------------------------o

----------------------------------------------------------------------

・事前準備

FreeBSD 5.4-RELEASEの場合パケットフォワードを今回の目的で行なうにはカーネ
ルオプションとして

	options IPFIREWALL_FORWARD
	options IPFIREWALL_FORWARD_EXTENDED

が必要なので、事前にカーネル構築をしておこう。

	(スーパーユーザになる)
	# cd /sys/i386/conf/
	# cp GENERIC UU		(適当な名前にコピー)
	# vi UU
	→ 上記の2つのオプションを追加して保存終了
	# config UU
	# cd ../compile/UU
	# make depend && make && make install

新しいカーネルがインストールできたら再起動しておこう。

・フォワードルールの追加

IPFW2では fwd アクションを用いてパケットのフォワードを行なう。始点/終点ア
ドレスに応じたパケットをフォワードするためのルールを追加する際の基本書式
は

	ipfw add [ルール番号] fwd <フォワード先> <ルール>

【図 ろ】の例に従い、

	「始点アドレスが10.2.2.10のものは全て10.2.2.254にフォワード」

というルールを追加するには、以下のコマンドラインで行なう。

	ipfw add fwd 10.2.2.254 ip from 10.2.2.10 to any

さらに確実にするには、始点アドレスが 10.2.2.254 のもののうち、デフォルト
ルート経由で(つまりインタフェースfxp0経由で)出て行こうとするものをフォワー
ドするように指定する。

	ipfw add fwd 10.2.2.254 ip from 10.2.2.10 to any via fxp0

こうすることで、venusと同一LANにあるホストから 10.2.2.254 宛に向けられた
通信は、直接LAN内のホストに返される。より詳しい設定については ipfw(8) オ
ンラインマニュアルを参照して欲しい。


●iproute2によるポリシールーティング

iproute2では、複数のルーティングテーブルを切り替えて使うことによりポリシー
ルーティングを実現する。送出するパケットに対し、どのルーティングテーブル
を使うかは「ルール」の設定によって決定する。

・事前準備

複数のルーティングテーブルを利用するためにはカーネルに "IP: policy
routing" オプションを組み込む必要がある。【図 へ】の手順にならい、
該当オプションを有効化した上でカーネルを再構築し、インストールする。
次回リブート後よりポリシールーティングの設定が可能となる。

---[図 へ]------------------------------------------------------------
Linuxカーネル設定(menuconfigの例)

 %image linuxmenu-1.png
	Networking options を選択

 %image linuxmenu-2.png
	IP: advanced router を組み込み(*)
	さらに IP: policy routing を組み込む(*)
----------------------------------------------------------------------

・ルーティングテーブルの選択

IP: pilicy routing オプションの有効化されたカーネルでは、以下のコマンドで
標準で利用されているルーティングテーブルを参照できる。

	# ip rule
	  ~~~~~~~
	0:      from all lookup local 
	32766:  from all lookup main 
	32767:  from all lookup 253 

これは、どのようなパケットに対してどのルーティングテーブルを参照するかの
ルールが優先順位に従って表示されている。この例では、全て(all)のパケットに
対し local, main, 253 の各テーブルがその順に参照され、いずれかのルーティ
ングテーブルにマッチするパケットであれば、そこで処理される。local, main
テーブルの内訳を見てみよう。

	# ip route show table local
	# ip route show table main

localテーブルには同一サブネットのホストに対するルーティングが、mainテー
ブルにはそれ以外のルーティング、つまり route コマンドで表示されるものと
同じものが定義されている。

これらのほかに任意の名前のテーブルを作成できる。これを追加するには
/etc/iproute2/rt_tables をテキストエディタで開き、既存のエントリを参考に
新しいテーブル名を追加する。

	# vi /etc/iproute2/rt_tables

---------------------------- rt_tables の編集
#
# reserved values
#
#255    local
#254    main
#253    default
#0      unspec

#
# local
#
#1      inr.ruhep

10	FOO          <<<<----これを追加
------------------------------

上記の例では FOO というルーティングテーブルを追加した。FOOルーティングテー
ブルの内容を確認する。

	# ip route show table FOO

エラーメッセージ等表示されなければ正常に追加できている。

・副回線利用のルール追加

---[図 ほ]------------------------------------------------------------
Linuxサーバのインタフェース接続例

    【主回線】          【副回線】
   10.1.1.254へ        10.2.2.254へ
        |                 |
         \               /
          \             /
           \           /
            \         /
    default  \       /
    10.1.1.10 |     | 10.2.2.10
       eth0   |     |   eth1
          +---+-----+----+
	  |    Linux     |
	  +------+-------+
		 |192.168.1.254
		 | eth2
                 |          LAN 192.168.1.0/24
     o-----------+--------------------------------o

----------------------------------------------------------------------

【図 ほ】の接続例に従い以下のような設定を行なう。

	(1) ルーティングテーブルFOOのデフォルトルートを
	    10.2.2.254とする
	(2) 始点アドレスが10.2.2.10のものは全てFOOテーブルを参
	    照してルーティングを決定させる

まず先程作成したFOOルーティングテーブルに対し、10.2.2.254をデフォルトルー
トと設定する。

	# ip route add default via 10.2.2.254 table FOO

次に始点アドレスが10.2.2.10のパケットはFOOルーティングテーブルを参照する
ようにする。

	# ip rule add from 10.2.2.10 table FOO

なお、ルーティングテーブルの操作を行なったときは、それ以前のルーティング
情報をクリアすることを忘れずに行なう。

	# ip route flush cache


●外部からの接続確認

外部ネットワークにあるホストから

	% telnet <ルータBのグローバルアドレス> 22

としてSSHの greeting message が出てくるか確かめよう。設定に失敗している
ケースはほとんどの場合返りパケットのルーティングができていないものだろう。
そのような場合は

	Trying b1.b2.b3.b4...

と出たまま止まってしまうはずだ。venus側で返りパケットがデフォルトルート
側に行こうとしていないか、パケットキャプチャツールを用いて調べると良いだ
ろう。デフォルトルートを持つインタフェースは fxp0(FreeBSDの場合)、または
eth0(Linuxの場合)であるから、tcpdumpで、

	venus# tcpdump -i fxp0 host <外部ホストのIPアドレス> (FreeBSD)
	venus# tcpdump -i eth0 host <外部ホストのIPアドレス> (Linux)

と起動したまま外部ホストからのtelnet試験をしてみる。ポリシールーティング
がしっかりできていればデフォルトルート側のインタフェースにはパケットが来
ないはずであるが、そうでない場合は venus から telnet起動した外部ホストに
向かっていきなりACKフラグをもったパケットが現れる【図 と】【註 ち】。

---[図 と]------------------------------------------------------------
17:29:42.108095 IP balius.gentei.org.ssh > external.example.org.55672:
S 533449298:533449298(0) ack 1310590309 win 5840 
----------------------------------------------------------------------
---[註 ち]------------------------------------------------------------
本来このパケットは副回線側に送られるべき。
----------------------------------------------------------------------

●対外NICが1枚の場合

【図 ほ, 図 に】いずれの場合もサーバの対外接続用NICは「主回線用」、「副回
線用」の2枚を装備している。しかし必ずしも対外回線ごとのNICを用意しなけれ
ばならないわけではなく、【図 り】のように単一のNICを二つのルータと同一サ
ブネットに接続した場合も、副回線へのポリシールーティングをほどこすことが
できる。

---[図 り]------------------------------------------------------------
単一LANのFreeBSDサーバのインタフェース接続例

    【主回線】      【副回線】
   [[ルータA]]    [[ルータB]]
   10.1.1.254     10.1.1.253
         |         /
          \       /
           \     /
	    |   |
         +---------+
         |   HUB   |
         +----+----+
              |
              |
              |
    10.1.1.10 | 10.1.1.11(alias)
        +-----+--------+
	|    venus     |
	| defaut route |
	| ->10.1.1.254 |
	+------+-------+
	       |192.168.1.254
	       |
	       |          LAN 192.168.1.0/24
   o-----------+--------------------------------o

----------------------------------------------------------------------


この場合、対外接続用のインタフェースにもうひとつのIPアドレスを付番する。
【図 り】の例でいえば本来のIPアドレス 10.1.1.10/24 のほかに10.1.1.11/32
を IP-alias で設定する。そしてルータBからサーバvenusにパケットをリダイレ
クトするときの宛先を、aliasアドレスである 10.1.1.11 にする。ルータBでこの
ように設定してあれば、venus側で「ルータBにフォワードする」ための判断基準
を「始点アドレスが 10.1.1.11 のものは…」と決められる。このための設定は以
下の通り。

	【FreeBSDの場合】
	# ifconfig fxp0 alias 10.1.1.11 netmask 0xffffffff
	# ipfw add fwd 10.1.1.253 ip from 10.1.1.1 to any via fxp0

	【Linuxの場合】
	# ifconfig eth0:1 10.1.1.11 netmask 0xffffffff
	# ip rule add from 10.1.1.11 table FOO
	# ip route add default via 10.1.1.253 table FOO
	# ip route flush cache


--------------------[[ コラム IP Filter と PF の場合 ]]--------------------
% 編集 註: 前回の帯域制御で「PFも……」という意見が
% あったので、PFを練習してコラムで入れてみました。
% PF使いやすいですね。

本文中で行なったようなアドレスベースのポリシールーティングは IP Filter や
PF でももちろん設定できる。

以下の説明では、

	主回線側のインタフェース fxp0 (10.1.1.10)
	デフォルトルート	 10.1.1.254
	副回線側のインタフェース fxp1 (10.2.2.10)
	副回線側のルータアドレス 10.2.2.254

の場合に、始点アドレス 10.2.2.254 のパケットを副回線側のルータにフォワー
ドする設定を示す。

【IP Filterの場合】

IP Filterではpassアクションのオプションとして、to(またはfastroute)が利用
できる。これはルーティングテーブルに依らずパケットのフォワードのみ行なう。
今回仮定した設定の場合は、

pass out quick on fxp0 to fxp1:10.2.2.254 from 10.2.2.10 to any

とする。

【PFの場合】

PFでは "route-to" を利用する。

pass out quick on fxp0 route-to (fxp1 10.2.2.254) from 10.2.2.10 to any

PFの場合は定義ファイルにマクロが利用できるので、インタフェース名やIPアド
レスに分かりやすい名前を付けておくと見通しが良くなり、将来IPアドレスが変
わったときなど、柔軟に対応できる。

main_if	= fxp0
main_ip	= "10.1.1.10"
sub_if	= fxp1
sub_ip	= "10.2.2.10"
sub_gw	= "10.2.2.254"

pass out quick on $main_if route-to ($sub_if $sub_gw) from $sub_ip to any
---------------------------------------------------------------------------

%●内部からのアクセスを副回線へ
%
%これまでの例では、副回線の先から内部サーバ宛に来たパケットに対する応答を
%正しく副回線側に返すためのものを示した。これとは逆に、LAN内部を起点とす
%る通信で副回線を利用するようにすることもできる。
%
% Linux では
% iptables -A PREROUTING -t mangle -p tcp --dport 22 -j MARK --set-mark 1
% としておいて、
% ip rule add fwmark 1 table FOO
%
% で内部発のパケットのポリシールーティングができると、そこら中に(HOWTOに
% も)書いてありますが、これがうまくいきません………
%
% ipfwでは
% ipfw add fwd 10.1.1.253 tcp from 10.1.1.11 to any via fxp0
% であっさりうまく行きました。
%
% なので、下記セクションを詳しめに書いてちょっとごまかしてます…うう



■
■アプリケーションレイヤから利用する
■

SMTPのようにpreference値をもって複数のサーバを指定できるものであれば、
副回線側に付けたグローバルIPアドレスをセカンダリサーバとして指定しておく
ことも有効だろう。

そうでないサービスの場合、動的にDNSのAレコードを変更して副回線側からのア
クセスに導く方法である程度カバーできる。たとえば、www.example.org という
名前でWebサーバを公開しているとしよう。BINDのゾーンファイルで
www.example.org を定義している行はおそらく以下のようなものになるだろう。


	www	IN	A	a1.a2.a3.a4
	; (a1.a2.a3.a4は主回線側のグローバルIPアドレス)

主回線障害時など、wwwを副回線側に導くには以下のように書き換える必要がある。

	www	IN	A	b1.b2.b3.b4
	; (b1.b2.b3.b4は副回線側のグローバルIPアドレス)


---[図 か]------------------------------------------------------------

  【正常運用時】

    a1.a2.a3.a4   +---------+     +------------------+
   ---------------| ルータA +---\ | [DNS]	     |
   		  +---------+    \|  www.example.org |
                                  |  == a1.a2.a3.a4  |
    b1.b2.b3.b4   +---------+    /|                  |
   ---------------| ルータB +---/ |		     |
   		  +---------+     +------------------+

  【主回線トラブル運用時】

    a1.a2.a3.a4   +---------+     +------------------+
   -----×××----| ルータA +---\ | [DNS]	     |
   		  +---------+    \|  www.example.org |
                                  |  == b1.b2.b3.b4  |
    b1.b2.b3.b4   +---------+    /|                  |
   ---------------| ルータB +---/ |		     |
   		  +---------+     +------------------+

----------------------------------------------------------------------

このように定義されたゾーンファイルを自動的に書き換えるためには、make と
m4【註 ぬ】を利用するととても単純に作業できる。

---[註 ぬ]------------------------------------------------------------
マクロ定義とその展開を処理するための汎用マクロプロセッサ。ほとんどのUnix
システムに付属している。
----------------------------------------------------------------------

m4 では特定の文字列を別の文字列に置き換えるような定義を行なえる(マクロ定
義と展開)。たとえば、主回線のグローバルIPアドレス a1.a2.a3.a4 を別の文字
列(たとえばMAIN_NET)に置き換えて、

	www	IN	A	MAIN_NET

のように記述しておく。これをm4で処理すると通常は MAIN_NET → a1.a2.a3.a4
という置き換えをするのだが、必要に応じて MAIN_NET → b1.b2.b3.b4 という
置き換えに変更することができる。

仮に、example.org のDNSレコード情報を example.zone というファイルに保存し
ていたとしたら、まずそれを example.src というファイルにリネームする。次に
同じディレクトリに【リスト る】のような Makefile を作成する(行頭の空白は
全てTAB文字とする)。

---[リスト る]--------------------------------------------------------
#
# Makefile for example.zone
#
M4OPT		=
SRC		= example.src
all:		example.zone

example.zone:	${SRC}
	echo ';;; DO NOT EDIT THIS FILE! Edit example.src' > $@
	cat ${SRC} | m4 ${M4OPT} >> $@

backup:
	touch ${SRC}
	${MAKE} M4OPT=-DBACKUP
----------------------------------------------------------------------


続いて、makeコマンドを実行する。

	# make

これで example.zone ファイルが example.src ファイルを元に生成される。
念のため diff を取って、第1行目以外は違いのないことを確認しよう。

	# diff -ua example.{src,zone}
	--- example.src       Sat Jun  4 15:06:00 JST 2005
	+++ example.zone      Sat Jun  4 15:06:20 JST 2005
	@@ -1,3 +1,4 @@
	+;;; DO NOT EDIT THIS FILE! Edit example.src
	 ;
	 ; Zone file of example.org
	 ;

続いて、example.src をm4のマクロ置換を前提としたものに書き換える。たとえ
ば、「そのとき優先で利用するIPアドレス」を MAIN_LINE というマクロで表すこ
ととする。example.src の先頭部分に以下の【リスト を】の記述を追加する。
---[リスト を]--------------------------------------------------------
ifdef(`BACKUP',
`define(`MAIN_LINE', `b1.b2.b3.b4')',
`define(`MAIN_LINE', `a1.a2.a3.a4')')
----------------------------------------------------------------------

文字列のクォートがバッククォート(`)で始まりシングルクォート(')で終わるこ
とに注意しよう。【リスト を】の記述は、m4処理中に「BACKUP というマクロが
定義されていたら MAIN_LINE を "b1.b2.b3.b4" に、未定義なら MAIN_LINE を
"a1.a2.a3.a4" に定義せよ」という意味を持つ。m4ではコマンドラインオプショ
ン -D で任意のマクロを定義することができ、のちほどこれを利用する。

次に example.src 中、「www」のAレコードの定義部分を以下のように変更する。

----------------------------------------------------------------------
www		IN	A	MAIN_LINE
----------------------------------------------------------------------

再度 make を起動し example.zone ファイルを確認する。

	# make
	  ~~~~
	# grep '^www' example.zone
	  ~~~~~~~~~~~~~~~~~~~~~~~~
	www	IN	A	a1.a2.a3.a4

今度は、m4起動時に BACKUP マクロを定義するよう make ターゲット、
backupを評価する。

	# make backup
	  ~~~~~~~~~~~
	# grep '^www' example.zone
	  ~~~~~~~~~~~~~~~~~~~~~~~~
	www	IN	A	b1.b2.b3.b4


wwwのAレコードが変わることが確認できたら、もう一度makeを起動して
元(a1.a2.a3.a4)に戻しておく。

上記の設定が確認できたら、「主回線が通じているかを検査し、一定時間以上不
通状態が続いたら所定のディレクトリで「make backup」を起動するスクリプト」
をcronジョブに登録しておけば、Webサービスの副回線への移行を自動化できるだ
ろう【註 わ】。このためのスクリプトの例を【リスト よ】に示す。
	

---[註 わ]------------------------------------------------------------
もちろんDNSレコードのTTLがあるので外部からの名前参照で副回線側アドレスが
返るようになるまでは一定時間がかかる。必要ならレコード自体のTTLを数時間
程度に短く設定しておくのもよいだろう。
----------------------------------------------------------------------

---[リスト よ]--------------------------------------------------------
【pingを利用したDNS切り替え簡易スクリプト例 swdns.sh】
(リスト る に相当する Makefile が作成してあることが前提)

#!/bin/sh

# PPPoEの対向アドレス
ISP=i1.i2.i3.i4

# DNSのゾーンファイルを置いているディレクトリ
ZONEDIR=/var/dns/namedb

case `uname` in
  *BSD)  PING='ping -t 5' ;;
  Linux) PING='ping -w 5' ;;
esac

ckalive () {
  $PING -c 1 $ISP || \
  $PING -c 1 $ISP || \
  $PING -c 1 $ISP
}
ckalive > /dev/null 2>&1  ||   TARGET="BACKUP"

(cd $ZONEDIR; make $TARGET)
----------------------------------------------------------------------

■
■柔軟な切り替えを
■

現状ではコンシューマ向けの回線サービスもネットワーク機器も、想定される連
続運用時間があまり長くなく、定期的にルータにリセットをかけて再接続させる
必要がある場合も珍しくない。回線およびルータ機器の安定度に応じて、あるい
は負荷分散の目的で副回線を利用するのは効果的といえる。

主回線以外でも外部と通信できるように設定さえしてあれば、それをどのような
タイミングで生かすかは管理者の意志次第となる。ぜひ様々な使いわけを検討し
ていただきたい。

■
■参考文献
■

○ipfw
http://www.jp.freebsd.org/cgi/mroff.cgi?subdir=man&lc=1&cmd=&man=ipfw&dir=jpman-5.2.0%2Fman§=8#toc

○iproute2
http://www.linux.or.jp/JF/JFdocs/Adv-Routing-HOWTO/index.html

○PF
http://www.openbsd.org/faq/pf/ja/


yuuji@example.org
Fingerprint16 = FF F9 FF CC E0 FE 5C F7 19 97 28 24 EC 5D 39 BA
HIROSE Yuuji - ASTROLOGY / BIKE / EPO / GUEST BOOK / YaTeX [Tweet]