私的サーバー構築日誌：公開鍵の送付専用ユーザー

# 能書き

[私的サーバー構築日誌：仕切り直し](https://qiita.com/katz_engineer/items/1f21de2bd9072c260ae6)からの自宅サーバー構築、[前回](https://qiita.com/katz_engineer/items/fe954644fa570093ca3a)の続きです。

[前回はオレオレ認証局で証明書を認証](https://qiita.com/katz_engineer/items/fe954644fa570093ca3a)しまして、公開鍵（及び秘密鍵）を作成できる環境を作りました。

ここで問題になるのが公開鍵の送付です。

セキュリティを鑑みると、最終的には ssh を公開鍵認証するようにしたいのです。しかしその為には、クライアントマシンで作成した公開鍵をサーバーマシンに送付しなければなりません。

USBメモリで物理的に運搬、でも良いのですが一手間掛かります。折角なので電子的に送付できるようにしてスマートな操作を実現したい。

そこで、公開鍵送付専用のユーザーを作成する事にしました。

調べた結果、sftp なら OpenSSH だけあれば構築できるようです。余計なモジュールのインストールは不要。chroot 設定も可能。操作体系は ftp 準拠なので、変なコマンドを実行されてしまう事もありません。

[この問題は以前も取り上げました](https://qiita.com/katz_engineer/items/8c0dcbb985d4493200d2)が、今回はユーザー名などを変更します（単純に、私の好みによります）

## 参考文献

- [自宅サーバー構築譚：公開鍵の送付専用ユーザーを作成 - Qiita](https://qiita.com/katz_engineer/items/8c0dcbb985d4493200d2)
- [鍵とパスワードの認証を混合するsshd_configの設定 - treedown’s Report](https://blog.treedown.net/entry/2017/05/08/010000)
- [SSHでちょっとした設定TIPS - treedown’s Report](https://blog.treedown.net/entry/2017/06/08/010000)
- [OpenSSH : SSH ファイル転送 (Ubuntu)](https://www.server-world.info/query?os=Ubuntu_22.04&p=ssh&f=2)
- [OpenSSH : SFTP only + Chroot](https://www.server-world.info/query?os=Ubuntu_22.04&p=ssh&f=5)
- [Linux にログインできないユーザを作成する - てしりこじり](https://tesiri.hateblo.jp/entry/2014/10/23/111441)
- [SCPとSFTPの違い - OS - クラウド・AWSのIT技術者向けブログ SKYARCH BROADCASTING](https://www.skyarch.net/blog/scp%e3%81%a8sftp%e3%81%ae%e9%81%95%e3%81%84/)
- [sshdのmatchでユーザ単位・アドレス単位でchrootをさせるなど、matchに応じて処理方法を変える - 201703 - Blog -  俺的備忘録 ～なんかいろいろ～](https://orebibou.com/ja/home/201703/20170331_001/)

## 目標

- 公開鍵をsftpで運搬できるようにします。
    - sftp用のユーザーを用意します。
    - ディレクトリなどを用意し、手順を確立します。

# サーバー設定

## スナップショット

スナップショットだいじ。超だいじ。

```console:サーバー
sudo zfs snapshot tank/root/ubuntu@$(date +%Y%m%d_%H%M%S)_before_transporter
```

## ユーザー追加

- ユーザー名は transporter
- ホームディレクトリ無し
- ログイン禁止

上記を踏まえて、下記のコマンドを実行します。ユーザー作成とパスワード設定になります。

```console:サーバー
sudo useradd -s /usr/sbin/nologin -M transporter
```

```console:サーバー
sudo passwd transporter
```

## 追加したユーザーの sftp 設定

transporter は共通鍵の送付専用です。その送付対象となる共通鍵ファイルは```/srv/transport```ディレクトリに置く事とします。異論もおありでしょうけども、私はこう決めました！
と言う訳で皆様それぞれの思想に従って細かい点は調整をお願いします。

下記のコマンドを実行します。

```console:サーバー
sudo mkdir /srv/transport
```

```console:サーバー
cat | sudo tee /etc/ssh/sshd_config.d/transporter.conf >/dev/null <<___
Match User transporter
  X11Forwarding no
  AllowTcpForwarding no
  PermitTTY no
  PasswordAuthentication yes
  ForceCommand internal-sftp
  ChrootDirectory /srv/transport
___
```

ssh 設定ファイルを作成したら```sshd```を再起動します。

```console:サーバー
sudo systemctl restart sshd
```

## ディレクトリ作成

確認用のファイルとディレクトリを準備します。

どうも接続先ディレクトリは root がオーナーで、root 以外の書き込みが禁止されていないと、接続に失敗するようです。従って書き込み確認用にサブディレクトリを用意しておきます。主に公開鍵をやり取りするので```publickey```というディレクトリ名にします。

```console:サーバー
cd /srv/transport
sudo mkdir publickey
```

```console:サーバー
sudo chgrp transporter publickey/
```

```console:サーバー
sudo chmod g+w publickey/
```

こういう場合は権限に注意して確認します。

```console:サーバー
$ ls -l
total 1
drwxrwxr-x 2 root transporter 2 Oct 19 20:14 publickey
```

# 確認

## 接続と転送

実験用に、公開鍵ではないテキストファイルを置きます。

```console:サーバー
cd /srv/transport
echo hello,world | sudo tee hello.txt >/dev/null
```

別マシンからサーバーへtransporterユーザーでssh接続します。私はWin10マシンで実行しました。[primary.homeが私のサーバーマシン名です](https://qiita.com/katz_engineer/items/f2198e5cb7b222d4180e#%E8%A8%AD%E5%AE%9A)。

下記のように、これは失敗します。

```console:クライアント
>ssh transporter@primary.home
transporter@primary.home's password:
PTY allocation request failed on channel 0
This service allows sftp connections only.
Connection to primary.home closed.
```

実は scp も失敗します。解説記事は見つからなかったのですが、どうも ssh 接続できないと scp も出来ないようです。

```console:クライアント
>scp transporter@primary.home:/hello.txt .
transporter@primary.home's password:
protocol error: mtime.sec not present
```

sftp は成功します。

```console:クライアント
>sftp transporter@primary.home
transporter@primary.home's password:
Connected to primary.home.
sftp> pwd
Remote working directory: /
sftp> ls -l
-rw-r--r--    1 root     root           12 Oct 19 11:22 hello.txt
drwxrwxr-x    2 root     1002            2 Oct 19 11:14 publickey
sftp> get hello.txt
Fetching /hello.txt to hello.txt
/hello.txt                                                                            100%   12     0.1KB/s   00:00
sftp> cd publickey
sftp> put hello.txt
Uploading hello.txt to /publickey/hello.txt
hello.txt                                                                             100%   12     0.3KB/s   00:00
sftp> ls -l
-rw-rw-r--    1 1002     1002           12 Oct 19 11:24 hello.txt
sftp> pwd
Remote working directory: /publickey
sftp> exit
```

```put```した```hello.txt```を確認。

```console:サーバー
cd /srv/transport/publickey/
ls -l
```

```hello.txt```が存在する事を確認します。

```console:サーバー
$ cd /srv/transport/publickey/
$ ls -l
total 1
-rw-rw-r-- 1 transporter transporter 12 Oct 19 20:24 hello.txt
```

動作確認が終了したら、不要なファイルは削除しましょう。

```console:サーバー
cd /srv/transport
sudo rm hello.txt
```

```console:サーバー
cd publickey
sudo rm hello.txt
```

# 仕舞い

動作確認できたら```/etc```を Subversion 登録しましょう。

```console:サーバー
sudo svn st /etc | grep "^?" | cut -b9- | sudo xargs -I{} find {} -type f -or -type d -or -type l | sudo xargs -t svn add
sudo svn ci /etc -m"set 'transporter' user"
```

これで、サーバーマシンとクライアントマシンの間で公開鍵を送付する手段を確保できました。