デッドマンスイッチによるiptablesの安全な変更
古本屋で「Red Hat Linux Firewalls」の本を手に入れたのでパラパラしていたら、面白いiptablesのネタを見つけました。のでちょっと紹介します。
Red Hat Linux Firewalls (redhat PRESSシリーズ)
- 作者: ビルマッカーティ,Bill McCarty,中川和夫,ヴァインカーブ
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2003/04
- メディア: 単行本
- 購入: 1人 クリック: 5回
- この商品を含むブログ (4件) を見る
この本は2003年発行ということで、既にいろんな記述が古くなっているのは確か。しかしiptablesやファイアウォールの基本的な考え方などはそうそう変わるもんでもないので、今読んでも参考になります。
リモートホストのiptables設定時の悩み
RedHatやCentOSなどRH系Linuxのリモートホストにsshでログインして作業しているとき、iptablesのルールを試行錯誤しながら修正したいことがあります。この場合、いきなり/etc/sysconfig/iptablesファイルはいじらずに、まずはiptablesコマンドで1行ルールを色々試してみるのが普通です。
この試行錯誤の最中に、例えばもし間違えて以下のようなコマンドを打つと、sshがブチ切られて以後何も繋がらなくなってしまいます。
# iptables -I INPUT -p tcp --dport 22 -j REJECT
これは「-A INPUT」ではなく、間違って「-I INPUT」としたため、チェーンの末尾ではなく先頭にルールを追加しちゃった! という例。わざとらしいかな?
上記のようにiptablesコマンドで設定している場合は、「# service iptables restart」さえ打てれば、/etc/sysconfig/iptablesファイルを読み込んでiptablesが再起動してくれるので、間違えて打ち込んだ1行コマンドのルールは消え失せてくれます。
ということでこのような場合はコンソールさえあれば、万一通信不可となってしまっても、コンソールからiptablesをrestartすれば良いのですが……政治的な理由でコンソールが使えなかったり、あるいは使えないことは無いがひどく使いにくい(デザイン的に・政治的に・技術的に・スペース的に)、ということもよくあります。
シェルスクリプトによるiptablesデッドマンスイッチ
以下のようなスクリプトになります。
#!/bin/sh echo "iptablesを実行します。実行後、プロンプトに従いyキーを入力してください。" echo echo "iptables記述に誤りがあり通信不可となった場合は、yキー入力のリモートエコーが返りません。" echo "その場合は、10秒待てば自動的にリカバリされます。" echo # (1) 実行したいiptablesコマンド iptables -A INPUT -p tcp --dport 22 -j REJECT # (2) 10秒間待ってから、iptablesをrestartする ( sleep 10; service iptables restart; ) & echo "Enter [y] Key" read line case $line in [yY]*) # (3) yが入力されたら、iptablesのrestartをkillしてやめさせる kill $! ;; *) ;; esac
まず、(1)でiptablesコマンドを実行します。ここに試行錯誤したいルールを書いておきます。
(2)がこのスクリプトのキモで、10秒sleepしてからiptablesをrestartします。つまり何もしないでボーっとしていると、(1)で実行したiptablesコマンドは10秒後に無効となります。ここではコマンド全体をカッコでくくってサブシェルとして、その最後に&を付けることでバックグラウンド起動としています。
(3)では、readコマンドで読み込んだキー入力がyだった時のみ、「kill $!」を実行しています。ここで$!とはシェルの特殊変数で、最後に実行されたバックグラウンドコマンドのプロセスIDが入っています。ここではこのプロセスIDの対象となるコマンドとは、(2)のサブシェルです。ですから$!をkillすれば(2)の処理をやめさせる、すなわちiptablesのrestartを止めることができるわけです。
余談
ここで出てきたデッドマンスイッチ(デッドマン装置)とは、元は「運転士が突然死しても車両が暴走するのを防ぐ」という車両の安全装置です。ここではリモート接続が切れることによってデッドマン装置が発動し、iptablesをリカバリする、という動作を指しています。
デッドマン装置は、身近なところにも結構あります。例えば鉄オタには常識なのですが、電車というのは基本的に無操作ではブレーキがかかるようになっています。このため、突然運転士が倒れたり車外に放り出されても、無操作となればそのうちブレーキがかかり、列車は停止します。
この他にも、最近のフォークリフトは基本的に常にブレーキがかかっており、「ブレーキペダルを踏んでブレーキを解除」することで動くのが普通です。これはデッドマンブレーキと呼ばれます。
ちなみにこの辺の設計思想は、現代の自動車(AT車)とは大違いですね。無操作ではエンストして止まるMT車に対し、無操作では延々とクリープ現象で動き続けるAT車というのは、機械工学的に根本的な欠陥品なんじゃないかなぁ(そのせいで踏切侵入事故もありましたね)。