2015年7月20日月曜日

FreeBSD 10.1にscponlyをインストールする

他の組織からファイルを転送してもらう必要がでてきました。そのために、DMZにFreeBSD 10.1のサーバーを設置し、このサーバーにscponlyをインストールしました。scponlyを使えば、sshでのシェル操作は許さず、scpでのファイル転送だけを有効にすることができます。さらに、sshdでパスワードでのログインを無効・公開鍵でのログインを有効にすることで、安全性を高めることできます。

scponlyは以下のようにインストール、設定しました。
# sudo -s
Password: ******
# cd /usr/ports/shells/scponly
# make config
....
[x] CHROOT chroot(8) functionality
[ ] DEFAULT_CHDIR Chdir(2) by default
[x] DOCS Build and/or install documentation
[ ] GFTP gftp support
[ ] RSYNC rsync support
[x] SCP vanilla scp support
[ ] SVN Subversion support
[ ] SVNSERVE Suversion support for svn+ssh://
[ ] UNISON Unisson support
[x] WILDCARDS Wildcards processing
[x] WINSCP WinSCP support
# make install
...
To setup chroot cage, run the following commands:
1) cd /usr/local/share/examples/scponly/ && /bin/sh setup_chroot.sh
2) Set scponlyc_enable="YES" in /etc/rc.conf
3) Run /usr/local/etc/rc.d/scponly start
#
scponlyはCHROOT、SCP、WILDCARDS、WINSCPを有効にしました。WILDCARDSは微妙ですが、CHROOTオプションを有効にすることで、scponlyのホームディレクトリ以下にしかアクセスできないようにできるので、利便性と安全性が両立できると判断しました。

このあと、インストール時に表示された支持に従い、chroot.shを実行し、rc.confに記述を追加、scponlyスクリプトを実行しました。chroot.shで表示された選択肢にはすべてデフォルトを選びました(ただ、私の場合、scponly用のホームディレクトリ以下にうまくdevディレクトリが作成できなかったので、~scpoly/devを一度削除してから、chroot.shを再実行する必要がありました)。

そして、以下のようにscponlyを試してみます(公開鍵でのログインのみを有効にしています)。
$ scp ./FILE scponly@IPアドレス:incoming/
Enter passphrase for key '/home/ss/.ssh/id_rsa':
lost connection
$
lost connectionとなり、うまくファイルを転送することができません(scponlyではscponlyのホームディレクトリにあるincomingディレクトリにのみファイルを転送することができます)。

そこで、 /usr/local/etc/scponly/debeglevel の内容を「3」にしてデバッグ出力を有効にしてみます。
$ cat /usr/local/etc/scponly/debuglevel
3
$
ふたたびファイル転送を試みます。
$ scp ./FILE scponly@IPアドレス:incoming/
Enter passphrase for key '/home/ユーザー/.ssh/id_rsa':
scponly[6354]: chrooted binary in place, will chroot()
scponly[6354]: 3 arguments in total.
scponly[6354]: arg 0 is scponlyc
scponly[6354]: arg 1 is -c
scponly[6354]: arg 2 is scp -t incoming/
scponly[6354]: opened log at LOG_AUTHPRIV, opts 0x00000029
scponly[6354]: determined USER is "scponly" from environment
scponly[6354]: retrieved home directory of "/home/scponly" for user "scponly"
scponly[6354]: chrooting to dir: "/home/scponly"
scponly[6354]: chdiring to dir: "/"
scponly[6354]: setting uid to 2003
scponly[6354]: processing request: "scp -t incoming/"
scponly[6354]: Using getopt processing for cmd /usr/bin/scp
(username: scponly(2003), IP/port: IPアドレス 64023 22)
scponly[6354]: getopt processing returned 't' (username: scponly(2003), IP/port: IPアドレス 64023 22)
scponly[6354]: running: /usr/bin/scp -t incoming/ (username: scponly(2003), IP/port: IPアドレス 64023 22)
scponly[6354]: about to exec "/usr/bin/scp" (username: scponly(2003), IP/port: IPアドレス 64023 22)
scponly[6354]: failed: /usr/bin/scp -t incoming/ with error Too many levels of symbolic links(62) (username: scponly(2003), IP/port: IPアドレス 64023 22)
lost connection
$
転送先のホストで/usr/bin/scpコマンドを実行しようとしていますが、scpのあるディレクトリがシンボリックリンクの先にあるためにscpコマンドが実行できないようです。

実は、この前にscponlyコマンドがないというエラーが出ていたので、
# cd ~scponly
# cd usr
# mv bin bin.ORG
# ln -s /usr/bin .
#
のようにして~scponly/usr/binから/usr/binへのシンボリックリンクを設定したのですが、これではうまくいかないようです。

そこでこのシンボリックリンクは削除し、scpコマンドをコピーしてみることにしました。
# cd ~scpoly/usr
# rm bin
# mkdir ~scponly/usr/bin
# cp /usr/bin/scp .
#
ファイル転送を試してみます。
$ scp ./FILE scponly@IPアドレス:incoming/
Enter passphrase for key '/home/ユーザー/.ssh/id_rsa':
scponly[6368]: chrooted binary in place, will chroot()
scponly[6368]: 3 arguments in total.
scponly[6368]: arg 0 is scponlyc
scponly[6368]: arg 1 is -c
scponly[6368]: arg 2 is scp -t incoming/
scponly[6368]: opened log at LOG_AUTHPRIV, opts 0x00000029
scponly[6368]: determined USER is "scponly" from environment
scponly[6368]: retrieved home directory of "/home/scponly" for user "scponly"
scponly[6368]: chrooting to dir: "/home/scponly"
scponly[6368]: chdiring to dir: "/"
scponly[6368]: setting uid to 2003
scponly[6368]: processing request: "scp -t incoming/"
scponly[6368]: Using getopt processing for cmd /usr/bin/scp
(username: scponly(2003), IP/port: IPアドレス 24123 22)
scponly[6368]: getopt processing returned 't' (username: scponly(2003), IP/port: IPアドレス 24123 22)
scponly[6368]: running: /usr/bin/scp -t incoming/ (username: scponly(2003), IP/port: IPアドレス 24123 22)
scponly[6368]: about to exec "/usr/bin/scp" (username: scponly(2003), IP/port: IPアドレス 24123 22)
FILE 100% 260KB 260.2KB/s 00:00
$
こんどはうまくファイルを転送することができました。