トップ 履歴 一覧 カテゴリ ソース 検索 ヘルプ RSS ログイン

OpenSSH/Chrooted

INDEX

Chrooted OpenSSH

ssh (scp, sftp) アクセスを許可したユーザにホームディレクトリ以外のディレクトリを参照させないようにする、いわゆる chroot 機能を持たせた sshd の構築メモ。暗号化されないとかはないと思うけど、うまく行かないところはあるかも。

OpenBSD 以外の他プラットフォームへのリリース(-p リリース)用のパッチは存在しますが、OpenBSD 用の OpenSSH には、既に組み込まれていたり、追加するためのパッチがありません。ので、-p リリース用のパッチを参考に組み込みます。

ルートを変更(chroot)するユーザは、/etc/passwd ファイルのホームディレクトリの記述を /home/chrooted から /home/chrooted/./ のように変更します。ようは、chroot でルートとする箇所に /./ を挟んで指定する。/./ がないユーザは、通常の sshd と動作は変らない。

sshd with chroot の作成

ssh 関係のソースは、/usr/src/usr.bin/ssh/ 配下にあります。それらのソースファイルに下記のパッチを当てて、sshd を make します。

# cd /usr/src/usr.bin/ssh/
# patch -p0 < chrooted.patch
# cd sshd
# make
# make install

 Chroot patch for OpenSSH 4.3

OpenBSD 3.9 に付いている、OpenSSH_4.3, OpenSSL 0.9.7g を修正した内容(差分)です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
--- session.c.org Tue Feb 28 10:10:21 2006
+++ session.c Wed Nov 29 23:25:44 2006
@@ -67,6 +67,8 @@ #include "kex.h" #include "monitor_wrap.h"
+#define CHROOT +
#ifdef KRB5 #include <kafs.h> #endif @@ -996,7 +998,32 @@ void do_setusercontext(struct passwd *pw) {
+#ifdef CHROOT + char *user_dir; + char *new_root; +#endif /* CHROOT */ +
if (getuid() == 0 || geteuid() == 0) {
+#ifdef CHROOT + user_dir = xstrdup(pw->pw_dir); + new_root = user_dir + 1; + + while((new_root = strchr(new_root, '.')) != NULL) { + new_root--; + if(strncmp(new_root, "/./", 3) == 0) { + *new_root = '\0'; + new_root += 2; + + if(chroot(user_dir) != 0 || chdir("/") != 0) + fatal("Couldn't chroot to user's directory %s", user_dir); + pw->pw_dir = new_root; + break; + } + + new_root += 2; + } +#endif /* CHROOT */ +
#ifdef HAVE_LOGIN_CAP if (setusercontext(lc, pw, pw->pw_uid, (LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) {

chroot 環境の構築

chroot させるユーザの環境構築手順です。スーパーユーザ(root)で作業します。

手始めに、ユーザとグループ名、現在のホームディレクトリをシェル変数にセットする。作業場所は、そのユーザのホームディレクトリ。$1は、対象ユーザ名に変更のこと。

#!/bin/sh
# set chroot user name
USERNAME=$1
GROUPNAME=`id -gn $USERNAME`
HOMEDIR=`grep /etc/passwd -e "^$USERNAME" | cut -d':' -f 6`
cd $HOMEDIR

※一行目が '#!/bin/sh' の整形済テキストは、sh のコマンド。

 ホームディレクトリの設定

chrootするユーザであることを示すためにホームディレクトリの記述を変更します。

#!/bin/sh
# change home directory
usermod -d $HOMEDIR/./ $USERNAME

 必要なディレクトリの作成

chrootした際に必要なファイルを置くディレクトリを作成する。ユーザが触ることはないので、オーナは root にする。

#!/bin/sh
# Create Directories
DIRS="./bin ./dev ./etc ./usr ./usr/lib ./usr/libexec"
mkdir -m 755 -p $DIRS
chown -R root:wheel $DIRS

 デバイスファイルを作成する

null デバイスファイルが必要なので作ります。

#!/bin/sh
# Make device file
cd dev
cp -p /dev/MAKEDEV ./
./MAKEDEV std
cd ..

 パスワードファイルとグループファイルの作成

必要最低限に絞ったパスワードファイルとグループファイルを作成します。また、時間表示をあわせる為、タイムゾーンのファイルもコピーします。

#!/bin/sh
# Make /etc/passwd and /etc/group
grep /etc/passwd -e "^root" -e "^$USERNAME" > ./etc/passwd
grep /etc/group -e "^wheel" -e "kmem" -e "^bin" -e "^$GROUPNAME" > ./etc/group
chmod 644 ./etc/passwd ./etc/group
chown root:wheel ./etc/passwd ./etc/group
cp -p /etc/pwd.db ./etc/pwd.db
cp -p /etc/localtime ./etc/localtime

※パスワードファイルは、以下のようにする方が正しい?(未確認)

grep /etc/master.passwd -e "^root" -e "^$USERNAME" > ./etc/master.passwd
pwd_mkdb -d ./etc ./etc/master.passwd
if [ ! -f ./etc/group ] ; then
  grep /etc/group -e "^wheel" -e "kmem" -e "^bin" > ./etc/group
fi
grep /etc/group -e "^$GROUPNAME" >> ./etc/group

if [ ! -f ./etc/master.passwd ] ; then
  grep /etc/master.passwd -e "^root" > ./etc/master.passwd
fi
grep /etc/master.passwd -e "^$USERNAME" >> ./etc/master.passwd
pwd_mkdb -d ./etc ./etc/master.passwd

 コマンドファイルと関係ライブラリをコピーする

必要なコマンドファイルとダイナミックリンクされているライブラリをコピーします。/bin/groups は、スクリプトで id を呼び出しているのでパスをあわせて作り直します。

#!/bin/sh
# copy command list
CMDS="sh ksh csh chmod chown chgrp id ls pwd cp scp mv rm mkdir rmdir vi cat"
# Copy command and library
for prog in `which $CMDS`; do
  cp -p $prog ./bin
  # obtain a list of related libraries
  ldd $prog > /dev/null 2> /dev/null
  if [ "$?" = 0 ] ; then
    LIBS=`ldd $prog | grep rlib | awk '{ print $7 }'`
    for lib in $LIBS; do
      cp -p $lib ./usr/lib
    done
  fi
done

# Copy command and library Part2
cp -p /usr/libexec/ld.so ./usr/libexec/ld.so
cp -p /usr/libexec/sftp-server ./usr/libexec/sftp-server
LIBS=`ldd /usr/libexec/sftp-server | grep rlib | awk '{ print $7 }'`
for lib in $LIBS; do
  cp -p $lib ./usr/lib
done

# Make groups command
echo '#!/bin/sh -'> ./bin/groups
echo 'exec /bin/id -Gn $*'>> ./bin/groups
chown root:bin ./bin/groups
chmod 555 ./bin/groups

備考等

 参考

 ひとりごと

公式にサポートしないですかね。OpenBSD の ftpd の chroot機能が、/etc/ftpchroot に列挙してなので、sshd もならって、/etc/sshchroot とかで出来れば便利かな。※ OpenSSH 4.9 (2008/03/30) から公式に chroot 機能が追加された。

やってみてわかったけど、"/./" をホームディレクトリに入れると、普通にコンソールで入った場合に、ホームディレクトリにいてもホームディレクトリにいると見てくれない('~' の表示にならない)。実害はないけど変な感じ。

最終更新時間:2008年12月24日 01時29分00秒 指摘や意見などあればSandBoxのBBSへ。