アクセスコントロールを知ってサーバ運用の基本を理解しよう
|  |  | 
|  | いちばん近道なLinuxマスター術 | 
| Linuxの用途として,サーバとして動作させるのは機能の見せ所だ。サーバソフトにはApacheやbind,ftpd,squidなど多くのものがあるが,どこのドメイン(IPアドレス)からのアクセスは許可し,拒否設定はどのようにするかは,すべて一括管理されている。第3回目は,アクセスコントロールをテーマとして,インターネットに公開する前に知っておきたい必須の設定項目を解説していこう。 | 
|   | アクセスコントロールを知ってサーバ運用の基本を理解しよう | 
24時間インターネット接続できる環境は,今やケーブルインターネットやフレッツ・ISDNなどで比較的低価格で手に入れることができるようになった。このようなユーザーであれば,回線を十分に使いこなしたいという要望が高いはずだ。そこで候補に上がるのが,サーバソフトを動かしておいて,出先からもアクセスできるようにする用途だ。ほかにもISPのサーバのようにnamedやhttpdなどを動かしてインターネットサーバを実体験することが可能だ。
ここで注意しなければならないのは,ほぼ常時接続という環境ではセキュリティについての配慮だ。
インターネットサーバは,日ごろの管理・監視作業が必要といわれるが,個人で運用する程度であれば導入時の設定さえきちんと行なっておけば,それほど手間をかけないで運用することも可能である。
UNIX 上で利用されるサーバーソフトウェアには,大きく分けて「常に起動しているもの」と「必要に応じて起動されるもの」の2種類がある。一般的には,前者にはsendmailやApache,後者にはftpサーバやPOP3サーバなどが当てはまる。今回は主に,後者の「必要に応じて起動されるサーバソフトウェアのアクセスコントロール」について解説していこう。
 基本はinetdとtcp wrapperにある
					基本はinetdとtcp wrapperにある必要に応じて起動されるサーバは,「inetd」と呼ばれるプログラムが管理を行っている。クライアントとサーバの間は,inetdが中継する役割を持ち,常にメモリを占有せずに必要なときだけ起動するというスタンスなのだ。inetdは,特定のサービス(POP3 や telnet など)への接続を一括して受け付け,そのサービスに対応するサーバプログラムの起動を行う。inetdは,複数のサーバーの起動を担当することから,「internet super server」や「internet super daemon」と呼ばれることもある。
inetdの設定は,/etc/inetd.confと呼ばれるファイルで行う。このファイル内で設定することで,それぞれのサービスへのリクエストに対しどのサーバープログラムを実行するかを設定しているのだ。また,例えば「telnet サービスは危険なので提供しない」などという場合にも,このファイル内で無効にする設定を行う。
 inetd.confの記述
					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の一例だ。
 tcp wrapperは今や標準のアクセスコントロール手段
					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/ | 
 hosts.allow/hosts.denyの記述方法
					hosts.allow/hosts.denyの記述方法hosts.allow/hosts.deny,2つのファイルは,それぞれの目的が「許可するか」,「拒絶するか」といった違いだけだ。記述方法に違いはない。また,多くのファイルと同じく,「#」で始まる行はコメントと判断される。
| 
 | ||||||||||||||||||
| ※サーバプログラムリスト ※クライアントリスト | ||||||||||||||||||
| # 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アドレスなどをシェルコマンドに渡すことが可能なのだ。 | ||||||||||||||||||
| □展開される文字列内容 
 | 
| /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) を参照してほしい。
 そのほかのセキュリティ関連ファイル/etc/passwd,/etc/shadow
					そのほかのセキュリティ関連ファイル/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 % | 
| satoshi:NSlJGwNVtPVVg:501:100:Satoshi Nagayasu:/home/satoshi:/bin/tcsh | 
| 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 | なし | 
/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 | 
 rootログイン制限
					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」コマンドを利用して調べることが可能だ。
ネットワーク経由で入る場合などには「/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ログインを許可 | 
FreeBSDの場合,仮想コンソールはttyv0からttyv7に該当する。これらのコンソールは,一般的には安全と思われるためrootログインを許可しているわけだ。
ほかの仮想コンソールからのrootログインを許可または制限する場合,secureと記述,またはsecureという記述を削除する。
たとえば,ttyv0からのみのrootログインを許可したい場合,標準でsecureになっている個所を削除するのだ。
Solarisでrootログインをコンソールに限定する場合,/etc/default/loginファイルで行う。
loginファイルの中で次の行を探してみよう。
| #CONSOLE=/dev/console | 
この行のコメント「#」を取ることで,rootは/dev/consoleからのみログインできるようになる。
このようにOS別で若干の差はあるものの,アクセスをコントロールする概念に違いはない。Linuxのインストール後,インターネットにつなぐ前には最低限今回紹介した点を確認するべきである。