0
1

WinSCPからSFTP、SCP接続する際にchrootで接続ディレクトリを制限する。

Posted at

はじめに

WinSCPSFTPSCPでサーバに接続してファイル転送等を行う際に便利なWindowsアプリケーションですが、OpenSSHchrootの機能で接続できるディレクトリを制限したいと思いやってみたところ、中々苦戦したため記事に残しておこうと思います。

chrootとは

ルートディレクトリを変更する機能となり、chrootの機能を使用することで、指定のディレクトリ配下をルートディレクトリとして動作させることができるので、今回のように特定のディレクトリ配下しか見せないということができます。

以下のようにuser1は特に制限せず、user2user3chrootで制限されていた場合、制限がないuser1は全て閲覧可能ですが、user2user3/chroot/userXより上位には移動できないため、user2からuser3user3からuser2のファイル・ディレクトリを閲覧することはできません。

chrootの例
/
├── home
│   └── user1    ← user1は全ての場所を閲覧可能
│       └── dir1
│           └── dir2
└── chroot
    ├── user2    ← /chroot/user2をchrootでルートとした場合、user2はdir3とdir4のみ閲覧可能
    │   └── dir3
    │       └── dir4
    └── user3    ← /chroot/user3をchrootでルートとした場合、user3はdir5とdir6のみ閲覧可能
        └── dir5
            └── dir6

但し、指定のディレクトリ配下をルートディレクトリとして動作させると、当然、その配下には/bin/etc等、サーバの動作に必要となるディレクトリは存在しないことから、サーバへのリモート接続時の制限として設定する場合、動作に必要となるコマンドやライブラリをchrootで制限しているディレクトリ配下に配置する必要が出てくる場合があります。

ちなみに、chrootはUnixでは昔からある機能となり、最近よく使われているDocker等のコンテナ技術はchrootがベースとなっている技術となります。

サーバ構成

今回は以下の構成のサーバで設定を行おうと思います。

OSにより若干手順が異なるかもしれませんが、OpenSSHを使用しているサーバならUbuntuや他のLinuxでも同様の手順でできるかと思います。

項目 内容
OS Red Hat Enterprise Linux 8.9
OpenSSHサーババージョン 8.0p1-19.el8_9.2

SFTP、SCP接続する際のパターン別chroot設定

SFTPSCPどちらもSSHプロトコルを使用してファイル転送する機能となりますが、chrootで制限を行う場合、SFTPSCP両方接続できるようにするのは大変なので、できればSFTPのみでファイル転送できるようにすることをおすすめします。

今回SFTPSCPそれぞれchrootで制限する方法は紹介しますが、よほどの理由がなければSFTPのみで接続できるような運用としたほうがよいと思います。

事前設定

事前にchrootでルートディレクトリ先となるディレクトリの作成と、接続確認用のユーザ、また、共通で必要となるディレクトリを先に作成しておきます。

今回はSFTPSCPでそれぞれユーザを分けたいと思うので、ユーザとchrootで制限するディレクトリは以下のようにしたいと思います。

ユーザ名 chrootディレクトリ
sftpuser /chroot/sftpuser
scpuser /chroot/scpuser
chroot用ディレクトリ作成
sudo mkdir -p /chroot/sftpuser
sudo mkdir -p /chroot/scpuser

なお、今回作成するユーザはSFTPSCP接続専用ユーザとして、接続時にchrootでルートディレクトリを変更するため、ユーザ作成時、不要なホームディレクトリは作成しないようにしますが、ホームディレクトリのパスは通常通りのパス指定で行ってください。

ユーザの作成(ホームディレクトリ指定のみ)
sudo useradd -d /home/sftpuser -M sftpuser
sudo useradd -d /home/scpuser -M scpuser

今回は説明簡略化のため、パスワード認証にしたいと思いますので、パスワードも設定しておきますが、実際の運用時はSSH鍵ファイルでの接続を検討しましょう。

パスワードの設定
sudo passwd sftpuser
sudo passwd scpuser

chroot制限のSFTP、SCPを行った際のルートディレクトリについて

chrootで制限するルートディレクトリはrootの権限である必要があるため、デフォルトでは755のパーミッションでディレクトリ作成されることから、ルートディレクトリ直下にはファイル等作成することができません。

そのため、ファイル転送用のディレクトリ(今回はdata)を作成してそれぞれのユーザ権限にしておきます。

ファイル転送用ディレクトリ作成と権限変更
sudo mkdir -p /chroot/sftpuser/data
sudo mkdir -p /chroot/scpuser/data
sudo chown sftpuser:sftpuser /chroot/sftpuser/data
sudo chown scpuser:scpuser /chroot/scpuser/data

もしルートディレクトリ直下にファイルを格納したい場合はchrootで制限するディレクトリのパーミッションを777等に変更してください。

SFTP接続する際のchroot設定

以下より実際にSFTP接続時のchroot設定を行っていきます。

SFTPでのchroot制限を行うため、/etc/ssh/sshd_configvi等で開き、以下のように設定します。

/etc/ssh/sshd_config
# /usr/libexec/openssh/sftp-serverをコメントアウト
#Subsystem	sftp	/usr/libexec/openssh/sftp-server
# internal-sftpを追記
Subsystem	sftp	internal-sftp

# ファイル末尾にsftpuser用のchroot設定を追加
Match User sftpuser
 ChrootDirectory /chroot/sftpuser

OpenSSHサーバ(sshdサービス)を使用している場合、chrootで制限したSFTP接続を行うためにはサブシステム設定でinternal-sftpを使用する必要があるため、デフォルトで設定されているsftp-serverをコメントアウトしたうえで、ChrootDirectoryでルートディレクトリとするディレクトリを指定します。

設定後、sshdサービスを再起動しておきます。

sshdサービスの再起動
sudo systemctl restart sshd

WinSCPによるSFTP接続確認

chroot制限を行っているとはいえ、接続方法は変わらないので、WinSCPで通常の接続と同様SFTP接続を行います。

Monosnap_20240728_172957.png

接続すると以下のようにルートディレクトリ直下に先ほど作成したファイル転送用のdataディレクトリしか存在しないことが確認できるかと思います。

Monosnap_20240728_173450.png

なお、SFTPではなくSCPで接続した場合は以下のようなエラーメッセージが表示されます。

SCP接続した場合のエラーメッセージ
開始時のメッセージ省略のエラー。選択したシェルは WinSCP 互換ではないかもしれません。 (bash をお勧めします)

これだとどのようなエラーなのかよくわかりませんが、PowerShell等で、SSHコマンドで接続してみると以下のように表示され、SFTP以外では接続できないことがわかります。

internal-sftp設定したユーザにSSH接続した場合
This service allows sftp connections only.
Connection to hostname closed.

chroot設定を行わずに、デフォルトのsshdの設定(sftp-server)で接続する場合はSFTPでもSCPでも接続できますが、internal-sftpchroot制限を行うとSFTP接続しかできなくなるので、ご注意ください。

SCP接続する際のchroot設定

SCPchrootの制限を行う場合はSFTPのように簡単にはいかず、SCP接続時に必要となるコマンドファイルやライブラリ等をchrootで指定したルートディレクトリ配下に配置して、機能制限されたミニOSを作成するような作業を行う必要があります。

/etc/ssh/sshd_configの設定としてはファイル末尾にscpuser用のchroot設定を行うのみとなるため、以下のように設定してsshdサービスを再起動しておきます。

/etc/ssh/sshd_config
# デフォルトのまま
Subsystem	sftp	/usr/libexec/openssh/sftp-server

# ファイル末尾にscpuser用のchroot設定を追加
Match User scpuser
 ChrootDirectory /chroot/scpuser
sshdサービスの再起動
sudo systemctl restart sshd

必要ファイルのコピー

SCP接続した際に裏で行われている操作を行えるようにするため、必要なファイルをchrootで指定するルートディレクトリ配下に配置します。

以下の例を見るとイメージできるかと思いますが、scpuser/chroot/scpuser配下がルートディレクトリとなるため、本物のディレクトリ・ファイル構造と同じように、配下に必要となるディレクトリやファイルを配置していきます。

/chroot/scpuser配下に作成するディレクトリ例
/
├── bin
├── dev
├── etc
├── ()
│
└── chroot
    └── scpuser
        ├── bin   ←シンボリックリンクで設定
        ├── dev   ←/devをbindでマウント
        ├── data  ←ファイル転送用ディレクトリ
        ├── etc   ←scpuserのみ記載されたpasswdファイルを配置
        ├── lib      ←シンボリックリンクで設定
        ├── lib64  ←シンボリックリンクで設定
        └── usr
            ├── bin    ←必要なコマンドファイルのみコピー
            ├── lib      ←/usr/libをbindでマウント
            └── lib64  ←/usr/lib64をbindでマウント

まずは、必要なディレクトリをmkdirコマンドで作成します。

必要ディレクトリの作成
sudo mkdir -p /chroot/scpuser/dev
sudo mkdir -p /chroot/scpuser/data
sudo mkdir -p /chroot/scpuser/etc
sudo mkdir -p /chroot/scpuser/usr
sudo mkdir -p /chroot/scpuser/usr/bin
sudo mkdir -p /chroot/scpuser/usr/lib
sudo mkdir -p /chroot/scpuser/usr/lib64

binliblib64は通常の構成でもシンボリックリンクで/usr/xxxにリンクされているため、同じように/chroot/scpuser/usr/xxxにシンボリックリンクでリンクしておきます。

シンボリックリンクの作成
sudo ln -s usr/bin /chroot/scpuser/bin
sudo ln -s usr/lib /chroot/scpuser/lib
sudo ln -s usr/lib64 /chroot/scpuser/lib64

また、devusr/libusr/lib64mountコマンドのbindオプションで同サーバ上の本物のディレクトリをマウントしてしまいます。

必要ディレクトリのマウント
sudo mount --bind /dev /chroot/scpuser/dev
sudo mount --bind /usr/lib /chroot/scpuser/usr/lib
sudo mount --bind /usr/lib64 /chroot/scpuser/usr/lib64

マウントした領域は再起動するとマウントが外れてしまうため、以下の情報を/etc/fstabにも記載しておきます。

/etc/fstabに設定する内容
/dev        /chroot/scpuser/dev                 none    bind            0 0
/usr/lib    /chroot/scpuser/usr/lib             none    bind            0 0
/usr/lib64  /chroot/scpuser/usr/lib64           none    bind            0 0

binに含まれるコマンドも、bindオプションでマウントしてしまっても良いですが、必要なコマンドのみに絞るほうがセキュリティ的には望ましいため、今回はWinSCPで接続した際に使うコマンドのみ/chroot/scpuser/usr/binにコピーしておきます。

WinSCP接続する際に必要となる基本コマンドのコピー
sudo cp -a /usr/bin/bash /chroot/scpuser/usr/bin/
sudo cp -a /usr/bin/chgrp /chroot/scpuser/usr/bin/
sudo cp -a /usr/bin/chmod /chroot/scpuser/usr/bin/
sudo cp -a /usr/bin/chown /chroot/scpuser/usr/bin/
sudo cp -a /usr/bin/cp /chroot/scpuser/usr/bin/
sudo cp -a /usr/bin/ln /chroot/scpuser/usr/bin/
sudo cp -a /usr/bin/ls /chroot/scpuser/usr/bin/
sudo cp -a /usr/bin/mkdir /chroot/scpuser/usr/bin/
sudo cp -a /usr/bin/mv /chroot/scpuser/usr/bin/
sudo cp -a /usr/bin/rm /chroot/scpuser/usr/bin/
sudo cp -a /usr/bin/scp /chroot/scpuser/usr/bin/

/etc/passwdの設定のうち、scpuserの分のみ必要となるため、以下でscpuserのみ抜き出したものを出力します。

scpuser部分のみの/etc/passwd出力
sudo grep scpuser /etc/passwd > /chroot/scpuser/etc/passwd

WinSCPによるSCP接続確認

設定できたのでWinSCPでSCP接続を行います。

SCPの場合、先ほど配置したファイル、ディレクトリが必要となることから、SFTPの場合とは異なり、以下のように/chroot/scpuser配下の各種ファイル・ディレクトリも表示されています。

Monosnap_20240728_172735.png

また、今回はWinSCPで使用する基本的なコマンド(赤枠)は実行できるようにコマンド実行用のファイルを配置していますが、カスタムコマンド(青枠)まで実行できるようにはしていないため、もしカスタムコマンドも使いたいという場合はusr/bin等の配下に必要なファイルを配置してください。

Monosnap_20240728_175307.png

なお、SCPではなくSFTPで接続した場合は以下のようなエラーメッセージが表示されます。

SFTP接続した場合のエラーメッセージ
SFTP プロトコルを初期化できません。SFTP サーバが起動していますか?

SFTP接続をした場合、ChrootDirectoryの設定は有効のため、ChrootDirectoryに従ってルートディレクトリが設定されますが、internal-sftpではなく、sftp-serverでの動作となるため、接続するために必要なファイルが足りず、接続できないことが原因となります。

こちらについては「同じユーザでSFTP、SCP接続する際のchroot設定」で対処方法を説明していきます。

SFTPユーザとSCPユーザを共存する際のchroot設定

ここまでのSFTPSCPの設定では、chroot制限のSFTPを有効にした場合はinternal-sftpサブシステムが全体にかかるため、chroot制限のSCPは使用できず、chroot制限のSCPを有効にした場合はchroot制限のSFTPを使用できませんでした。

internal-sftpForceCommandの設定で特定のユーザ接続でのみ使用するように設定することができるため、デフォルトのサブシステムはsftp-serverのまま、sftpuserのみinternal-sftpを使用することで、chroot制限のSFTPSCPそれぞれ使用することができるようになります。

/etc/ssh/sshd_config
# sftp-server設定はデフォルトのまま
Subsystem	sftp	/usr/libexec/openssh/sftp-server

# ForceCommand設定でsftpuserのみinternal-sftpを有効化する
Match User sftpuser
 ChrootDirectory /chroot/sftpuser
 ForceCommand internal-sftp
# scpuser用のchroot設定を追加
Match User scpuser
 ChrootDirectory /chroot/scpuser

設定後、sshdサービスを再起動しておきます。

sshdサービスの再起動
sudo systemctl restart sshd

この設定を行うことで、sftpuserSFTP接続した場合はSFTPchroot制限が行われ、scpuserSCP接続した場合はSCPchroot制限が行われるようになります。

同じユーザでSFTP、SCP接続する際のchroot設定

chroot制限のSCP設定を行った際には、同じユーザでSFTP接続することはできませんでしたが、そもそもchroot設定を行わない場合はどちらも同じ使用感で使用できるため、chroot設定を行ったから使用できないわけではなくchroot設定を行ったことで、SFTP接続するのに必要となるファイル・ディレクトリが参照できずに接続できなかったことが原因となります。

そのため、chrootのルートディレクトリに、SFTP接続に必要となるファイルも配置することで対処します。

ベースとしてはSCP接続する際の設定となるため、SCP接続する際の設定が行われている前提で進めます。

scpuserSFTPSCP接続するよう設定するため、/etc/ssh/sshd_configSCPのときと同様以下のように設定します。

/etc/ssh/sshd_config
# デフォルトのまま
Subsystem	sftp	/usr/libexec/openssh/sftp-server

# ファイル末尾にscpuser用のchroot設定を追加
Match User scpuser
 ChrootDirectory /chroot/scpuser
sshdサービスの再起動
sudo systemctl restart sshd

必要なファイル・ディレクトリについては、/usr/libexec配下のファイル・ディレクトリが必要となるため、こちらは他のlib系ディレクトリと同様、bindオプションでマウントしようと思います。

libexec用ディレクトリの作成
sudo mkdir -p /chroot/scpuser/usr/libexec
libexec用ディレクトリのマウント
sudo mount --bind /usr/libexec /chroot/scpuser/usr/libexec

liblib64と同様、/etc/fstabにも記載しておきます。

/etc/fstabに設定する内容
/usr/libexec /chroot/scpuser/usr/libexec        none    bind            0 0

結果として、WinSCPでSFTPSCPともに同じユーザで接続するためにはlibexecのマウントを追加するだけでできました。

これで、scpuserSFTPSCPどちらでもchrootで制限された接続、ファイル転送ができるようになります。

おわりに

SFTPchrootで制限する方法は多くの方が紹介していたため、SCPも同じだろうと軽く考えていたら、まんまとハマりました。

SCPchroot制限については、スバリこの設定をすればOKというような記事は見つからず、当然SFTPSCP両方同じユーザでchroot制限を行って接続するような記事は見当たらなかったため、中々苦労しました。

今回の記事をまとめたことで、chrootの仕組みの復習、SCPSFTPの違いなど、色々と知ることができ、昔ながらの機能ながら新たな発見ができました。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1