洗練されたPerl: xinetdプログラムによるシステム管理

inetdに代わる優れたプログラム

UNIX管理者の誰もがよく知っているとおり、inetdは、集中構成ファイル(inetd.conf)によって着信ネットワーク接続要求を管理するデーモンです。xinetdデーモンは、inetdに代わるものであり、さまざまな改善された機能や新機能を備え、構成も容易です。この記事では、inetdの背景となる概念について説明し、また、xinetdの実際のセットアップ例を示します。

Teodor Zlatanov (tzz@iglou.com), Programmer, Gold Software Systems

Teodor Zlatanov氏は、1999年、ボストン大学でコンピューター・エンジニアリング理学修士号を取得しました。1992年以来、プログラマーとしての業務に従事しており、使用してきた言語は、Perl、Java、C、C++です。テキスト構文解析におけるオープン・ソースによる作業、3層のクライアント/サーバー・データベース・アーキテクチャー、UNIXのシステム管理、CORBA、プロジェクト管理に関心を持っています。



2001年 11月 01日

inetdデーモンは、長い間使われてきました。その機能を受け継ぐプログラムにはいくつかありますが、最も柔軟で簡単なものはxinetdでしょう。xinetdは、inetdを凌ぐ機能を備えており、TCPラッピング、モジュール構成、接続要求リダイレクション、着信接続要求に対する負荷制限などの機能だけを見ても、xinetdがシステム管理者にとって申し分のない選択肢であることがわかります。

この記事は、初級から中級のシステム管理者を対象にしており、ここで示す説明と例は、inetdにそれほど詳しくないユーザーでも理解できるものです。この記事では、インストールからセキュリティー・ポリシーの実施まで、xinetdの簡単な使い方について考察します。

始める前に

この記事の目的上、システムは最新(2000年以降)のメインストリームUNIX(Linux、Solaris、BSD)であることが望まれます。しかし、他のオペレーティング・システムでも同様に動作するはずです。古いバージョンのPerlおよびUNIXその他のオペレーティング・システムでも動作する可能性はありますが、動作しない場合は、皆さん自身の課題として取り組んでみてください。ここで示される例は、Red Hat Linux環境のものですが、他のシステムでも動作する(ただしchkconfig以外)はずです。


inetdとは

UNIXシステム管理者にとって、inetdは、cp/rm/mvコマンドと同じくらい基本的なものであり、着信要求の処理に欠かせないものです。しかし、実際にはどのようなものであり、何を行うものなのでしょうか。

その答えとしてまず挙げられるのはTCP/IPです(UDPも含まれますが、ここでは取り上げないことにしましょう)。ホストとの接続を確立する際、実際にはTCP/IP接続(通常はソケット)が生成されます。これは、ホストとの間の電話通話接続のようなものです。TCP/IP接続は、発信側ホストと受信側ホストによって一意に定義されますが、識別子はその他にもあります。私たちがサーバーに接続する際、サーバーはどのような方法でwebserver、telnet、SSH、FTPなどの接続を識別するのでしょうか。ソケットは、接続に使用されるポートによって定義されます。たとえば、ポート21は着信FTP、ポート22はSSH、ポート23はTELNETというように決まっています(その他のポートについては、UNIXシステムの/etc/servicesを参照してください)。

接続が確立されたということは、相手側が受話器をとったということと同じです。そしてこれには、「オペレーターを通した通話」と「直接通話」があります。「直接通話」は「サーバーへの直接接続」に相当し、また「オペレーターを通した通話」は「inetdを使用する方法」に相当します。オペレーターは一連の着信回線(ホスト上のポート)の処理を行い、それをプログラム(サーバー)に渡します。

UDPの接続方法は他のものとは異なります。TCPなども基本的には相手側との通信ですが、信頼性は保証されません。先ほどと同様に電話にたとえると、UDPは、メッセージをコンベヤー・ベルトに載せて受信者に送るようなものです。このコンベヤー・ベルトを使うことによって、より多くのメッセージの処理が可能となりますが、メッセージがあまりに多い(ネットワーク・トラフィックが多い)場合、あるいは、メッセージを読むのに時間がかかりすぎる(サーバーのビジー状態)場合には、受信者が送られたメッセージの一部を失う可能性があります。

Inetdを使用すると、いくつかのチェックの後に特定のサーバーに対して接続がリダイレクトされます。そして、すべての着信接続要求の管理は、inetd.confという1つのファイルによって行われます。これにより、システムにおけるサービスの追加/削除/変更/検討がより簡単に行えるようになります。たとえば、TCPラッパーを持つSolarisシステムでは、ftpは次のように定義されています。

リスト1. inetd.confにおけるFTPサービスの定義
ftp     stream  tcp     nowait  root    /usr/sbin/tcpd          in.ftpd

これらはすべて、FTP接続に必要なパラメーターです。これはすなわち、TCP/IP(tcp)をストリーム指向(stream)モードで使用し、同時(nowait)に複数のFTP接続を許可し、rootとして実行し、FTPを起動(TCPラッパーを起動し、それによってFTPデーモンを起動)しているということです。

構文解析が難しいと言われれば確かにそうですが、複雑でなければならないということは決してありません。xinetdは、inetdの設計を継承しつつ、それをモジュール化しています。つまり、サービスごとに独自の構成ファイルを持たせることができます。また、xinetdには、TCPラッパーなど、簡単な構成を可能とする機能も追加されています。

xinetdは、一元構成(オペレーター)のアプローチを維持しており、すべての構成ファイルを1カ所(通常は/etc/xinetd.confと/etc/xinetd.d/*)に格納することができ、容易なシステム管理が可能です。また、モジュール構成であるため、xinetd.dディレクトリーへのコピー/削除によってサービスを複数のマシンに分散させることができます。また、その他のインクルード・ディレクトリーの指定も可能です。

なお、xinetd FAQ(この記事末尾の参考文献を参照)によると、RPCプログラムとxinetdの相性はよくないようです。しかし、RPCにinetdを使用し、その他のプログラムにxinetdを使用するようにすれば問題はありません。これは、大勢の外国人の中に1人だけ別の国の言葉を話す人がいた場合、どうしても2人の通訳が必要になってしまうのと同じことです。


xinetdの概要

では、xinetdとはどのようなものなのでしょうか。まあ、はっきり言うと単なるプログラムにすぎません。着信ネットワーク接続要求の処理に関しては特筆すべき点はなく、PerlやPython、Javaでも同じことが可能です。xinetdはCで書かれており、速度に関しては、少なくとも従来のinetdに劣るということはありません(たとえば、TCPラッパーは、着信接続要求ごとに実行する必要はなく、メモリーに対して起動時にロードされます)。

xinetdは開発途上のプログラムである(皆さんがお持ちのバージョンは古いバージョンかもしれません。ホーム・ページ(参考文献を参照)で最新版をチェックしてみてください)ため、パッチのリリースに時間がかかるinetdとは違い、xinetdのセキュリティー・ホールに対するパッチは速やかにリリースされます。もちろん、xinetdにはソース・コードが付属しているため、ソース・コードをレビューすれば脆弱性に関するチェックを自分で行うこともできます。

xinetdに対してサービスを定義するには、/etc/xinetd.confに指定された汎用パラメーターとは別に、特定の構成を指定するサービス・ファイルを作成します。したがって、/etc/xinetd.confが次のようなものである場合には、

リスト2. xinetd.confの例(標準のRed Hat 7.1)
defaults
{
        instances               = 60
        log_type                = SYSLOG authpriv
        log_on_success          = HOST PID
        log_on_failure          = HOST
        cps                     = 25 30
}
service telnet
{
        flags           = REUSE
        socket_type     = stream        wait            = no
        user            = root
        server          = /usr/sbin/in.telnetd
        log_on_failure  += USERID
        disable         = yes
}
includedir /etc/xinetd.d

/etc/xinetd.dに置かれたすべてのサービス・ファイルはこれらのデフォルトを継承し、それぞれのパラメーターを指定します。そして、telnetサービスは、サブディレクトリーではなくトップレベルで定義されています。これはきわめて優れた点であり、また、このモジュール構成によって、複雑な構成も可能となります。

xinetdによって構成ファイルを再度読み込む場合は、USR2信号を送るだけでよく、再起動の必要はありません。

これらのパラメーターにどのような意味があるのか、リスト全体をザッと見てみましょう。manページが正しくインストールされていれば、コマンド・ラインでman xinetd.confを実行してリストを見ることもできますが、ここでは、ソケットやサービスについて完全に把握していない方でも理解できるように、各パラメーターについてわかりやすく説明します。ただし、いくつかのパラメーター(rpc_version、rpc_number)は省略しました。

汎用パラメーター

id
当該のサービスを表す一意の名前。サービス名は、中括弧の前ですでに指定されていますが、IDによって論理的に同一のサービスに対して複数のプロトコルを指定することができるようになります。ただし、これは一時的ユーザーに限られます。たとえば、NFSサービスは、UDPまたはTCP伝送プロトコルを介して実行することができます。xinetd内部のtimeサービスは、Red Hat Linux 7.1用のTCPバージョンとUDPバージョンがそれぞれ/etc/xinetd.d/timeと/etc/xinetd.d/time-udpにあります。
type
これは、専用のサービスのみに適用されることから、実際には「specialtype」と呼ぶべきものです。RPCサービスを表す「RPC」(Sunの「リモート・プロシージャー呼び出し」は、セキュリティー上のさまざまな問題の原因となるため、避けた方がよいでしょう)、timeサービスなど、xinetdに組み込まれたサービスを表す「INTERNAL」、システムのリスト(/etc/services、またはRPCサービスの場合は/etc/rpc)に含まれていない標準外サービスを表す「UNLISTED」を組み合わせて指定することができます。
flags
追加フラグはすべてここで指定します。このリストは、非常に膨大かつ詳細です。興味深いフラグとしては、REUSE(telnetなどのソケット再使用)、NAMEINARGS/NOLIBWRAP(TCPラッパーを手動で呼び出す場合、またはラッパー全体を回避する場合)、NODELAY/KEEPALIVE(TCPソケットの調整)、DISABLE(トップレベルの「disable」パラメーターのオーバーライド)、SENSOR(ある種のサービス拒否(DoS)ネットワーク攻撃の検知/阻止)などがあります。
disable
サービスを無効にする場合以外は常に「no」に設定します。Red Hat Linuxのchkconfigプログラムは、「disable」パラメーターの切り替えが可能です。Red Hatで特定のサービスを有効化/無効化する場合は、おそらく、chkconfigを使う方が手動よりも簡単です。ただし、chkconfigを使用する場合、サービス・ファイルが/etc/xinetd.d/SERVICEに格納されている必要があります。先ほどのリスト2の例に関する限り、chkconfigは、要求されてもtelnetのオン/オフを行いません。見方によって、これはバグとも仕様とも考えることができます。
socket_type
通常は「stream」に設定します。ただし、UDPサービスを使用している場合は「dgram」に設定します。その他にも「raw」と「seqpacket」がありますが、これらを使用する状況はかなりまれです。
protocol
これは、接続に使用されるプロトコルです。通常は"tcp"または"udp"ですが、理論上は/etc/protocolsにあるものなら何でも使用することができます。
wait
「no」に設定した場合、xinetdは、当該のサービスに対して接続ごとに新しいハンドラーを起動します。「yes」に設定した場合は、ハンドラーが停止するまで、1つのハンドラーによって後続の接続要求がすべて処理されます。ほとんどの場合、「no」に設定します。
server、server_args
ハンドラーのプログラム名、およびハンドラーが取得するパラメーター。inetdの場合と同様、引数にはハンドラー名を入れません。
port
当該サービスのポート。ポートは/etc/servicesファイルによってサービスにマップされるため、通常は不要です。
redirect
xinetdによって、サービスに対するすべてのトラフィックを別のホストに送信することが可能となります。これにより、ファイアウォールを持つホストは、xinetdの集中転送機能を介して、外部ネットワークに接続する必要なく、セキュリティーが確保されたトラフィックを受け入れることができます。この機能を利用すれば、わずかな労力で、2つのホスト間におけるサービスのフェイルオーバーも行えるようになります。
banner、banner_success、banner_fail
接続の成功時/失敗時にファイルから印刷するカスタム・テキスト・ブロック。
enabled
「disabled」パラメーターおよびDISABLEフラグをグローバル・レベルで補います。
include、includedir
ファイル/ディレクトリーをインクルードするようxinetdに指示します。

環境パラメーター

user、group、umask、groups
サービス・ハンドラーの起動の際にxinetdが扮するUNIX属性。これは主に、セキュアではないサービスのために使われます。
nice
当該サービスのシステムに対する重要度を決定するUNIX優先レベル。システムに合わせた調整が可能です。詳しくは、「nice」のmanページをご覧ください。
env
サービス・ハンドラー用の環境変数。
passenv
xinetdからサービス・ハンドラーに渡す環境変数。

リソース管理パラメーター

instances
同時に起動できるハンドラーの数。これを調整することによって、サービス拒否攻撃を防止することができます。デフォルト(無制限)の設定は「UNLIMITED」です。
max_load
システムが過負荷の場合に、接続要求の受信を停止します。負荷の数はシステムによって異なるため、正確に分かる場合以外は、調整は避けましょう。
rlimit_as、rlmist_cpu、rlimit_data、rlimit_rss、rlimit_stack
rlimitパラメーターは、サービス・ハンドラーのリソース限界(メモリー、CPU、特定のメモリー域)を指定します。

セキュリティー関連パラメーター

only_from、no_access
これは、TCPラッパーを補うものであり、接続要求を行うホストをブロックする手段となります。TCPラッパー(ルールは通常、/etc/hosts.allowにあります)によって特に指定されていない限り、デフォルトではすべてのアクセスを許可します。
access_times
1日のうちのサービス利用可能時間。たとえば、「6:00-23:00」と指定した場合、午前6時から午後11時1分までサービスを利用できることになります。
log_type、log_on_success、log_on_failure
各種ロギング・オプション。特にUSERIDフラグには問題があります。接続中のマシンに対して、接続しているユーザーに関する問い合わせを行うため、パフォーマンスの低下につながります。できればUSERIDの使用は避けた方がよいでしょう。
bind
通常はセキュリティー上の理由により、サービスを特定のインターフェースに限定します。たとえば、内部ネットワーク上でのFTPサービスは単にFTPとして扱い、外部からのFTP接続に対して侵入者警報を生成することができます。これには「id」パラメーターが有用です。
per_source
1つのソースIPからの最大サービス・インスタンス数を指定します。単一ソースからのサービス拒否攻撃や過度の接続要求を行う異常なプログラムへの対処に役立ちます。
cps
1秒当たりの最大許容接続要求数、およびサービスを再び有効化するまでの秒数。「30 45」は、「1秒当たりの着信接続要求数を30に制限し、その制限を超えた場合は45秒間待機する」という意味です。主にサービス拒否攻撃の防止に役立ちます。
deny_time
SENSORフラグが設定された人からのサービスを拒否する期間。

TCPラッパーの置き換え

TCPラッパー・パッケージは、非常に役に立つツールです。一元化されたファイル(通常は/etc/hosts.allowと/etc/hosts.deny)によって、必要に応じて任意のホストからのアクセスをサービスごとに許可/拒否することができます。しかし、残念なことに、TCPラッパー・ライブラリーは、システム負荷、リソース限定、攻撃などがあまり考慮されていません。xinetdにはTCPラッパー機能が組み込まれているため(libwrapライブラリーを介して)、従来と同じ構成ファイルを使用しながら、スムーズにxinetdに移行することができます。

移行は、きわめて簡単に行うことができます。従来のhosts.denyおよびhosts.allowファイルはそのままxinetdに使うことができます。また、xinetdにはTCPラッパーの機能を向上させるさまざまな接続制御オプションがあります。たとえば、1秒当たりの接続要求数の制限や負荷が高すぎる場合の接続要求数の制限などは、サーバー管理上のきわめて有用な機能です。

まず、xinetdをコンパイルする際は、必ずlibwrapオプションを指定してください。このオプションを指定しないと、TCPラッパーが認識されません。Red Hat LinuxでRPMからxinetdを呼び出す場合は、マシンを公開する前に必ずTCPラッパー・ファイルが正常に動作することを確認してください。


高度な使い方:フェイルオーバー

xinetdにはさまざまな使い方がありますが、特にredirectパラメーターはきわめて興味深い使い方ができます。ご存じのとおり、フェイルオーバーはかなり難しい作業であり、ハードウェアによるフェイルオーバーはコストがかかります。これから説明する方法は、シンプルなソフトウェアによるもので、低コストで効果を得ることができます。ただし、リダイレクト・ステーションがシングル・ポイント障害(SPOF)となるため、その点を許容できるかどうか検討が必要です。許容できない場合には、(高コストな)ハードウェアによるフェイルオーバーを採用できるかどうか考えてみてください。

まず、複数のマシンの中から「アクティブ」マシンを選ぶ方法を決めます。では、スクリプト「set_active.pl」を使って行ってみましょう(ここではtelnetサービスを対象としていますが、代替サーバーへの切り替えが問題なくできるものであれば、他のサービスでも可能です)。このスクリプトは、新規フェイルオーバーの設定に使用するマシン名と、編集するべき適切な/etc/xinetd.d/SERVICEファイルを示すサービス名を取得します。スクリプトを自由にカスタマイズして別のファイルを編集したり、別のパラメーターを設定したりしてみてください。この作業は、「perl -p -i -e」の1行スクリプトでもできますが、このようなやり方の方が可能性がより拡がり、パラメーターのエラーのチェックも可能となります。

これは非常に簡単で、後は手動、クローン・ジョブ、別のプログラムによる起動など、このスクリプトを呼び出すプロシージャーを決めるだけです。こうなると後はアーキテクチャーの問題です。この時点で、忘れずにUSR2信号をxinetdに送るか、または必要に応じて再起動してください。Red Hat Linuxでは、「pkill -USR2 xinetd」によって信号の自動化が可能です。また、Linuxや他のほとんどのUNIXシステムでは、「/etc/rc.d/init.d/xinetd restart」のみでxinetdの再起動ができます。

この種のフェイルオーバーは、データベース接続ではデータベース側にかなりの工夫を加えないと動作しません。rsync、ssh、ftp、telnetなど、フェイルオーバー・マシン間に依存関係がないプロトコルに対して使用をお勧めします。


まとめ

xinetdが提供する多くの機能を見ると、xinetdは明らかに使用する価値のあるものです。また、「バグは報告に応じてきわめて迅速に修正される」「ソース・コードを自由に入手できる」「既存のinetd構成から容易に移行できる(xinetdに付属するitoxヘルパー・プログラムを使用すれば)」といった、xinetdの他の利点も忘れてはなりません。

xinetdをぜひ使ってみてはどうでしょうか。もし使用できないとすれば、その第一の理由は下位互換性の問題、続いて特定のプラットフォームとの互換性の問題が挙げられるでしょう。xinetdソフトウェアは、SolarisサーバーやLinuxサーバーではきわめて一般的なものですが、その他のプラットフォームにおいては未解決の問題もあるかもしれません。

参考文献

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Linux, Open source
ArticleID=231730
ArticleTitle=洗練されたPerl: xinetdプログラムによるシステム管理
publish-date=11012001