林と申します。

以下のような条件の FreeBSDマシンに sftp でログインし、lsをすると結果が
返ってくるまで非常に時間がかかります(ファイルの数によりますが、1分以上
はかかります)。私の環境固有の問題なのか、FreeBSD一般の問題なのか確かめ
たいと思ったのですが、似たようなトラブルを経験された、もしくは似たよう
な環境で問題なく動いている方はいらっしゃいますでしょうか?

・NFSサーバ EMC NS700
・LDAP/NISサーバ Sun SunFire240 
        LDAPサーバ Sun Java Directory Server 5.2Patch5
        NISサーバ  PADL ypldapd
        (現在 passwdは1634アカウント、groupは156グループ登録されています)

を利用するクライアントとして、FreeBSD 6.2-RELEASE のマシンを動かしてい
ます。portsで nss_ldap-1.255 および pam_ldap-1.8.2 をインストールして、
/etc/nsswitch.conf では

group: compat
group_compat: ldap
passwd: compat
passwd_compat: ldap

を指定し、

/etc/master.passwd では

+:*::::::::

/etc/group では

+:*:0:

を記述しています。


このFreeBSDマシンに対して、sftpでログインして NFSマウントしているディ
レクトリで lsコマンドを実行すると、結果が返ってくるまで数分かかってし
まいます。WinSCP でプロトコルにsftpを指定してログインしようとした場合
はタイムアウトしてしまいます。同様の設定の FreeBSD 6.2-RELEASEのマシン
が複数台あるのですが、どのマシンでも同じ現象が発生します。

/etc/nsswitch.conf の ldap の指定を nis に変更し、/etc/rc.conf で
nisdomainnameを設定し、nis_client_enable="YES"にしてリブートしても問題
は改善されませんでした。

同じNISサーバ, NFSサーバを利用する Solaris9 および Solaris10 のマシン
に対して sftpでログインして同様の操作を行なった場合はこのような問題は
起きず、すぐに ls の結果が返ってきます。

/etc/master.passwd および /etc/group に (+:*:::::::: などの)NIS/LDAPを
利用する記述がなく、ローカルアカウントのみのFreeBSD 6.2-RELEASEのマシ
ンではこのような問題は発生しませんでした。また、

+foo:*::::::::
+bar:*::::::::

などのようにNIS/LDAPで認証するユーザを限定している場合はそれほど長い時
間はかかりませんでした。

OS付属の /usr/libexec/sftp-server, ports の openssh-portable-4.6.p1,1 
の /usr/local/libexec/sftp-server どちらを利用してもこの問題が発生しま
した。

デバッガで追いかけてみますと、OpenSSH 4.6p1のソースの sftp-common.c の
ls_file関数の中で getpwuid および getgrgid をコールするところで時間が
かかっていることが分かりました。それで、この部分を以下のように、
user_from_uid と group_from_gid を使うように変更したところ、問題のない
早さで lsコマンドの結果が返ってくるようになりました。

*** sftp-common.c.ORG   Sat Aug  5 11:39:40 2006
--- sftp-common.c       Mon Jun 25 17:11:06 2007
***************
*** 194,208 ****
--- 194,220 ----
        char buf[1024], mode[11+1], tbuf[12+1], ubuf[11+1], gbuf[11+1];
  
        strmode(st->st_mode, mode);
+       /*
        if (!remote && (pw = getpwuid(st->st_uid)) != NULL) {
                user = pw->pw_name;
        } else {
                snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid);
                user = ubuf;
        }
+       */
+       if (remote || (user = user_from_uid(st->st_uid, 0)) == NULL) {
+               snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid);
+               user = ubuf;
+       }
+       /*
        if (!remote && (gr = getgrgid(st->st_gid)) != NULL) {
                group = gr->gr_name;
        } else {
+               snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid);
+               group = gbuf;
+       }
+       */
+       if (remote || (group = group_from_gid(st->st_gid, 0)) == NULL) {
                snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid);
                group = gbuf;
        }


それで、

・FreeBSDの getpwuid および getgrgid はこういうものだから、
  user_from_uid および group_from_gid を使うのが正しい
  →OpenSSHで対応すべき or FreeBSDの問題?

・FreeBSDの getpwuid および getgrgid でもそんなに時間がかかるわけはな
  いので、私のなんらかの設定がおかしい

のいずれかだと思うのですが、似たような構成でお使いの方でこのような現象
を経験された方はおられますでしょうか?

- 
  林 周志(はやし ひろし)

メールによる返信