アクセスコントロールを知ってサーバ運用の基本を理解しよう

 いちばん近道なLinuxマスター術
Linuxの用途として,サーバとして動作させるのは機能の見せ所だ。サーバソフトにはApacheやbind,ftpd,squidなど多くのものがあるが,どこのドメイン(IPアドレス)からのアクセスは許可し,拒否設定はどのようにするかは,すべて一括管理されている。第3回目は,アクセスコントロールをテーマとして,インターネットに公開する前に知っておきたい必須の設定項目を解説していこう。
第3回 アクセスコントロールを知ってサーバ運用の基本を理解しよう

 24時間インターネット接続できる環境は,今やケーブルインターネットやフレッツ・ISDNなどで比較的低価格で手に入れることができるようになった。このようなユーザーであれば,回線を十分に使いこなしたいという要望が高いはずだ。そこで候補に上がるのが,サーバソフトを動かしておいて,出先からもアクセスできるようにする用途だ。ほかにもISPのサーバのようにnamedやhttpdなどを動かしてインターネットサーバを実体験することが可能だ。

 ここで注意しなければならないのは,ほぼ常時接続という環境ではセキュリティについての配慮だ。

 インターネットサーバは,日ごろの管理・監視作業が必要といわれるが,個人で運用する程度であれば導入時の設定さえきちんと行なっておけば,それほど手間をかけないで運用することも可能である。

 UNIX 上で利用されるサーバーソフトウェアには,大きく分けて「常に起動しているもの」と「必要に応じて起動されるもの」の2種類がある。一般的には,前者にはsendmailやApache,後者にはftpサーバやPOP3サーバなどが当てはまる。今回は主に,後者の「必要に応じて起動されるサーバソフトウェアのアクセスコントロール」について解説していこう。

icon 基本はinetdとtcp wrapperにある

 必要に応じて起動されるサーバは,「inetd」と呼ばれるプログラムが管理を行っている。クライアントとサーバの間は,inetdが中継する役割を持ち,常にメモリを占有せずに必要なときだけ起動するというスタンスなのだ。inetdは,特定のサービス(POP3 や telnet など)への接続を一括して受け付け,そのサービスに対応するサーバプログラムの起動を行う。inetdは,複数のサーバーの起動を担当することから,「internet super server」や「internet super daemon」と呼ばれることもある。

 inetdの設定は,/etc/inetd.confと呼ばれるファイルで行う。このファイル内で設定することで,それぞれのサービスへのリクエストに対しどのサーバープログラムを実行するかを設定しているのだ。また,例えば「telnet サービスは危険なので提供しない」などという場合にも,このファイル内で無効にする設定を行う。

icon inetd.confの記述

 inetd.confの記述方法は次の通りだ。「#」で始まる行はコメントとして扱われ,各フィールド間は1つ以上のスペースやタブ文字で区切られる。

フィールド 内容 設定例
第1フィールド サービス名 (/etc/services の中から選択) ftp
第2フィールド ソケットタイプ(stream/dgram) stream
第3フィールド プロトコル(tcp/udp) tcp
第4フィールド wait/nowait(dgramの場合のみ有効) nowait
第5フィールド 実行ユーザー(グループ)権限 root
第6フィールド サーバープログラム in.ftpd
第7フィールド サーバープログラム引数 -l -a

 特定のサービスを使用不能にするには,該当する行をコメントアウトにすればよい(その後,/etc.rc.d/init.d/inetd restartとして再起動する必要もある)。たとえば,telnetサービスを無効にするのは次の通りだ。

telnet stream tcp nowait root /usr/sbin/tcpd in.telnetd
# telnet stream tcp nowait root /usr/sbin/tcpd in.telnetd

 次に挙げるinetd.confはLinuxの一例だ。

リスト
別ウィンドウで見る or 03a.txt

icon tcp wrapperは今や標準のアクセスコントロール手段

 inetd.confの中で,「tcpd」という文字列が見られるだろう。最近のディストリビューションでは,この「tcpd」が使われており,「tcp wrapper」と呼ばれる外部からのアクセスをコントロールするプログラムだ。inetdから起動するサーバプログラムは,このtcp wrapperを経由することで,特定のホストからのアクセスのみを許可したり,逆にアクセスを拒絶したりすることができる。ホスト名/ドメイン名/IPアドレス/IPアドレスを指定することで制御が可能だ。これらの設定を記述するのが「hosts.allow/hosts.deny」ファイルである。

 それぞれのファイルには,「hosts.allow」が許可条件,「hosts.deny」には拒絶条件を記述する。通常は基本ポリシー(ほとんどを許可するのか,ほとんどを拒絶するのか)を決めてから,例外を設定することでアクセス制御を行う。

 たとえば,「基本的に接続は拒絶。LAN(内側)からの ftp と telnet は許可」や「基本的にすべて接続は許可。ただし特定のホストからの telnet 接続は拒絶」のように設定することができる。標準のディレクトリ先は,OSによって異なるため注意が必要だ。

OSによるhosts.allow/hosts.denyディレクトリの違い
Linux /etc/
FreeBSD (ports) /usr/local/etc/
Solaris /etc/


icon hosts.allow/hosts.denyの記述方法

 hosts.allow/hosts.deny,2つのファイルは,それぞれの目的が「許可するか」,「拒絶するか」といった違いだけだ。記述方法に違いはない。また,多くのファイルと同じく,「#」で始まる行はコメントと判断される。

サーバプログラムリスト: クライアントリスト [: シェルコマンド]

※サーバプログラムリスト
 inetd経由でtcpdが起動するサーバプログラムを指定する。上記のように「in.ftpd」や「in.telnetd」などとなり,複数を同時に指定することも可能だ。その場合にはスペース(空白文字)かカンマ(,)で区切り,「in.ftpd in.telnet」,「in.ftpd,in.telnetd」といった指定を行う。すべてのプログラムやIP(ドメイン)を指定する場合には「ALL」を使用する。

※クライアントリスト
 この項目には,ホスト名やIPアドレス,ドメイン名やIPアドレス+ネットマスクなどを利用して指定する。複数指定する場合には,スペースかカンマで区切ろう。

# IPアドレスで指定
127.0.0.1
# ネットワークで指定
192.168.1.0/255.255.255.0
# ネットワークで指定
192.168.1.
# ネットワークで指定(例外を設定)
192.168.1. EXCEPT 192.168.1.1
# ドメイン名で指定
.some.domain.com
# ドメイン名で指定(例外を設定)
.some.domain.com EXCEPT yourhost.some.domain.com
# ホスト名で指定
myhost.some.domain.com

 上記のような記述方法がある。「EXCEPT」キーワードを使用することで指定範囲の中から例外も記述できるため,柔軟性に富んだ指定が可能だろう。

※シェルコマンド
 通常実行するコマンドをそのまま記述することができる。そのコマンドに時間がかかるような場合には,末尾に「&」をつけることによってバックグラウンドで実行可能だ。

 また,シェルコマンドのフィールドでは「%」+「文字」を特定の文字列に展開することができる。アクセスしてきたホストのIPアドレスなどをシェルコマンドに渡すことが可能なのだ。

展開される文字列内容
%a (%A) クライアント(サーバ)のIPアドレス
%c ユーザ名,ホスト名,IPアドレスなどのクライアント情報
%d サーバプログラムのプロセス名 (argv[0])
%h (%H) クライアント(サーバ)のホスト名。無い場合にはIPアドレス
%n (%N) クライアント(サーバ)のホスト名
%p サーバプログラムのプロセスID
%s プログラム名,ホスト名,IPアドレスなどのサーバ情報
%u クライアントのユーザ名
%% '%'の文字


実例1
/etc/hosts.deny
ALL: ALL

/etc/hosts.allow
ALL: 127.0.0.1
ALL: 192.168.1.0/255.255.255.0
in.ftpd: .trusted.domain.com

 上記の例では,まず最初にhosts.denyですべての接続を拒絶する宣言をしている。「すべての」を示す場合「ALL」が該当する文字列だ。

 次に,hosts.allowの中で接続を許可するものを記述する。

 1行目では,許可するホストとして「127.0.0.1」(自ホスト)を挙げ,そこからの接続はすべて許可しているのだ。このIPアドレスはループバックアドレスと呼ばれるもので,そのホスト自身を示す特有のIPアドレスである。セキュリティ的に問題になることはほぼ皆無といえるだろう。

 2行目では,「192.168.1.0/255.255.255.0」のネットワークからの接続を全面的に許可している。「255.255.255.0」はネットマスクを表しており,「192.168.1.1」から「192.168.1.255」までの連番IPアドレスのマシンからの接続を許可している。「192.168.1.0/255.255.255.0」は,特にプライベートアドレスを表しているため,ここではローカルネットワークであることが分かる。

 また,上記と同じように設定するには,次のように記述する方法もある。

ALL: 192.168.1.

 IPアドレスのネットワーク部だけを記述することで,ネットマスクが8/16/24ビットの場合だけにアクセスを許可する指定となるのだ。

 3行目では,「.trueted.domain.com」からの接続はすべて信用できるものとして「in.ftpd」に限り接続を許可している。「.trusted.domain.com」の最初の「.」は必要だ。これよりまえのサブドメイン部は任意のものという指定になるからだ。

実例2
hosts.deny
in.telnetd: ALL: (/usr/sbin/safe_finger -l @%h | /bin/mail -s "telnet rejected (%h)" root) &
in.fingerd: ALL: (/usr/sbin/safe_finger -l @%h | /bin/mail -s "finger rejected (%h)" root) &
ALL: ALL

hosts.allow
in.ftpd in.telnetd: 192.168.1.0/255.255.255.0 EXCEPT 192.168.1.1
in.ftpd: .dialup.provider.com: (/bin/mail -s "ftp accepted (%h)" root) ipop3d: ALL

 この例では,基本的に外部からのアクセスはすべて拒絶して,POP3はすべてのプロバイダ,ftpは特定のプロバイダからのアクセスのみを許可している。また,プライベートネットワークからのアクセスについては,ftpとtelnetを許可しているのが分かる。

 ここで注目したいのは,外部からのtelnetやfingerを拒絶する場合であっても,接続してきた外部のホストに対してfingerを実行し,その結果をrootにメール通知している点だ。

 外部からのtelnetやfingerを拒絶していることは,ドメイン内に告知している場合アタック行為だと断定できるだろう。このような場合,(その相手のマシンが UNIX であれば)fingerが動作していることもある。接続要求してきたマシンに対し,fingerを実行しておくことでどのようなユーザーがログインしているのかをレポートすることが可能だ。

 ただし,クライアントがWindowsやMacintoshを使っていたり,fingerdが止めていたりすると意味は成さない。特定の大学やプロバイダなどのホストを踏み台にして攻撃を仕掛けてきた場合には有効だろう。同様に,ftpを許可するプロバイダに関しても,rootにメール告知するように設定している。

 tcp wrapperをコンパイルする際,PROCESS_OPTIONSを付けて実行しているのであれば,そのほかのオプション類を使用することが可能だ。たとえば,hosts.denyの中であってもallowルールを記述したりすることもできるようになる。詳細については,マニュアルページのhosts_options(5) を参照してほしい。

icon そのほかのセキュリティ関連ファイル/etc/passwd,/etc/shadow

 ユーザー名とパスワードなどが記入されているpasswdファイルは,一般ユーザーでも読むことができることから内部からのクラックの原因となり得る。暗号化された他人のパスワードフィールドを読むことができれば,それをパスワード解読プログラムにかけることによって,比較的容易にパスワードを破ることができてしまうのだ。

 この対策として,ユーザーが他のユーザーの暗号化パスワードを見られないようにするのが「shadowパスワード」だ。最近のLinuxディストリビューションでは,インストール時に標準で暗号化パスワードになるため,メジャーな形式だといえる。shadowパスワードでは,暗号化されたパスワードフィールドをpasswdファイルと分離して保管するため,一般ユーザーからは見られないようになっている(暗号化されたパスワードフィールドはshadowと呼ばれるファイルに保存される)。

OS別のパスワードファイル
OS passwordファイル shadowファイル
Linux /etc/passwd /etc/shadow
FreeBSD /etc/passwd /etc/master.passwd
Solaris /etc/passwd /etc/shadow

 次は,Linuxのファイル例だ。通常のパスワードファイルの場合,passwd内の第二フィールドに暗号化されたパスワードが格納されている。

% ls -l /etc/passwd /etc/shadow
-rw-r--r-- 1 root  root   1078 Apr 29 05:33 /etc/passwd
-r-------- 1 root  root   929 Apr 29 05:33 /etc/shadow
%

暗号化されていないpasswdファイル例
satoshi:NSlJGwNVtPVVg:501:100:Satoshi Nagayasu:/home/satoshi:/bin/tcsh

shadowパスワードされているpasswdファイル例
satoshi:x:501:100:Satoshi Nagayasu:/home/satoshi:/bin/tcsh

 上記のようにパスワードフィールドが「x」として記述されており,その代わりにshadow ファイル内に次のように記述される。

satoshi:NSlJGwNVtPVVg:11100:0:99999:7:::

 このshadowファイルは管理者以外は読めないため,一般ユーザーがほかのユーザーの暗号化されたパスワードフィールドを読むことができない仕組みだ。なお,このshadow化されたパスワードファイル形式は,OSによって若干の違いがあることも付け加えておこう。

 通常のpasswdファイルとshadowパスワードへの切り替えは,「pwconv」というコマンドを利用する。逆に,shadow パスワードから通常の plain パスワードへの切り替えは「pwunconv」コマンドで可能だ。

OS別のパスワード形式変換コマンド
OS plain->shadow shadow->plain
Linux pwconv pwunconv
FreeBSD なし なし
Solaris pwconv なし
※FreeBSDでは,pwconvに相当するコマンドは用意されていない。これは最初からshadow化されたパスワードシステムが提供されているからだ。

/etc/shells
 UNIXでは,コマンドラインのインターフェイスを提供するプログラムのことを「shell(シェル)」と呼ぶ。このシェルとして利用できる一覧が,/etc/shellsに記述されている。

/bin/bash
/bin/sh
/bin/ash
/bin/bsh
/bin/tcsh
/bin/csh

 ユーザーがシェルログイン(コマンドラインを利用できるログイン)をするには,/etc/passwdで指定されているシェルに,shellsファイルの中に書いてあるいずれかが指定されていなければならない。たとえば,tcshが指定されているpasswdファイルは次のようになっている。

tcshが指定されている/etc/passwd例
satoshi:x:501:100:Satoshi Nagayasu:/home/snaga:/bin/tcsh

 また,passwdの中に記述するシェルを無効なものに指定することで,次のようにシェルログインを禁止することも可能だ。

satoshi:x:501:100:Satoshi Nagayasu:/home/snaga:/dev/null

 上記のように指定されているユーザーは,シェルログインはできないが,ftpログインは可能となる。たとえばホームページ更新だけ必要であれば,このようなftp専用のアカウントを作成すればよいだろう。また応用的な方法として,ftp のみのユーザーであってもパスワードを変更させたいような場合には,shellsに1行を加え,

/bin/bash
/bin/sh
/bin/ash
/bin/bsh
/bin/tcsh
/bin/csh
/usr/bin/passwd  ←この行

passwd ファイルのシェルに /usr/bin/passwd を指定する。このユーザーはシェルは使えないもののパスワードの変更だけはできるように設定されるわけだ。

上記例の/etc/passwd
satoshi:x:501:100:Satoshi Nagayasu:/home/snaga:/usr/bin/passwd


icon rootログイン制限

 ネットワークに接続している場合,ネットワーク経由での rootのログインを制限したい場合がある。ネットワーク経由でのrootのログインを禁止することにより,「誰がログインしたか」を明確に記録しておくことができるのだ。rootのパスワードを知っている人が複数いる場でも,まずは個々のユーザーアカウントでログインしてから「su」コマンドでrootにログインすることで,誰がログインしたかが明示され把握できるわけだ。

 最近のディストリビューションでは,次のようなネットワーク経由のrootログインがあらかじめ禁止設定となっている。このため,確認しておく程度でよいだろう。Linuxの場合,rootログインの制限は,/etc/securettyファイルで行われている。

tty1
tty2
tty3
tty4
tty5
tty6
tty7
tty8

「tty?」という文字列はコンソールモードのログイン(正確にいうと,initレベル3)の場合のログインプロンプトを示している。

 コンソールは「ALT+F1〜ALT+F6」で仮想コンソールを切り変えられるため,rootはこれらのコンソールからのみログインできるようになっていることが分かる。

 現在ログインしているTTY(Tele TYpewriter)を知るには,「tty」コマンドを利用して調べることが可能だ。

リスト
別ウィンドウで見る or 10a.txt

 ネットワーク経由で入る場合などには「/dev/pts/0」のような仮想端末が利用される場合がある。このような場合seturettyには次のように数字のみで記述する。

0
1
2

 FreeBSDの場合には,rootのログイン制限は/etc/ttysファイルで行われている。ttysの書式は次の通りだ。

フィールド 説明
name 仮想端末名 ttyv0
getty gettyプログラム /usr/libexec/getty Pc
type 端末のタイプ cons25, dialup, networkなど
status 状態 on または off。secureをつけるとrootログインを許可

リスト
別ウィンドウで見る or 11a.txt

 FreeBSDの場合,仮想コンソールはttyv0からttyv7に該当する。これらのコンソールは,一般的には安全と思われるためrootログインを許可しているわけだ。

 ほかの仮想コンソールからのrootログインを許可または制限する場合,secureと記述,またはsecureという記述を削除する。

 たとえば,ttyv0からのみのrootログインを許可したい場合,標準でsecureになっている個所を削除するのだ。

リスト
別ウィンドウで見る or 11b.txt

 Solarisでrootログインをコンソールに限定する場合,/etc/default/loginファイルで行う。

リスト
別ウィンドウで見る or 11c.txt

 loginファイルの中で次の行を探してみよう。

#CONSOLE=/dev/console

 この行のコメント「#」を取ることで,rootは/dev/consoleからのみログインできるようになる。

 このようにOS別で若干の差はあるものの,アクセスをコントロールする概念に違いはない。Linuxのインストール後,インターネットにつなぐ前には最低限今回紹介した点を確認するべきである。