hosts.denyで制限かけたのに、コネクションが張れてしまう

Linuxなどで、sshdやportmapなどの簡単なアクセス制御をかけるのによく用いられる、hosts_acecss(/etc/hosts.deny, /etc/hosts.allow)。
今回は、hosts.denyにてアクセス制限をかけたのに、コネクションが張れてしまうということについて。

hosts_accessで制限できるサービス

調べてみると、知恵遅れなどのサイトなどを含め多くのサイトでいろいろな記述があります。
その中でもよくまとまっていると思ったのは以下のページ。
Stray Penguin – Linux Memo (NFS)

簡単に言うと、TCP Wrappersがアクセス制限を行っていて、xinetd経由のサービスやlibwrapをサポートするサービスであれば制限可能。
libwrapに対応しているか調べるためには、次のコマンドを使う。

# strings /path/to/binfile | grep hosts

例えば、portmapであれば次のような結果となる。

# which portmap
/sbin/portmap
# strings /sbin/portmap | grep hosts
hosts_access_verbose
hosts_allow_table
hosts_deny_table
/etc/hosts.allow
/etc/hosts.deny

検証

さて、portmapはhosts_accessで制限できることが分かったわけですが、早速検証してみましょう。

検証環境

クライアント(Windowsでもなんでも):ホスト名はclientとします。
サーバ(CentOS 5.8):ホスト名はserver_chanとします。
サーバは当然のごとくiptablesは無効、SELinuxも無効としています(検証に影響出たらいやなので)。

検証開始

※以下、通信制限しますので、サーバにsshで接続してる人は、セッションを切らないようにしましょう。もしくは直接コンソールを使うのが安全です。

portmap

portmapはtcp/111を開けています。
外部からtelnetでここにアクセスしてみましょう。

client$ telnet server_chan 111

繋がりますね。

ではサーバ側で早速制限をかけてみます。
/etc/hosts.denyファイルを編集します。

# 以下を追記して保存
ALL:ALL

これで即時反映されます。
但し少し古い情報ですが、以下のサイトにportmapの場合はportmapを再起動しないと反映しない可能性があるとの記述がありますので、念のため以下のコマンドで再起動しておきましょう。
TCPラッパーの設定ファイル

server_chan# service portmap stop
server_chan# service portmap start

さて外部から再度telnetでアクセスしてみましょう。

client$ telnet server_chan 111

繋がるようです。

サーバ側ではどのように見えているのでしょうか。
watchコマンドを使って1秒ごとにnetstatの結果を見てみましょう。
クライアントから接続されていないときは、

server_chan$ watch --interval=1 netstat -na
..snip..
tcp    0    0 0.0.0.0:111    0.0.0.0:*    LISTEN
..snip..

クライアントからtelnetで接続したときは(hosts.deny記述後)、

..snip..
tcp    0    clientのIPアドレス:111    server_chanのIPアドレス:ランダムなポート番号    ESTABLISHED
..snip..

普通にestablishedしてます。
これって、アクセス制限かかっていないってことでしょうか。
実はちゃんと制限がかかっています。

sshd

同じことをsshdで試してみましょう。
一旦、先ほど追記したhosts.denyのALL:ALLを消します。
そして、sshdが使うtcp/22へ外部から接続してみます。

client$ telnet server_chan 22
SSH-2.0-OpenSSH_4.3

お、何か応答がありましたね。
portmapの時とは違う感じです。

で、再度hosts.denyにALL:ALLを追記して、もう一度telnetをします。

client$ telnet server_chan 22

んん?繋がるけれども応答が無いようです。
これはつまりアクセス制限がかかっているということですね。

結果

hosts.deny制限無し hosts.deny制限有り
portmap コネクション確立
応答を返さない
コネクション確立
応答を返さない
sshd コネクション確立
応答を返す
コネクション確立
応答を返さない

以上からまとめ

  • hosts.denyに書くとサービスには接続できない。
  • hosts.denyに書いてもコネクションは確立する(establishedとなる)。
  • portmapはtelnetで接続しても応答を返さない。
  • sshdはtelnetで接続すると応答を返す。
  • portmapをhosts.denyで制限をかけても、コネクションは確立するので、制限をかける前後で応答が変わらないため、制限がかかったか分からない。
  • sshdをhosts.denyで制限をかけると、コネクションは確立するものの、sshdが返す応答を受け取れなくなるため、制限がかかることが分かる。

結局のところ、コネクションの確立すらさたせくない場合は、iptablesを使いましょう。