UbuntuでSFTP Chroot Jailを構築する:ユーザー専用ディレクトリを安全に隔離・制限する手順

Ubuntu tutorial - IT technology blog
Ubuntu tutorial - IT technology blog

現場で直面した課題:ファイルアップロードを許可したらシステム全体が丸見えに

半年ほど前、社内チームで外部パートナーとの共同開発案件を担当した際のことです。相手企業から、UbuntuのVPS環境にバックアップデータや画像ファイルを定期的にアップロードするためのアカウントがほしいと要望されました。よくある運用として、ジュニアエンジニアがLinuxアカウントを作成してパスワードを発行し、FileZilla経由でSFTP接続してもらうよう先方に案内しました。

当初は何事もなく運用できているように見えましたが、ある日アクセスログを確認して背筋が凍りました。クライアント側の担当者が興味本位でターミナルからSSHコマンドを叩いたところ、ホームディレクトリから cd /etc で移動でき、ps aux で起動中の全サービスを確認でき、さらにはシステム上の機密性の高い各種設定ファイルまで閲覧できていたのです。root権限がないためファイルの改ざんや破壊はできませんが、外部の第三者がOSのファイル構造内を自由に探索できる状態は、セキュリティ上決して看過できない重大なリスクです。

原因分析:デフォルトのSFTPが抱える構造的仕様

SFTP(SSH File Transfer Protocol)は、本質的にSSH(OpenSSH)の基盤上で動作するサブシステムです。Ubuntu上で通常の手順でユーザーアカウントを作成すると、デフォルトで以下の設定が適用されます。

  • 有効なログインシェル(通常は /bin/bash や /bin/sh)が割り当てられる。
  • /var/log、/etc、/usr など、ほとんどのシステム階層のディレクトリに対して others グループへの読み取り(read)権限が付与されている。

そのため、WinSCPやFileZillaといったSFTPクライアントでログインした場合、ユーザーは「1つ上の階層へ」(..)をクリックするだけでルートディレクトリ / 配下をくまなく参照できてしまいます。さらに、ターミナルから ssh user@ip を実行すれば、一般ユーザー権限を持つ完全なBashセッションが即座に起動してしまいます。

安全にファイルを共有するためのアプローチ比較

「外部からサーバーへのファイルアップロードは許可するが、それ以外のシステムデータを一切閲覧させない」という要件を満たすため、主に3つの選択肢を検討しました。

1. 単体のFTPまたはFTPS(vsftpd)を導入する

最も古典的なアプローチです。vsftpd などをインストールし、local_enable や chroot 機能を有効化します。しかし、追加のポート(21番ポートおよびパッシブポート範囲)の開放が必要になり、ファイアウォール設定が複雑化するほか、VPS上で独立したデーモンプロセスを新たに監視・管理するオーバーヘッドが発生します。

2. WebDAVやオブジェクトストレージサービスを活用する

NextcloudやMinIOをセルフホストするか、S3互換ストレージへ直接アップロードさせる方法です。インフラ設計としては非常にクリーンですが、小規模なユースケースにはオーバースペックであり、従来のFTPクライアントやレガシーな自動化スクリプトでの運用に慣れているパートナー側にとって導入のハードルが高くなります。

3. OpenSSHのSFTP Chroot Jailを活用する

Ubuntu Server標準のOpenSSHをそのまま活用する手法です。ユーザーのアクセス範囲を事前定義した単一のディレクトリ(Chroot Directory)内に閉じ込め、対話型シェルへのアクセス(nologin)を完全に無効化します。ユーザー側からは許可されたディレクトリがサーバー全体のルート / として見え、SSH接続も遮断された状態で安全にファイル転送のみを行えます。

ベストプラクティス:UbuntuでのSFTP Chroot Jail構築手順

筆者はこれまでに20台以上のVPS(Ubuntu Server 22.04)を構築してきましたが、第三者にファイルアップロード権限を付与する際は必ずこの構成を採用しています。標準のOpenSSH以外に追加ソフトウェアをインストールする必要がなく、強固なセキュリティを確保でき、本番環境でも極めて安定して稼働し続けています。

ステップ1:SFTP専用グループの作成

制限対象のユーザーを一括管理できるよう、専用のグループ(例:sftp_users)を作成します。これにより、SSH設定ファイル側で権限を一元管理できます。

sudo groupadd sftp_users

ステップ2:新規ユーザーの作成とログインシェルの無効化

uploaduser という名称で新規ユーザーを作成します。最大のポイントは、ログインシェルに /usr/sbin/nologin(または /bin/false)を指定し、SSHターミナルの起動を完全に遮断することです。

sudo useradd -m -g sftp_users -s /usr/sbin/nologin uploaduser
sudo passwd uploaduser

プロンプトに従い、強固なパスワードを設定してください。

ステップ3:OpenSSHサブシステムの設定

SSHデーモンの設定ファイルを編集します。

sudo nano /etc/ssh/sshd_config

既存の Subsystem sftp 行を探し、internal-sftp に変更します。続けてファイル末尾に、グループ sftp_users 向けの専用設定ブロックを追記します。

# 既存の設定行があればコメントアウトし、以下に変更:
Subsystem sftp internal-sftp

# sshd_configの末尾に追記:
Match Group sftp_users
    ChrootDirectory /var/sftp/%u
    ForceCommand internal-sftp
    X11Forwarding no
    AllowTcpForwarding no
    PasswordAuthentication yes

各設定項目の解説:

  • Match Group sftp_users: このグループに所属する全ユーザーに以下の制限ルールを適用します。
  • ChrootDirectory /var/sftp/%u: ユーザーを /var/sftp/uploaduser に隔離(Chroot)します。変数 %u は接続ユーザー名に自動置換されます。
  • ForceCommand internal-sftp: 認証成功時にsftpハンドラのみを強制実行し、シェルの起動を阻止します。
  • X11Forwarding no および AllowTcpForwarding no: ポートフォワーディングやGUI転送を遮断し、プロキシとしての悪用を防止します。

ステップ4:Chrootディレクトリの権限設定(最重要)

この工程は設定ミスが最も発生しやすく、“Connection reset by peer” や “Permission denied” などの接続エラーの原因になりがちです。OpenSSHの仕様上、以下のセキュリティ要件が厳格に定められています。

ChrootDirectoryに指定するディレクトリの所有者は必ず root でなければならず、root 以外のユーザーにいかなる書き込み権限も与えてはならない。

そのため、最上位の親ディレクトリは root 所有とし、その配下に uploaduser が所有する書き込み用のサブディレクトリ files を作成する構成をとります。

# 隔離用のディレクトリ階層を作成
sudo mkdir -p /var/sftp/uploaduser/files

# Jailの親ディレクトリは所有者をroot:root、権限を755に設定
sudo chown root:root /var/sftp/uploaduser
sudo chmod 755 /var/sftp/uploaduser

# アップロード用サブディレクトリの所有権を対象ユーザーに付与
sudo chown uploaduser:sftp_users /var/sftp/uploaduser/files
sudo chmod 775 /var/sftp/uploaduser/files

ステップ5:設定構文の検証とSSHサービスの再起動

タイポによる設定ミスでサーバーから締め出されるのを防ぐため、SSH再起動前には必ず設定ファイルの構文チェックを実行します。

sudo sshd -t

エラーが出力されなければ、SSHサービスを再起動して設定を反映します。

sudo systemctl restart ssh

ステップ6:接続テストと動作確認

クライアント端末から以下の2つのパターンで動作を検証します。

1. 通常のSSH接続を試行する:

ssh uploaduser@your_server_ip

サーバーから This account is currently not available. と返されるか、即座に接続が切断され、シェルセッションが取得できないことを確認します。

2. SFTPでの接続を試行する:

sftp uploaduser@your_server_ip

正常に接続されたら、カレントディレクトリの挙動を確認してみましょう。

sftp> pwd
Remote working directory: /
sftp> ls
files
sftp> cd ..
sftp> pwd
Remote working directory: /

何度 cd .. を実行しても仮想ルート / より上位には移動できず、アップロード用の files ディレクトリのみが視認できます。これにより、Ubuntuの重要なシステムファイル群は外部パートナーの視線から完全に隔離・保護されます。

Share: