HYLOGICS

今後は各分室にコンテンツを移して、ここは雑記や暮らしを中心としたライフログ的な何かにしていく予定です。

CentOSでsftpサーバを構築する

久々に備忘録。

経緯

  • 知人にファイルの伝送をすることになったが用意されたのがftp
  • 躊躇しつつアップロードするがchecksum失敗、リトライしても失敗
  • よし、代わりの環境を用意しよう

どうするのか

  • 一時的にVPSを借りる
  • 現環境に相乗りする

手間とお金のかからないSFTPにしよう*1

環境

$ cat /etc/redhat-release; uname -r
CentOS release 6.7 (Final)
2.6.32-573.7.1.el6.x86_64

手順

sftp用にsshdの導入

管理用のsshdとはPortを別にするため追加でコンパイルしています。既存のsshdに相乗りする場合は本項は飛ばして設定から。

cd /usr/local/src/
wget http://ftp.jaist.ac.jp/pub/OpenBSD/OpenSSH/portable/openssh-7.1p1.tar.gz
tar -xzf ./openssh-7.1p1.tar.gz
cd ./openssh-7.1p1

コンパイルオプションを確認

./configure --help

Makefileの生成。今回はインストール先だけ変更します。

./configure --prefix=/usr/local/openssh-7.1p1

ファイルが足りないと怒られたので必要なパッケージを導入してリトライ

yum install openssh-devel
yum install libssh2-devel
./configure --prefix=/usr/local/openssh-7.1p1

インストール

make && make install

sshdの設定変更

cd /usr/local/openssh-7.1p1
vi etc/sshd_config

変更点は以下の通り

diff etc/sshd_config*
13c13
< Port 11121
---
> #Port 22
19c19
< Protocol 2
---
> #Protocol 2
44c44
< PermitRootLogin no
---
> #PermitRootLogin prohibit-password
126,133c126
< #Subsystem    sftp    /usr/local/openssh-7.1p1/libexec/sftp-server
< Subsystem       sftp    internal-sftp
<
< Match User sftp
<  ChrootDirectory /sftp
<  X11Forwarding no
<  AllowTcpForwarding no
<  ForceCommand internal-sftp
---
> Subsystem     sftp    /usr/local/openssh-7.1p1/libexec/sftp-server

今回は特定ユーザのみなのでMatch Userとしているが複数ユーザがいる場合はUserではなくGroupでMatchさせるとよい

sshdの起動

一時的なものなので手で起動させてます。initスクリプトを書く際は既存のものを参考にどうぞ。また、既存のsshdに相乗りした場合は当然ですがserviceもしくは systemctlで。

/usr/local/openssh-7.1p1/sbin/sshd -f /usr/local/openssh-7.1p1/etc/sshd_config

sftp用ユーザの作成

useradd sftp -d /
passwd sftp

chroot用にHOME_DIRは'/'としておく

chroot用のディレクトリ作成

mkdir /sftp
ls -ld /sftp

所有権がroot.root、パーミッションが755であること

外部から接続確認*2

SSH

$ ssh sftpserver -l sftp
sakura@sftpserver's password:
This service allows sftp connections only.
Connection to sftpserver closed.

sftp接続のみ許可しているので接続出来ない(正常)

SFTP

from OSX

sftp -P 11121 sftp@sftpserver

from Linux

sftp -oPort=11121 sftp@sftpserver
Connecting to sftpserver...
sftp@sftpserver's password:
sftp> ls
test.img
test.md5

ファイルが見れればOK

ハマりどころ

作業時間は確認含めて小1時間程度だったけど意外なところでつまづきポイントががが

chrootに失敗するため接続できない

ディレクトリの所有者が一般ユーザだったり、root以外に書き込み権限が付与されてたりすると失敗する。

ここで注意しないといけないのは、ChrootDirectory で指定するディレクトリは root ユーザーだけが書き込みできる状態でなければなりません。所有者が一般ユーザーだったり、権限が 777 だと /var/log/secure に以下のようなエラーが吐かれます。

sshd[17779]: fatal: bad ownership or modes for chroot directory "/var/www"

CentOS の OpenSSH で chroot を設定する

そういえばchroot(1)ってroot onlyだった気がするなあ。

接続には成功するがファイルの一覧が取得できない

chroot先のディレクトリのパーミッションを705か755にすること。

700ではCouldn't get handle: Permission deniedとエラーが出るのに704(o+r)では何もエラーが出ない(そしてファイルの一覧も出ない)のでちょっと悩みました。

上記二項を鑑みての振り返り

共有ユーザが複数おり、同じディレクトリを共有する場合はグループで管理する(sftpusersなど)ことが必須。 この場合ディレクトリの所有者と権限は root.sftpusers 750( or 755 ) とする。

同じディレクトリを共有する要件がない場合は自由だが同じディレクトリを共有するケースに合わせておいた方があとあと運用が変更になっても設計を変更しなくて良い。これ大事。

sshdの設定もMatch Groupで括った上で個別に必要な要件があればMatch Userで設定する……という形が良いと思われる。が、その場合正しく設定が反映されるのかは確認してないので検証が必要かも。

参考

qiita.com

*1:結果から言うとFTPSのほうが簡単だった気も

*2:本筋とは逸れるので触れませんが、ポートマッピングやFWの設定は既に終わっているものとします。