tcp-wrappers 7.6 のインストール
〜 DDNS で sshd ログイン (正引きで tcpd) 〜
2003-11-15 作成 福島
2004-08-23 更新 福島

・インストール

$ ncftpget tcp_wrappers_7.6.tar.gz.sig
$ tar xzf tcp_wrappers_7.6.tar.gz
$ cd tcp_wrappers_7.6
tcp_wrappers_7.6$ vi percent_m.c
RedHat9 の場合、/usr/include/bits/sys_errlist.h とぶつかるのでソースを修正 (コメントアウト)
#ifndef SYS_ERRLIST_DEFINED
/*extern char *sys_errlist[];*/
/*extern int sys_nerr;*/
#endif
tcp_wrappers_7.6$ make REAL_DAEMON_DIR=/usr/sbin linux tcp_wrappers_7.6$ su tcp_wrappers_7.6# cp -p tcpd /usr/sbin/. tcp_wrappers_7.6# cp -p try-from /usr/sbin/. tcp_wrappers_7.6# cp -p safe_finger /usr/sbin/. tcp_wrappers_7.6# cp -p tcpdmatch /usr/local/bin/. tcp_wrappers_7.6# cp -p tcpdchk /usr/local/bin/. tcp_wrappers_7.6# cp -p libwrap.a /usr/local/lib/. tcp_wrappers_7.6# cp -p tcpd.h /usr/local/include/.
・DynamicDNS 対応 最近流行ハヤリのダイナミック DNS に対応してみました。 正引きで動作するため、動作が多少遅くなります。※1 $ tar xzf tcp_wrappers_7.6.tar.gz $ cd tcp_wrappers_7.6 tcp_wrappers_7.6$ zcat tcp_wrappers_7.6-dyn.p2.gz | patch tcp_wrappers_7.6$ vi percent_m.c 上記を参照して修正 tcp_wrappers_7.6$ make REAL_DAEMON_DIR=/usr/sbin \ TABLES="-DHOSTS_DENY=\\\"/etc/hosts.deny-dyn\\\" -DHOSTS_ALLOW=\\\"/etc/hosts.allow-dyn\\\"" \ DYNAMIC="-DDYNAMIC" linux tcp_wrappers_7.6$ su tcp_wrappers_7.6# cp -p tcpd /usr/sbin/tcpd-dyn とりあえず別名で動作させます tcp_wrappers_7.6# vi /etc/hosts.allow-dyn
ALL: !host1.example.com      正引きを行うので、ホスト名は FQDN で記述します (直前に '!' を付けます)
※ '!' は独自の書式です。正引きパッチを当てていない tcp_wrappers には存在しません
tcp_wrappers_7.6# vi /etc/hosts.deny-dyn
ALL: ALL
※1 動作が遅くなるのは接続するまでの間だけです。   tcpd は接続された後は自分をフラッシュするのでその後の動作に影響はありません。
・xinetd と tcpd-dyn から sshd を起動する メリット
sshd はスーパーデーモンを介さないで起動 (デーモンモードで起動) したとき、 その内部から libwrap を利用して接続クライアントを限定することができます。 しかし、tcp_wrappers の動作は IP アドレスの逆引きを基本としているため、 クライアントの IP が逆引きに対応していない場合は指定ができません。 DynamicDNS はその性質上、逆引きに対応していません。 (dhcp と DynamicDNS を組み合わせる等の、正規の構成なら逆引き可能ですが、解決法が別にあるので今回は除外します。) そこで、デーモンモードを使用せずに tcpd-dyn から起動すると、固定アドレスを持たないビンボーなクライアントでも、 DynamicDNS に登録してもらえば仲間に入れることができます。 DynamicDNS はセキュリティのしっかりしたところを使いましょう。 登録にも https 等、暗号化してあるところを推奨します。
デメリット
DynamicDNS クライアント (DiCE 等) は多くの場合、IP アドレスの更新は行いますが、期限切れの無効化を行いません。 (他に通信手段を確保しないと無効化できない) このため、自分のホスト (DynamicDNS クライアント) の電源が落ちているときにプロバイダの IP アドレスが変更されても DynamicDNS サーバではそれを検知できないので、第三者にアクセスを許すことになります。 これを防止するために、クライアント側できちんと IP アドレスの無効化 (DynamicDNS サーバにその要求を出す) が必要です。 また、tcpd-dyn を盲信せず、必ず別の認証 (パスワード認証等) を併用する工夫が必要です。 sshd そのものについても若干の問題があります。 sshd は起動するとその内部で保持すべき素数を計算しますが、その計算量が多いため起動に時間がかかります。 デーモンモードで起動した場合は、最初に一度だけその計算を行うので、いざ接続を受け付けたときの計算量は少なくなります。 それに比較して、こうして inetd や xinetd などのスーパーデーモンを介して待ち受ける場合は、接続の度に時間がかかります。 しかし、xinetd を介すことでホスト指定の中に入れるのだから、そのぐらいは我慢してもらいましょう。
仕組み
通常 xinetd から tcpd を通して sshd を呼び出したとき、libwrap がどのように働くかというと
1. xinetd で libwrap が呼ばれる (only_from 等のため) 2. tcpd で libwrap が呼ばれる (/etc/hosts.allow, /etc/hosts.deny を参照するため) 3. sshd で libwrap が呼ばれる (/etc/hosts.allow, /etc/hosts.deny を参照するため)
という具合に 3 回 libwrap が呼ばれ、その度に逆引きが行われます。 これを、
1. xinetd で libwrap が呼ばれる (only_from 等のため) 2. tcpd-dyn で libwrap を呼ばない (/etc/hosts.allow-dyn, /etc/hosts.deny-dyn で正引きにより制限を加える) 3. sshd で libwrap が呼ばれる (/etc/hosts.allow, /etc/hosts.deny を参照するため)
と変更します。※2 このとき、1 と 3 で逆引きが行われても影響がないように、※3  ・xinetd では only_from を使用しない  ・/etc/hosts.allow では該当サービス (sshd のことです) に ALL を指定する とします。 ※2 ちょっと嘘が入っています。   正しくは、「libwrap を呼んでいるけど、その前に正引きでマッチさせる」です。 ※3 1 と 3 でも正引きを対応させたいところですが、それには再コンパイルが   必要 (スタティックリンクされている) なのでこの手段を採っています。
設定
/etc/hosts.allow (通常の tcp_wrapper 用 : sshd から参照されます)
sshd: ALL            sshd で使用される libwrap のために ALL にしておきます
/etc/hosts.deny
ALL: ALL
/etc/hosts.allow-dyn (正引き対応の tcp_wrapper 用 : tcpd-dyn から参照します)
sshd: !host1.example.com
/etc/hosts.deny-dyn
ALL: ALL
/etc/xinetd.d/ssh 644
service ssh
{
    # tcp_wrappers から起動するために NAMEINARGS が必要 ※4
    flags          = REUSE NAMEINARGS
    socket_type    = stream
    wait           = no
    user           = root
    # sshd を tcpd-dyn (正引き) で起動する
    server         = /usr/sbin/tcpd-dyn
    # スーパーデーモンから起動するために -i オプションが必要
    server_args    = /usr/local/sbin/sshd -i -f /usr/local/etc/sshd_config
    log_on_failure += USERID
    disable        = no
}
※4 NAMEINARGS が必要 /etc/hosts.allow, /etc/hosts.deny に記述する名前が引数 (server_args のこと) に含まれるという指定が必要。
tcp_wrappers_7.6# /etc/rc.d/init.d/xinetd restart xinetd の再起動を忘れずに