叫ぶうさぎの悪ふざけ

うさぎが目印のWebエンジニアが、得たことや思ったことを言の葉に乗せて叫ぶ場所です。

学習記録:12月4日(火):[sftp] ユーザーの作り方

これは 俺のインプットアウトプット記録 Advent Calendar 2018 の4日目のエントリーです。

以前、sftpユーザーを作って提供する機会があったのですが、意外と情報が少ないことに気づきました。

ファイル転送プロトコルであるsftpですが、Webサーバーへ様々なファイルをアップロードする際など、まだまだ利用されているのが実情だと思います。

また、sftpだけでなく、ftpを利用するシーンもあることですし、この情報は有用なのでは?と思い、手取り足取りsftpユーザーの作り方を解説してみます。

前提

  • ubuntu16で実行
  • Webサーバーへのコンテンツアップ目的
  • アップロードできるディレクトリに制限を設ける
  • sftpユーザー作成にまつわる作業は全てコンソール上から実施

設定の流れ

  • sftp用ユーザー作成
  • ユーザーのグループ設定
  • ssh鍵作成
  • sftpできるディレクトリ制限
  • sftp先を制限する(DocumentRoot配下のみ許可)
  • sftp確認

対象者

  • 提供したサーバーに対し、直接ファイルアップロードのニーズがある方
  • 古いシステムをメンテナンスしている方
  • 鍵認証についてざっくり知りたい方
  • コンソール怖いという方(コワクナイヨ

sftp設定

新規ユーザー作成

  • sample-sftp というユーザーを作ります
$ sudo useradd sample-sftp
$ sudo passwd sample-sftp
新しい UNIX パスワードを入力してください: 
新しい UNIX パスワードを再入力してください: 
passwd: password updated successfully

# ユーザー用のディレクトリを作成
$ sudo mkdir /home/sample-sftp

sftpユーザーのグループ指定

次にsftpユーザーの所属グループを設定します。 今回はnginxで動いているDocumentRootに対し、コンテンツをアップすることが目的なので、条件を以下とします。

  • sftp接続後のディレクトリは変更しない
    • /home/sample-sftp のまま
    • 理由は後述の openssl(chroot)によるディレクトリ制限 のため
# DocumentRootの持ち主であるnginxユーザーをみる
$ id nginx
uid=112(nginx) gid=116(nginx) groups=116(nginx)

# sftpユーザーをnginxのグループに追加する
$ sudo usermod -g 116 sample-sftp

# グループIDを確認する
$ id sample-sftp
uid=1001(sample-sftp) gid=116(nginx) groups=116(nginx)

無事にグループがnginxになりました。

SSH鍵作成

次にsftpで接続するための鍵を作ります。 その前に鍵を保存するディレクトリを作成します。

$ cd /home/sample-sftp
$ pwd
/home/sample-sftp
$ sudo mkdir .ssh
$ sudo chown sample-sftp:sample-sftp .ssh
ubuntu@ip-172-31-47-139:/home/sample-sftp$ ls -la 
合計 12
drwxr-xr-x 3 root        root        4096 124 22:37 .
drwxr-xr-x 4 root        root        4096 124 22:35 ..
drwxr-xr-x 2 sample-sftp sample-sftp 4096 124 22:37 .ssh

次に実際にsftpするユーザーにチェンジし、鍵を作成します。 鍵のファイル名はデフォルト、パスワードは設定しません。

$ su sample-sftp
パスワード:
$ cd .ssh
$ ssh-keygen -t rsa -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (/home/sample-sftp/.ssh/id_rsa): [press enter]
Enter passphrase (empty for no passphrase): [press enter]
Enter same passphrase again: [press enter]
Your identification has been saved in /home/sample-sftp/.ssh/id_rsa.
Your public key has been saved in /home/sample-sftp/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:3YlPDtl7NZ0wX6DbGu5B5Z4+C39amQfQ3GcBg9XjGwk sample-sftp@ip-172-31-47-139
The key's randomart image is:
+---[RSA 4096]----+
|            o++. |
|           . E.=.|
|            oo* B|
|         . = B+==|
|        S = O ++=|
|           B = =+|
|            O +oo|
|           . *..o|
|            . == |
+----[SHA256]-----+

生成された鍵ファイルを確認します。

$ ls -la
合計 20
drwxr-xr-x 2 sample-sftp sample-sftp 4096 124 22:43 .
drwxr-xr-x 3 root        root        4096 124 22:37 ..
-rw------- 1 sample-sftp nginx       3247 124 22:40 id_rsa
-rw-r--r-- 1 sample-sftp nginx        754 124 22:40 id_rsa.pub

次に、公開鍵(ドアノブの鍵穴みたいなもの)を authorized_keys というファイルに転記します。 なお、適切な権限に設定しないと認証に失敗しますので、合わせて設定します。

$ chmod 600 authorized_keys
$ chmod 700 ../.ssh
$ pwd
/home/sample-sftp/.ssh
$ ls -la
合計 20
drwx------ 2 sample-sftp sample-sftp 4096 124 22:43 .
drwxr-xr-x 3 root        root        4096 124 22:37 ..
-rw------- 1 sample-sftp nginx        754 124 22:43 authorized_keys
-rw------- 1 sample-sftp nginx       3247 124 22:40 id_rsa
-rw-r--r-- 1 sample-sftp nginx        754 124 22:40 id_rsa.pub

# suでチェンジしたユーザーからexit
$ exit

sftpできるディレクトリを制限

sftpアカウントで接続した際、ルートからなんでも見れて更新できては何かと困ります。 ゆえに制限をかけていきます。

  • sshd_configはバックアップをとっておき、何かあったらすぐ戻せるように
  • sshd_configに制限を追加
  • 再起動

まずバックアップを作成します。

$ pwd
/etc/ssh
$ sudo cp -rp sshd_config sshd_org_config

ユーザーの制限事項を追加します。

# /etc/ssh/sshd_configを開く
$ sudo vim sshd_config

/etc/ssh/sshd_configにユーザー制限を追加します。 ファイルの末尾に追加しました。

Match User sample-sftp
    ChrootDirectory /home/sample-sftp
    ForceCommand internal-sftp

次にsshを再起動して設定を反映します。

$ sudo /etc/init.d/ssh restart
[ ok ] Restarting ssh (via systemctl): ssh.service.

あと、僕は失敗した時のために、必ずすぐ戻すためのコマンドを先に用意してたりします。

mv sshd_config sshd_config_failed
mv sshd_org_config sshd_config
sudo /etc/init.d/ssh restart

DocumentRootの調整

DocumentRootで直接ファイルを操作されると何かと困(ry 以下の手順で sftpユーザーのhome配下のみ更新できる ように設定していきます。

  • /home/sample-sftp/htdocs の配下にアップロードしてもらう
  • /srv/www/www.mamy1326.jp/htdocs を上記のシンボリックリンクにする
  • これをやることで、 sshd_configに設定したChrootDirectoryの制限を回避できる

/home/sample-sftp/htdocsを作成し、sftp接続で書き込み可能にします。

$ pwd
/home/sample-sftp
$ sudo mkdir htdocs
$ sudo chown sample-sftp:sample-sftp htdocs
$ sudo chmod 755 htdocs
$ ls -la
合計 16
drwxr-xr-x 4 root        root        4096 124 22:57 .
drwxr-xr-x 4 root        root        4096 124 22:35 ..
drwx------ 2 sample-sftp sample-sftp 4096 124 22:43 .ssh
drwxr-xr-x 2 sample-sftp sample-sftp 4096 124 22:57 htdocs

次に、実際のDocumentRootにシンボリックリンクを作成します。

$ pwd
/srv/www/www.mamy1326.jp
$ sudo ln -s /home/sample-sftp/htdocs public
$ ls -la
合計 12
drwxr-xr-x 3 root root 4096 124 23:01 .
drwxr-xr-x 4 root root 4096  97 02:37 ..
lrwxrwxrwx 1 root root   24 124 23:01 public -> /home/sample-sftp/htdocs

sftp実行

これで準備は整いましたので、実際に接続し、意図通りにファイル操作ができるかを確認します。手順は以下です。

  • ローカルから接続
  • 書き込みできることを確認
  • 他のディレクトリに移動できないことを確認
  • sftpのみ(sshできない)ことを確認
  • コンテンツをアップして、DocumentRootにアップされていることを確認する

まずは先ほど作った秘密鍵をサーバーから取得します。 ファイルの設置や、適切な権限設定を実行しておいてください。

$ scp -i mamy1326.pem ubuntu@18.179.206.65://home/ubuntu/id_rsa id_rsa_sample-sftp
id_rsa                                                                                                                              100% 3247    54.4KB/s   00:00 
$ sudo cp id_rsa_sample-sftp ~/.ssh
$ sudo chmod 600 ~/.ssh/id_rsa_sample-sftp
$ ls -la ~/.ssh/id_rsa_sample-sftp
-rw-------   1 mamy1326  staff  3247 12  4 23:06 id_rsa_sample-sftp

準備は整ったので、実際に接続してみます。

$ sftp -i id_rsa_sample-sftp sample-sftp@18.179.206.65
Connected to sample-sftp@18.179.206.65.
sftp> 

無事に接続できたので、色々コマンドを実行してみましょう。

# /home/sample-sftp直下にはアップロードできない(root:rootなので)

# 一覧をみる
sftp> ls -la
drwxr-xr-x    4 0        0            4096 Dec  4 13:57 .
drwxr-xr-x    4 0        0            4096 Dec  4 13:57 ..
drwx------    2 1001     1001         4096 Dec  4 13:43 .ssh
drwxr-xr-x    2 1001     1001         4096 Dec  4 13:57 htdocs

# 場所を確認する。sftpユーザーからみてルートであることがわかる
sftp> pwd
Remote working directory: /

# 権限が与えられていない場所にputすると権限がなくて失敗する
sftp> put sample.pdf                    
Uploading sample.pdf to /sample.pdf
remote open("/sample.pdf"): Permission denied
sftp> 

次に、権限が与えられているディレクトリに移動し、ファイルをputしてみます。

# htdocs配下にはアップできる

sftp> cd htdocs 
sftp> put sample.pdf
Uploading sample.pdf to /htdocs/sample.pdf
sample.pdf                                                                                                                          100% 4007    54.2KB/s   00:00    
sftp> ls -la
drwxr-xr-x    2 1001     1001         4096 Dec  4 14:17 .
drwxr-xr-x    4 0        0            4096 Dec  4 13:57 ..
-rw-r--r--    1 1001     116        614935 Dec  4 14:17 sample.pdf
sftp> pwd
Remote working directory: /htdocs
sftp> 

最後に、実際にDocumentRootにファイルが設置されているか確認します。

$ ls -la /srv/www/www.mamy1326.jp/public/
合計 12
drwxr-xr-x 2 sample-sftp sample-sftp 4096 124 23:17 .
drwxr-xr-x 4 root        root        4096 124 22:57 ..
-rw-r--r-- 1 sample-sftp nginx     614935 124 23:17 sample.pdf

無事にアップされていますね。 これでめでたく、外部の人に制限されたアクセス状態で、DocumentRootを更新 できるようになりました。

Webブラウザから確認

DocumentRootにアップしたので、Webブラウザから見れることを確認しておきます。 そのうちインスタンスを停止しますが、現在こんな感じですね。

f:id:Mamy1326:20181205010630p:plain
さんぷるのPDF

連絡報告

あとはクライアントに、接続情報、鍵ファイル、制限事項などを連絡報告および共有します。 その結果として、クライアントが無事に接続でき、目的を達成できたことを確認して、クライアント向けの作業が完了、となるかと思います。

課題

ブラウザから確認

  • せっかくWebサーバー立てて、ドメイン名をとったので、ブラウザから確認できるようにエントリーに追記します。
    • やりました!

CyberDuck確認

おそらくクライアントは何かしらツールを使うと思うので、設定手順があると便利よね。

ドキュメント整備

実際の業務だと、作って終わりというわけではないと思います。 各種情報や鍵ファイルなどは適切な権限と場所に管理しておきましょう。

  • GoogleDriveにsftp用の鍵を置く
  • 同じくアカウント情報を置く
    • 情報(sftp)
      • IPアドレス
      • ユーザー名
      • 鍵のファイル名
      • 接続方法
      • コンテンツアップ先(フルパス)

やってみて

以上、実際にEC2インスタンスを立て、Webサーバー(nginx)を起動し、実行した結果です。

実際の業務では、単一の作業だけではなく、お客さんへのリリースや連絡、社内でのドキュメント整備など、付随する作業があると思います。

また、なぜそう設定するのか。 理由も含めて手順として残しておけたらいいですよね。

というわけで、僕の個人メモをもう一度再現し、実際に動いた結果といて公開してみました。

もう一度やれと言われたら暗記してる自信は皆無だし、未来の自分が今の自分に必ず感謝すると思うので、積極的に残していきたいですね。